优化sncp版WebSocketNode

This commit is contained in:
redkale
2023-04-05 22:52:17 +08:00
parent 4bdbf0f493
commit 5746449cfb
5 changed files with 79 additions and 68 deletions

View File

@@ -464,7 +464,7 @@ public abstract class NodeServer {
}
final ResourceTypeLoader resourceLoader = (ResourceFactory rf, String srcResourceName, final Object srcObj, final String resourceName, Field field, final Object attachment) -> {
try {
if (Sncp.loadMethodActions(serviceImplClass).isEmpty()
if (Sncp.loadMethodActions(Sncp.getResourceType(serviceImplClass)).isEmpty()
&& (serviceImplClass.getAnnotation(Priority.class) == null && serviceImplClass.getAnnotation(javax.annotation.Priority.class) == null)) { //class没有可用的方法且没有标记启动优先级的 通常为BaseService
if (!serviceImplClass.getName().startsWith("org.redkale.") && !serviceImplClass.getSimpleName().contains("Base")) {
logger.log(Level.FINE, serviceImplClass + " cannot load because not found less one public non-final method");

View File

@@ -78,8 +78,8 @@ public class NodeSncpServer extends NodeServer {
int maxTypeLength = 0;
int maxNameLength = 0;
for (SncpServlet en : servlets) {
maxNameLength = Math.max(maxNameLength, en.getServiceName().length() + 1);
maxTypeLength = Math.max(maxTypeLength, en.getServiceType().getName().length());
maxNameLength = Math.max(maxNameLength, en.getResourceName().length() + 1);
maxTypeLength = Math.max(maxTypeLength, en.getResourceType().getName().length());
}
for (SncpServlet en : servlets) {
if (sb != null) {
@@ -93,8 +93,8 @@ public class NodeSncpServer extends NodeServer {
private StringBuilder toSimpleString(SncpServlet servlet, int maxTypeLength, int maxNameLength) {
StringBuilder sb = new StringBuilder();
Class serviceType = servlet.getServiceType();
String serviceName = servlet.getServiceName();
Class serviceType = servlet.getResourceType();
String serviceName = servlet.getResourceName();
int size = servlet.getActionSize();
sb.append(SncpServlet.class.getSimpleName()).append(" (type=").append(serviceType.getName());
int len = maxTypeLength - serviceType.getName().length();

View File

@@ -62,7 +62,7 @@ public abstract class Sncp {
boolean remote();
Class type(); //resourceServiceType
Class type(); //serviceType
int index() default 0; //排列顺序, 主要用于Method
}
@@ -83,6 +83,7 @@ public abstract class Sncp {
final List<Method> list = new ArrayList<>();
final List<Method> multis = new ArrayList<>();
final Map<Uint128, Method> actionids = new LinkedHashMap<>();
RedkaleClassLoader.putReflectionPublicMethods(resourceServiceType.getName());
for (final java.lang.reflect.Method method : resourceServiceType.getMethods()) {
if (method.isSynthetic()) {
continue;
@@ -237,10 +238,16 @@ public abstract class Sncp {
ResourceType type = serviceImplClass.getAnnotation(ResourceType.class);
return type != null ? type.value() : serviceImplClass;
}
//
// public static Class getServiceType(Service service) {
// return isSncpDyn(service) && service.getClass().getSimpleName().startsWith("_Dyn") ? service.getClass().getSuperclass() : service.getClass();
// }
public static Class getServiceType(Service service) {
SncpDyn dyn = service.getClass().getAnnotation(SncpDyn.class);
return dyn != null ? dyn.type() : service.getClass();
}
public static <T extends Service> Class getServiceType(Class<T> serviceImplClass) {
SncpDyn dyn = serviceImplClass.getAnnotation(SncpDyn.class);
return dyn != null ? dyn.type() : serviceImplClass;
}
public static AnyValue getResourceConf(Service service) {
if (service == null || !isSncpDyn(service)) {
@@ -456,7 +463,7 @@ public abstract class Sncp {
{
av0 = cw.visitAnnotation(sncpDynDesc, true);
av0.visit("remote", Boolean.FALSE);
av0.visit("type", Type.getType(Type.getDescriptor(getResourceType(serviceImplClass))));
av0.visit("type", Type.getType(Type.getDescriptor(serviceImplClass)));
av0.visitEnd();
}
{ //给新类加上原有的Annotation
@@ -663,18 +670,27 @@ public abstract class Sncp {
if (!java.lang.reflect.Modifier.isPublic(mod)) {
return null;
}
final SncpRemoteInfo info = createSncpRemoteInfo(name, serviceTypeOrImplClass, serviceTypeOrImplClass, BsonConvert.root(), sncpRpcGroups, client, agent, remoteGroup);
final SncpRemoteInfo info = createSncpRemoteInfo(name, getResourceType(serviceTypeOrImplClass), serviceTypeOrImplClass, BsonConvert.root(), sncpRpcGroups, client, agent, remoteGroup);
final String supDynName = serviceTypeOrImplClass.getName().replace('.', '/');
final String clientName = SncpClient.class.getName().replace('.', '/');
final String sncpInfoName = SncpRemoteInfo.class.getName().replace('.', '/');
final String resDesc = Type.getDescriptor(Resource.class);
final String sncpInfoDesc = Type.getDescriptor(SncpRemoteInfo.class);
final String clientDesc = Type.getDescriptor(SncpClient.class);
final String sncpDynDesc = Type.getDescriptor(SncpDyn.class);
final String anyValueDesc = Type.getDescriptor(AnyValue.class);
final ClassLoader loader = classLoader == null ? Thread.currentThread().getContextClassLoader() : classLoader;
//final String newDynName = supDynName.substring(0, supDynName.lastIndexOf('/') + 1) + REMOTEPREFIX + serviceTypeOrImplClass.getSimpleName();
final String newDynName = "org/redkaledyn/service/remote/_DynRemoteService__" + serviceTypeOrImplClass.getName().replace('.', '_').replace('$', '_');
String newDynName = "org/redkaledyn/service/remote/_DynRemoteService__" + serviceTypeOrImplClass.getName().replace('.', '_').replace('$', '_');
if (!name.isEmpty()) {
boolean normal = true;
for (char ch : name.toCharArray()) {
if (!((ch >= '0' && ch <= '9') || ch == '_' || (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'))) {
normal = false;
}
}
if (!normal) {
throw new SncpException(serviceTypeOrImplClass + "'s resource name is illegal, must be 0-9 _ a-z A-Z");
}
newDynName += "_" + (normal ? name : hash(name));
}
try {
Class clz = RedkaleClassLoader.findDynClass(newDynName.replace('/', '.'));
Class newClazz = clz == null ? loader.loadClass(newDynName.replace('/', '.')) : clz;
@@ -774,15 +790,7 @@ public abstract class Sncp {
// mv.visitMaxs(1, 1);
// mv.visitEnd();
// }
int i = -1;
Uint128 serviceid = serviceid(name, serviceTypeOrImplClass);
final List<SncpRemoteAction> serviceActions = new ArrayList<>();
Class serviceImpClass = realed ? createLocalServiceClass(loader, name, serviceTypeOrImplClass) : serviceTypeOrImplClass;
for (Map.Entry<Uint128, Method> en : loadMethodActions(serviceImpClass).entrySet()) {
serviceActions.add(new SncpRemoteAction(serviceImpClass, en.getValue(), serviceid, en.getKey()));
}
for (final SncpRemoteAction entry : serviceActions) {
final int index = ++i;
for (final SncpRemoteAction entry : info.getActions()) {
final java.lang.reflect.Method method = entry.method;
{
mv = new MethodDebugVisitor(cw.visitMethod(ACC_PUBLIC, method.getName(), Type.getMethodDescriptor(method), null, null));
@@ -798,7 +806,7 @@ public abstract class Sncp {
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, newDynName, FIELDPREFIX + "_sncp", sncpInfoDesc);
MethodDebugVisitor.pushInt(mv, index);
mv.visitLdcInsn(entry.actionid.toString());
{ //传参数
int paramlen = entry.paramTypes.length;
@@ -830,7 +838,7 @@ public abstract class Sncp {
}
}
mv.visitMethodInsn(INVOKEVIRTUAL, sncpInfoName, "remote", "(I[Ljava/lang/Object;)Ljava/lang/Object;", false);
mv.visitMethodInsn(INVOKEVIRTUAL, sncpInfoName, "remote", "(Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/Object;", false);
//mv.visitMethodInsn(INVOKEVIRTUAL, convertName, "convertFrom", convertFromDesc, false);
if (method.getGenericReturnType() == void.class) {
mv.visitInsn(POP);

View File

@@ -44,7 +44,8 @@ public class SncpRemoteInfo<T extends Service> {
protected final int serviceVersion;
protected final SncpRemoteAction[] actions;
//key: actionid.Uint128.toString()
protected final Map<String, SncpRemoteAction> actions = new HashMap<>();
//非MQ模式下此字段才有值
protected final SncpRpcGroups sncpRpcGroups;
@@ -86,16 +87,14 @@ public class SncpRemoteInfo<T extends Service> {
this.messageClient = messageAgent == null ? null : messageAgent.getSncpMessageClient();
this.topic = messageAgent == null ? null : messageAgent.generateSncpReqTopic(resourceName, resourceType);
final List<SncpRemoteAction> serviceActions = new ArrayList<>();
for (Map.Entry<Uint128, Method> en : loadMethodActions(resourceType).entrySet()) {
serviceActions.add(new SncpRemoteAction(serviceImplClass, en.getValue(), serviceid, en.getKey()));
for (Map.Entry<Uint128, Method> en : loadMethodActions(Sncp.getServiceType(serviceImplClass)).entrySet()) {
this.actions.put(en.getKey().toString(), new SncpRemoteAction(serviceImplClass, en.getValue(), serviceid, en.getKey()));
}
this.actions = serviceActions.toArray(new SncpRemoteAction[serviceActions.size()]);
}
//由远程模式的DyncRemoveService调用
public <T> T remote(final int index, final Object... params) {
final SncpRemoteAction action = this.actions[index];
public <T> T remote(final String actionid, final Object... params) {
final SncpRemoteAction action = this.actions.get(actionid);
CompletionHandler callbackHandler = null;
Object callbackHandlerAttach = null;
if (action.paramHandlerIndex >= 0) {
@@ -249,7 +248,7 @@ public class SncpRemoteInfo<T extends Service> {
return this.getClass().getSimpleName() + "(service = " + serviceType.getSimpleName() + ", serviceid = " + serviceid
+ ", serviceVersion = " + serviceVersion + ", name = '" + name
+ "', address = " + (clientSncpAddress == null ? "" : (clientSncpAddress.getHostString() + ":" + clientSncpAddress.getPort()))
+ ", actions.size = " + actions.length + ")";
+ ", actions.size = " + actions.size() + ")";
}
public String toSimpleString() { //给Sncp产生的Service用
@@ -257,7 +256,7 @@ public class SncpRemoteInfo<T extends Service> {
return serviceType.getSimpleName() + "(name = '" + name + "', serviceid = " + serviceid + ", serviceVersion = " + serviceVersion
+ ", clientaddr = " + (clientSncpAddress == null ? "" : (clientSncpAddress.getHostString() + ":" + clientSncpAddress.getPort()))
+ ((remoteGroup == null || remoteGroup.isEmpty()) ? "" : ", remoteGroup = " + remoteGroup)
+ ", actions.size = " + actions.length + ")";
+ ", actions.size = " + actions.size() + ")";
}
public void updateRemoteAddress(String remoteGroup, Set<InetSocketAddress> remoteAddresses) {
@@ -282,7 +281,7 @@ public class SncpRemoteInfo<T extends Service> {
}
public SncpRemoteAction[] getActions() {
return actions;
return actions.values().toArray(new SncpRemoteAction[actions.size()]);
}
public String getTopic() {

View File

@@ -31,9 +31,9 @@ import org.redkale.util.*;
*/
public class SncpServlet extends Servlet<SncpContext, SncpRequest, SncpResponse> implements Comparable<SncpServlet> {
protected final Class serviceType;
protected final Class resourceType;
protected final String serviceName;
protected final String resourceName;
protected final Service service;
@@ -42,24 +42,25 @@ public class SncpServlet extends Servlet<SncpContext, SncpRequest, SncpResponse>
private final HashMap<Uint128, SncpActionServlet> actions = new HashMap<>();
private SncpServlet(String resourceName, Class resourceType, Service service, Uint128 serviceid) {
this.serviceName = resourceName;
this.serviceType = resourceType;
this.resourceName = resourceName;
this.resourceType = resourceType;
this.service = service;
this.serviceid = serviceid;
}
protected SncpServlet(String resourceName, Class resourceType, Service service) {
this.serviceName = resourceName;
this.serviceType = resourceType;
this.resourceName = resourceName;
this.resourceType = resourceType;
this.service = service;
this._nonBlocking = true;
this.serviceid = Sncp.serviceid(resourceName, resourceType);
RedkaleClassLoader.putReflectionPublicMethods(service.getClass().getName());
for (Map.Entry<Uint128, Method> en : Sncp.loadMethodActions(resourceType).entrySet()) {
Class serviceImplClass = Sncp.getServiceType(service);
RedkaleClassLoader.putReflectionPublicMethods(serviceImplClass.getName());
for (Map.Entry<Uint128, Method> en : Sncp.loadMethodActions(serviceImplClass).entrySet()) {
SncpActionServlet action;
try {
action = SncpActionServlet.create(resourceName, resourceType, service, serviceid, en.getKey(), en.getValue());
action = SncpActionServlet.create(resourceName, resourceType, serviceImplClass, service, serviceid, en.getKey(), en.getValue());
} catch (RuntimeException e) {
throw new SncpException(en.getValue() + " create " + SncpActionServlet.class.getSimpleName() + " error", e);
}
@@ -103,8 +104,8 @@ public class SncpServlet extends Servlet<SncpContext, SncpRequest, SncpResponse>
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(this.getClass().getSimpleName()).append(" (type=").append(serviceType.getName());
sb.append(", serviceid=").append(serviceid).append(", name='").append(serviceName).append("'");
sb.append(this.getClass().getSimpleName()).append(" (type=").append(resourceType.getName());
sb.append(", serviceid=").append(serviceid).append(", name='").append(resourceName).append("'");
sb.append(", actions.size=").append(actions.size() > 9 ? "" : " ").append(actions.size()).append(")");
return sb.toString();
}
@@ -113,12 +114,12 @@ public class SncpServlet extends Servlet<SncpContext, SncpRequest, SncpResponse>
return service;
}
public String getServiceName() {
return serviceName;
public String getResourceName() {
return resourceName;
}
public Class getServiceType() {
return serviceType;
public Class getResourceType() {
return resourceType;
}
public Uint128 getServiceid() {
@@ -136,20 +137,20 @@ public class SncpServlet extends Servlet<SncpContext, SncpRequest, SncpResponse>
}
SncpServlet o = other;
int rs = 0;
if (this.serviceType == null) {
rs = o.serviceType == null ? 0 : -1;
} else if (o.serviceType == null) {
if (this.resourceType == null) {
rs = o.resourceType == null ? 0 : -1;
} else if (o.resourceType == null) {
rs = 1;
} else {
rs = this.serviceType.getName().compareTo(o.serviceType.getName());
rs = this.resourceType.getName().compareTo(o.resourceType.getName());
}
if (rs == 0) {
if (this.serviceName == null) {
rs = o.serviceName == null ? 0 : -1;
} else if (o.serviceName == null) {
if (this.resourceName == null) {
rs = o.resourceName == null ? 0 : -1;
} else if (o.resourceName == null) {
rs = 1;
} else {
rs = this.serviceName.compareTo(o.serviceName);
rs = this.resourceName.compareTo(o.resourceName);
}
}
return rs;
@@ -424,12 +425,13 @@ public class SncpServlet extends Servlet<SncpContext, SncpRequest, SncpResponse>
*
* </pre></blockquote>
*
* @param resourceName 资源名
* @param resourceType 资源类
* @param service Service
* @param serviceid 类ID
* @param actionid 操作ID
* @param method 方法
* @param resourceName 资源名
* @param resourceType 资源类
* @param serviceImplClass Service实现类
* @param service Service
* @param serviceid ID
* @param actionid 操作ID
* @param method 方法
*
* @return SncpActionServlet
*/
@@ -437,6 +439,7 @@ public class SncpServlet extends Servlet<SncpContext, SncpRequest, SncpResponse>
public static SncpActionServlet create(
final String resourceName,
final Class resourceType,
final Class serviceImplClass,
final Service service,
final Uint128 serviceid,
final Uint128 actionid,
@@ -445,6 +448,7 @@ public class SncpServlet extends Servlet<SncpContext, SncpRequest, SncpResponse>
final Class serviceClass = service.getClass();
final String supDynName = SncpActionServlet.class.getName().replace('.', '/');
final String resourceTypeName = resourceType.getName().replace('.', '/');
final String serviceImpTypeName = serviceImplClass.getName().replace('.', '/');
final String convertName = Convert.class.getName().replace('.', '/');
final String uint128Desc = Type.getDescriptor(Uint128.class);
final String convertDesc = Type.getDescriptor(Convert.class);
@@ -594,14 +598,14 @@ public class SncpServlet extends Servlet<SncpContext, SncpRequest, SncpResponse>
{ //调用service
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKEVIRTUAL, newDynName, "service", "()Lorg/redkale/service/Service;", false);
mv.visitTypeInsn(CHECKCAST, resourceTypeName);
mv.visitTypeInsn(CHECKCAST, serviceImpTypeName);
mv.visitVarInsn(ASTORE, store);
mv.visitVarInsn(ALOAD, store);
for (int[] j : codes) {
mv.visitVarInsn(j[0], j[1]);
}
mv.visitMethodInsn(resourceType.isInterface() ? INVOKEINTERFACE : INVOKEVIRTUAL, resourceTypeName, method.getName(), Type.getMethodDescriptor(method), resourceType.isInterface());
mv.visitMethodInsn(resourceType.isInterface() ? INVOKEINTERFACE : INVOKEVIRTUAL, serviceImpTypeName, method.getName(), Type.getMethodDescriptor(method), resourceType.isInterface());
store++;
}
if (method.getReturnType() != void.class) {