diff --git a/src/org/redkale/boot/Application.java b/src/org/redkale/boot/Application.java index 72a7db391..f7aa562ed 100644 --- a/src/org/redkale/boot/Application.java +++ b/src/org/redkale/boot/Application.java @@ -434,7 +434,8 @@ public final class Application { others.add(entry); } } - if (!sncps.isEmpty() && globalNodes.isEmpty()) throw new RuntimeException("found SNCP Server node but not found node info."); + //单向SNCP服务不需要对等group + //if (!sncps.isEmpty() && globalNodes.isEmpty()) throw new RuntimeException("found SNCP Server node but not found node info."); runServers(timecd, sncps); //必须确保sncp都启动后再启动其他协议 runServers(timecd, others); diff --git a/src/org/redkale/boot/NodeServer.java b/src/org/redkale/boot/NodeServer.java index 161e99519..be1e93766 100644 --- a/src/org/redkale/boot/NodeServer.java +++ b/src/org/redkale/boot/NodeServer.java @@ -119,7 +119,8 @@ public abstract class NodeServer { String host = this.serverConf.getValue("host", "0.0.0.0").replace("0.0.0.0", ""); this.sncpAddress = new InetSocketAddress(host.isEmpty() ? application.localAddress.getHostAddress() : host, this.serverConf.getIntValue("port")); this.sncpGroup = application.globalNodes.get(this.sncpAddress); - if (this.sncpGroup == null) throw new RuntimeException("Server (" + String.valueOf(config).replaceAll("\\s+", " ") + ") not found info"); + //单向SNCP服务不需要对等group + //if (this.sncpGroup == null) throw new RuntimeException("Server (" + String.valueOf(config).replaceAll("\\s+", " ") + ") not found info"); } if (this.sncpAddress != null) this.resourceFactory.register(RESNAME_SERVER_ADDR, this.sncpAddress); //单点服务不会有 sncpAddress、sncpGroup @@ -137,7 +138,7 @@ public abstract class NodeServer { resourceFactory.register(Server.RESNAME_SERVER_ROOT, Path.class, myroot.toPath()); final String homepath = myroot.getCanonicalPath(); - Server.loadLib(logger, config.getValue("lib", "") + ";" + homepath + "/lib/*;" + homepath + "/classes"); + Server.loadLib(logger, config.getValue("lib", "").replace("${APP_HOME}", homepath) + ";" + homepath + "/lib/*;" + homepath + "/classes"); if (server != null) server.init(config); } @@ -272,7 +273,7 @@ public abstract class NodeServer { if (entry.getName().contains("$")) throw new RuntimeException(" value cannot contains '$' in " + entry.getProperty()); if (resourceFactory.find(entry.getName(), type) != null) continue; //Server加载Service时需要判断是否已经加载过了。 final HashSet groups = entry.getGroups(); //groups.isEmpty()表示没有配置groups属性。 - if (groups.isEmpty() && isSNCP()) groups.add(this.sncpGroup); + if (groups.isEmpty() && isSNCP() && this.sncpGroup != null) groups.add(this.sncpGroup); final boolean localed = (this.sncpAddress == null && !type.isInterface() && !Modifier.isAbstract(type.getModifiers())) //非SNCP的Server,通常是单点服务 || groups.contains(this.sncpGroup) //本地IP含在内的 @@ -286,16 +287,18 @@ public abstract class NodeServer { service = Sncp.createRemoteService(entry.getName(), getExecutor(), type, this.sncpAddress, loadTransport(groups)); } final ServiceWrapper wrapper = new ServiceWrapper(type, service, entry.getName(), localed ? this.sncpGroup : null, groups, entry.getProperty()); - if (resourceFactory.find(wrapper.getName(), wrapper.getType()) == null) { - regFactory.register(wrapper.getName(), wrapper.getService()); - if (wrapper.isRemote()) { - remoteServiceWrappers.add(wrapper); - } else { - localServiceWrappers.add(wrapper); - if (consumer != null) consumer.accept(wrapper); + for (final Class restype : wrapper.getTypes()) { + if (resourceFactory.find(wrapper.getName(), restype) == null) { + regFactory.register(wrapper.getName(), restype, wrapper.getService()); + } else if (isSNCP() && !entry.isAutoload()) { + throw new RuntimeException(ServiceWrapper.class.getSimpleName() + "(class:" + type.getName() + ", name:" + entry.getName() + ", group:" + groups + ") is repeat."); } - } else if (isSNCP() && !entry.isAutoload()) { - throw new RuntimeException(ServiceWrapper.class.getSimpleName() + "(class:" + type.getName() + ", name:" + entry.getName() + ", group:" + groups + ") is repeat."); + } + if (wrapper.isRemote()) { + remoteServiceWrappers.add(wrapper); + } else { + localServiceWrappers.add(wrapper); + if (consumer != null) consumer.accept(wrapper); } } application.servicecdl.countDown(); diff --git a/src/org/redkale/net/sncp/ServiceWrapper.java b/src/org/redkale/net/sncp/ServiceWrapper.java index 8ff3632df..4a50c4028 100644 --- a/src/org/redkale/net/sncp/ServiceWrapper.java +++ b/src/org/redkale/net/sncp/ServiceWrapper.java @@ -8,6 +8,7 @@ package org.redkale.net.sncp; import org.redkale.service.Service; import org.redkale.util.AnyValue; import java.util.*; +import java.util.stream.*; import org.redkale.util.*; /** @@ -25,8 +26,6 @@ public final class ServiceWrapper implements Comparable type; - private final T service; private final AnyValue conf; @@ -39,10 +38,9 @@ public final class ServiceWrapper implements Comparable type, T service, String name, String sncpGroup, Set groups, AnyValue conf) { - this.type = type == null ? (Class) service.getClass() : type; this.service = service; this.conf = conf; this.sncpGroup = sncpGroup; @@ -50,16 +48,36 @@ public final class ServiceWrapper implements Comparable) service.getClass() : type} : rty.value(); maxNameLength = Math.max(maxNameLength, name.length()); - maxClassNameLength = Math.max(maxClassNameLength, type.getName().length() + 1); + StringBuilder s = new StringBuilder(); + if (this.types.length == 1) { + s.append(types[0].getName()); + } else { + s.append('['); + s.append(Arrays.asList(this.types).stream().map((Class t) -> t.getName()).collect(Collectors.joining(","))); + s.append(']'); + } + maxClassNameLength = Math.max(maxClassNameLength, s.length() + 1); } public String toSimpleString() { StringBuilder sb = new StringBuilder(); - sb.append(remote ? "RemoteService" : "LocalService ").append("(type=").append(type.getName()); - int len = maxClassNameLength - type.getName().length(); + sb.append(remote ? "RemoteService" : "LocalService "); + int len; + if (types.length == 1) { + sb.append("(type= ").append(types[0].getName()); + len = maxClassNameLength - types[0].getName().length(); + } else { + StringBuilder s = new StringBuilder(); + s.append('['); + s.append(Arrays.asList(this.types).stream().map((Class t) -> t.getName()).collect(Collectors.joining(","))); + s.append(']'); + sb.append("(types=").append(s); + len = maxClassNameLength - s.length(); + } + for (int i = 0; i < len; i++) { sb.append(' '); } @@ -77,13 +95,13 @@ public final class ServiceWrapper implements Comparable implements Comparable getType() { - return type; - } - - public Class[] getResTypes() { - return resTypes; + public Class[] getTypes() { + return types; } public Service getService() { diff --git a/src/org/redkale/net/sncp/Sncp.java b/src/org/redkale/net/sncp/Sncp.java index 9d07ac0cc..27b50a267 100644 --- a/src/org/redkale/net/sncp/Sncp.java +++ b/src/org/redkale/net/sncp/Sncp.java @@ -57,19 +57,20 @@ public abstract class Sncp { return ((0L + ip.getPort()) << 32) | ((0xffffffff & bytes[0]) << 24) | ((0xffffff & bytes[1]) << 16) | ((0xffff & bytes[2]) << 8) | (0xff & bytes[3]); } - public static DLong hash(final Class clazz) { - if (clazz == null) return DLong.ZERO; - return hash(clazz.getName()); - } - - public static DLong hashClass(final String clazzName) { - if (clazzName == null || clazzName.isEmpty()) return DLong.ZERO; - return hash(clazzName); - } - public static DLong hash(final java.lang.reflect.Method method) { if (method == null) return DLong.ZERO; - return hash(method.toString()); + StringBuilder sb = new StringBuilder(); //不能使用method.toString() 因为包含declaringClass信息导致接口与实现类的方法hash不一致 + sb.append(method.getReturnType().getName()).append(' '); + sb.append(method.getName()); + sb.append('('); + boolean first = true; + for (Class pt : method.getParameterTypes()) { + if (!first) sb.append(','); + sb.append(pt.getName()); + first = false; + } + sb.append(')'); + return hash(sb.toString()); } /** diff --git a/src/org/redkale/net/sncp/SncpClient.java b/src/org/redkale/net/sncp/SncpClient.java index 8aa29f612..f63662f7c 100644 --- a/src/org/redkale/net/sncp/SncpClient.java +++ b/src/org/redkale/net/sncp/SncpClient.java @@ -139,8 +139,8 @@ public final class SncpClient { protected final Consumer executor; - public SncpClient(final String serviceName, final Class serviceType, final Consumer executor, boolean remote, - final Class serviceClass, final InetSocketAddress clientAddress) { + public SncpClient(final String serviceName, final Class serviceType, final Consumer executor, + final boolean remote, final Class serviceClass, final InetSocketAddress clientAddress) { this.remote = remote; this.executor = executor; this.serviceClass = serviceClass; @@ -150,8 +150,7 @@ public final class SncpClient { final List methodens = new ArrayList<>(); //------------------------------------------------------------------------------ for (java.lang.reflect.Method method : parseMethod(serviceClass)) { - SncpAction en = new SncpAction(method, Sncp.hash(method)); - methodens.add(en); + methodens.add(new SncpAction(method, Sncp.hash(method))); } this.actions = methodens.toArray(new SncpAction[methodens.size()]); this.addrBytes = clientAddress == null ? new byte[4] : clientAddress.getAddress().getAddress(); diff --git a/src/org/redkale/net/sncp/SncpServer.java b/src/org/redkale/net/sncp/SncpServer.java index 07ead6b0a..f35862e85 100644 --- a/src/org/redkale/net/sncp/SncpServer.java +++ b/src/org/redkale/net/sncp/SncpServer.java @@ -36,10 +36,11 @@ public final class SncpServer extends Server getSncpServlets() { diff --git a/src/org/redkale/util/DLong.java b/src/org/redkale/util/DLong.java index 376ea3122..d3714f044 100644 --- a/src/org/redkale/util/DLong.java +++ b/src/org/redkale/util/DLong.java @@ -12,53 +12,53 @@ import java.util.*; * 16bytes数据结构 * 注意: 为了提高性能, DLong中的bytes是直接返回, 不得对bytes的内容进行修改。 * - *

