This commit is contained in:
RedKale
2016-02-22 13:50:58 +08:00
parent fad0d69637
commit a4ab83f482
7 changed files with 93 additions and 74 deletions

View File

@@ -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 <group> node info.");
//单向SNCP服务不需要对等group
//if (!sncps.isEmpty() && globalNodes.isEmpty()) throw new RuntimeException("found SNCP Server node but not found <group> node info.");
runServers(timecd, sncps); //必须确保sncp都启动后再启动其他协议
runServers(timecd, others);

View File

@@ -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 <group> info");
//单向SNCP服务不需要对等group
//if (this.sncpGroup == null) throw new RuntimeException("Server (" + String.valueOf(config).replaceAll("\\s+", " ") + ") not found <group> 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("<name> value cannot contains '$' in " + entry.getProperty());
if (resourceFactory.find(entry.getName(), type) != null) continue; //Server加载Service时需要判断是否已经加载过了。
final HashSet<String> groups = entry.getGroups(); //groups.isEmpty()表示<services>没有配置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();

View File

@@ -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<T extends Service> implements Comparable<Servi
private static volatile int maxNameLength = 0;
private final Class<T> type;
private final T service;
private final AnyValue conf;
@@ -39,10 +38,9 @@ public final class ServiceWrapper<T extends Service> implements Comparable<Servi
private final boolean remote;
private final Class[] resTypes;
private final Class[] types;
public ServiceWrapper(Class<T> type, T service, String name, String sncpGroup, Set<String> groups, AnyValue conf) {
this.type = type == null ? (Class<T>) service.getClass() : type;
this.service = service;
this.conf = conf;
this.sncpGroup = sncpGroup;
@@ -50,16 +48,36 @@ public final class ServiceWrapper<T extends Service> implements Comparable<Servi
this.name = name;
this.remote = Sncp.isRemote(service);
ResourceType rty = service.getClass().getAnnotation(ResourceType.class);
this.resTypes = rty == null ? new Class[]{this.type} : rty.value();
this.types = rty == null ? new Class[]{type == null ? (Class<T>) 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<T extends Service> implements Comparable<Servi
if (obj == null) return false;
if (!(obj instanceof ServiceWrapper)) return false;
ServiceWrapper other = (ServiceWrapper) obj;
return (this.type.equals(other.type) && this.remote == other.remote && this.name.equals(other.name) && Objects.equals(this.sncpGroup, other.sncpGroup));
return (this.types[0].equals(other.types[0]) && this.remote == other.remote && this.name.equals(other.name) && Objects.equals(this.sncpGroup, other.sncpGroup));
}
@Override
public int hashCode() {
int hash = 3;
hash = 67 * hash + Objects.hashCode(this.type);
hash = 67 * hash + Objects.hashCode(this.types[0]);
hash = 67 * hash + Objects.hashCode(this.sncpGroup);
hash = 67 * hash + Objects.hashCode(this.name);
hash = 67 * hash + (this.remote ? 1 : 0);
@@ -92,17 +110,13 @@ public final class ServiceWrapper<T extends Service> implements Comparable<Servi
@Override
public int compareTo(ServiceWrapper o) {
int rs = this.type.getName().compareTo(o.type.getName());
int rs = this.types[0].getName().compareTo(o.types[0].getName());
if (rs == 0) rs = this.name.compareTo(o.name);
return rs;
}
public Class<? extends Service> getType() {
return type;
}
public Class[] getResTypes() {
return resTypes;
public Class[] getTypes() {
return types;
}
public Service getService() {

View File

@@ -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());
}
/**

View File

@@ -139,8 +139,8 @@ public final class SncpClient {
protected final Consumer<Runnable> executor;
public <T extends Service> SncpClient(final String serviceName, final Class<T> serviceType, final Consumer<Runnable> executor, boolean remote,
final Class serviceClass, final InetSocketAddress clientAddress) {
public <T extends Service> SncpClient(final String serviceName, final Class<T> serviceType, final Consumer<Runnable> 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<SncpAction> 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();

View File

@@ -36,10 +36,11 @@ public final class SncpServer extends Server<DLong, SncpContext, SncpRequest, Sn
super.init(config);
}
public SncpDynServlet addService(ServiceWrapper entry) {
SncpDynServlet sds = new SncpDynServlet(BsonFactory.root().getConvert(), entry.getName(), entry.getType(), entry.getService());
this.prepare.addServlet(sds, null, entry.getConf());
return sds;
public void addService(ServiceWrapper entry) {
for (Class type : entry.getTypes()) {
SncpDynServlet sds = new SncpDynServlet(BsonFactory.root().getConvert(), entry.getName(), type, entry.getService());
this.prepare.addServlet(sds, null, entry.getConf());
}
}
public List<SncpServlet> getSncpServlets() {

View File

@@ -12,53 +12,53 @@ import java.util.*;
* 16bytes数据结构
* 注意: 为了提高性能, DLong中的bytes是直接返回 不得对bytes的内容进行修改。
*
* <p> 详情见: http://www.redkale.org
* <p>
* 详情见: http://www.redkale.org
*
* @author zhangjx
*/
public final class DLong extends Number implements Comparable<DLong> {
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<DLong> {
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<DLong> {
@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;
}