详情见: http://www.redkale.org + *

+ * 详情见: http://www.redkale.org + * * @author zhangjx */ public final class DLong extends Number implements Comparable { public static final DLong ZERO = new DLong(new byte[16]); - protected final byte[] bytes; + protected final byte[] value; protected DLong(long v1, long v2) { //暂时不用 - this.bytes = new byte[]{(byte) (v1 >> 56), (byte) (v1 >> 48), (byte) (v1 >> 40), (byte) (v1 >> 32), + this.value = new byte[]{(byte) (v1 >> 56), (byte) (v1 >> 48), (byte) (v1 >> 40), (byte) (v1 >> 32), (byte) (v1 >> 24), (byte) (v1 >> 16), (byte) (v1 >> 8), (byte) v1, (byte) (v2 >> 56), (byte) (v2 >> 48), (byte) (v2 >> 40), (byte) (v2 >> 32), (byte) (v2 >> 24), (byte) (v2 >> 16), (byte) (v2 >> 8), (byte) v2}; } protected DLong(byte[] bytes) { if (bytes == null || bytes.length != 16) throw new NumberFormatException("Not 16 length bytes"); - this.bytes = bytes; + this.value = bytes; } public byte[] getBytes() { - return Arrays.copyOf(bytes, bytes.length); + return Arrays.copyOf(value, value.length); } public byte[] directBytes() { - return bytes; + return value; } public static DLong create(byte[] bytes) { - if (ZERO.equals(bytes)) return ZERO; return new DLong(bytes); } public static DLong read(ByteBuffer buffer) { byte[] bs = new byte[16]; buffer.get(bs); - if (ZERO.equals(bs)) return ZERO; return new DLong(bs); } - public static ByteBuffer write(ByteBuffer buffer, DLong value) { - buffer.put(value.bytes); + public static ByteBuffer write(ByteBuffer buffer, DLong dlong) { + buffer.put(dlong.value); return buffer; } public boolean equals(byte[] bytes) { - return Arrays.equals(this.bytes, bytes); + return Arrays.equals(this.value, bytes); } @Override @@ -66,35 +66,35 @@ public final class DLong extends Number implements Comparable { if (obj == null) return false; if (getClass() != obj.getClass()) return false; final DLong other = (DLong) obj; - return Arrays.equals(this.bytes, other.bytes); + return Arrays.equals(this.value, other.value); } @Override public int hashCode() { - return Arrays.hashCode(bytes); + return Arrays.hashCode(value); } @Override public String toString() { if (this == ZERO) return "0"; - return new String(Utility.binToHex(bytes)); + return new String(Utility.binToHex(value)); } @Override public int intValue() { - return ((bytes[12] & 0xff) << 24) | ((bytes[113] & 0xff) << 16) | ((bytes[14] & 0xff) << 8) | (bytes[15] & 0xff); + return ((value[12] & 0xff) << 24) | ((value[113] & 0xff) << 16) | ((value[14] & 0xff) << 8) | (value[15] & 0xff); } @Override public long longValue() { - return ((((long) bytes[8] & 0xff) << 56) - | (((long) bytes[9] & 0xff) << 48) - | (((long) bytes[10] & 0xff) << 40) - | (((long) bytes[11] & 0xff) << 32) - | (((long) bytes[12] & 0xff) << 24) - | (((long) bytes[13] & 0xff) << 16) - | (((long) bytes[14] & 0xff) << 8) - | (((long) bytes[15] & 0xff))); + return ((((long) value[8] & 0xff) << 56) + | (((long) value[9] & 0xff) << 48) + | (((long) value[10] & 0xff) << 40) + | (((long) value[11] & 0xff) << 32) + | (((long) value[12] & 0xff) << 24) + | (((long) value[13] & 0xff) << 16) + | (((long) value[14] & 0xff) << 8) + | (((long) value[15] & 0xff))); } @Override @@ -110,8 +110,8 @@ public final class DLong extends Number implements Comparable { @Override public int compareTo(DLong o) { if (o == null) return 1; - for (int i = 0; i < bytes.length; i++) { - if (this.bytes[i] != o.bytes[i]) return this.bytes[i] - o.bytes[i]; + for (int i = 0; i < value.length; i++) { + if (this.value[i] != o.value[i]) return this.value[i] - o.value[i]; } return 0; }