Java 从零开始手写 RPC—Reflect 反射实现通用调用之服务端

开发 后端
前面我们的例子是一个固定的出参和入参,固定的方法实现。本节将实现通用的调用,让框架具有更广泛的实用性。

[[430216]]

前面我们的例子是一个固定的出参和入参,固定的方法实现。

本节将实现通用的调用,让框架具有更广泛的实用性。

基本思路

所有的方法调用,基于反射进行相关处理实现。

[[430217]]

服务端

核心类

  • RpcServer

调整如下:

  1. serverBootstrap.group(workerGroup, bossGroup) 
  2.     .channel(NioServerSocketChannel.class) 
  3.     // 打印日志 
  4.     .handler(new LoggingHandler(LogLevel.INFO)) 
  5.     .childHandler(new ChannelInitializer<Channel>() { 
  6.         @Override 
  7.         protected void initChannel(Channel ch) throws Exception { 
  8.             ch.pipeline() 
  9.             // 解码 bytes=>resp 
  10.             .addLast(new ObjectDecoder(Integer.MAX_VALUE, ClassResolvers.cacheDisabled(null))) 
  11.              // request=>bytes 
  12.              .addLast(new ObjectEncoder()) 
  13.              .addLast(new RpcServerHandler()); 
  14.         } 
  15.     }) 
  16.     // 这个参数影响的是还没有被accept 取出的连接 
  17.     .option(ChannelOption.SO_BACKLOG, 128) 
  18.     // 这个参数只是过一段时间内客户端没有响应,服务端会发送一个 ack 包,以判断客户端是否还活着。 
  19.     .childOption(ChannelOption.SO_KEEPALIVE, true); 

其中 ObjectDecoder 和 ObjectEncoder 都是 netty 内置的实现。

RpcServerHandler

  1. package com.github.houbb.rpc.server.handler; 
  2.  
  3.  
  4. import com.github.houbb.log.integration.core.Log; 
  5. import com.github.houbb.log.integration.core.LogFactory; 
  6. import com.github.houbb.rpc.common.rpc.domain.RpcRequest; 
  7. import com.github.houbb.rpc.common.rpc.domain.impl.DefaultRpcResponse; 
  8. import com.github.houbb.rpc.server.service.impl.DefaultServiceFactory; 
  9. import io.netty.channel.ChannelHandlerContext; 
  10. import io.netty.channel.SimpleChannelInboundHandler; 
  11.  
  12.  
  13. /** 
  14.  * @author binbin.hou 
  15.  * @since 0.0.1 
  16.  */ 
  17. public class RpcServerHandler extends SimpleChannelInboundHandler { 
  18.  
  19.  
  20.     private static final Log log = LogFactory.getLog(RpcServerHandler.class); 
  21.  
  22.  
  23.     @Override 
  24.     public void channelActive(ChannelHandlerContext ctx) throws Exception { 
  25.         final String id = ctx.channel().id().asLongText(); 
  26.         log.info("[Server] channel {} connected " + id); 
  27.     } 
  28.  
  29.  
  30.     @Override 
  31.     protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception { 
  32.         final String id = ctx.channel().id().asLongText(); 
  33.         log.info("[Server] channel read start: {}", id); 
  34.  
  35.  
  36.         // 接受客户端请求 
  37.         RpcRequest rpcRequest = (RpcRequest)msg; 
  38.         log.info("[Server] receive channel {} request: {}", id, rpcRequest); 
  39.  
  40.  
  41.         // 回写到 client 端 
  42.         DefaultRpcResponse rpcResponse = handleRpcRequest(rpcRequest); 
  43.         ctx.writeAndFlush(rpcResponse); 
  44.         log.info("[Server] channel {} response {}", id, rpcResponse); 
  45.     } 
  46.  
  47.  
  48.     @Override 
  49.     public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { 
  50.         cause.printStackTrace(); 
  51.         ctx.close(); 
  52.     } 
  53.  
  54.  
  55.     /** 
  56.      * 处理请求信息 
  57.      * @param rpcRequest 请求信息 
  58.      * @return 结果信息 
  59.      * @since 0.0.6 
  60.      */ 
  61.     private DefaultRpcResponse handleRpcRequest(final RpcRequest rpcRequest) { 
  62.         DefaultRpcResponse rpcResponse = new DefaultRpcResponse(); 
  63.         rpcResponse.seqId(rpcRequest.seqId()); 
  64.  
  65.  
  66.         try { 
  67.             // 获取对应的 service 实现类 
  68.             // rpcRequest=>invocationRequest 
  69.             // 执行 invoke 
  70.             Object result = DefaultServiceFactory.getInstance() 
  71.                     .invoke(rpcRequest.serviceId(), 
  72.                             rpcRequest.methodName(), 
  73.                             rpcRequest.paramTypeNames(), 
  74.                             rpcRequest.paramValues()); 
  75.             rpcResponse.result(result); 
  76.         } catch (Exception e) { 
  77.             rpcResponse.error(e); 
  78.             log.error("[Server] execute meet ex for request", rpcRequest, e); 
  79.         } 
  80.  
  81.  
  82.         // 构建结果值 
  83.         return rpcResponse; 
  84.     } 
  85.  
  86.  

和以前类似,不过 handleRpcRequest 要稍微麻烦一点。

这里需要根据发射,调用对应的方法。

pojo

其中使用的出参、入参实现如下:

RpcRequest

  1. package com.github.houbb.rpc.common.rpc.domain; 
  2.  
  3.  
  4. import java.util.List; 
  5.  
  6.  
  7. /** 
  8.  * 序列化相关处理 
  9.  * (1)调用创建时间-createTime 
  10.  * (2)调用方式 callType 
  11.  * (3)超时时间 timeOut 
  12.  * 
  13.  * 额外信息: 
  14.  * (1)上下文信息 
  15.  * 
  16.  * @author binbin.hou 
  17.  * @since 0.0.6 
  18.  */ 
  19. public interface RpcRequest extends BaseRpc { 
  20.  
  21.  
  22.     /** 
  23.      * 创建时间 
  24.      * @return 创建时间 
  25.      * @since 0.0.6 
  26.      */ 
  27.     long createTime(); 
  28.  
  29.  
  30.     /** 
  31.      * 服务唯一标识 
  32.      * @return 服务唯一标识 
  33.      * @since 0.0.6 
  34.      */ 
  35.     String serviceId(); 
  36.  
  37.  
  38.     /** 
  39.      * 方法名称 
  40.      * @return 方法名称 
  41.      * @since 0.0.6 
  42.      */ 
  43.     String methodName(); 
  44.  
  45.  
  46.     /** 
  47.      * 方法类型名称列表 
  48.      * @return 名称列表 
  49.      * @since 0.0.6 
  50.      */ 
  51.     List<String> paramTypeNames(); 
  52.  
  53.  
  54.     // 调用参数信息列表 
  55.  
  56.  
  57.     /** 
  58.      * 调用参数值 
  59.      * @return 参数值数组 
  60.      * @since 0.0.6 
  61.      */ 
  62.     Object[] paramValues(); 
  63.  
  64.  

RpcResponse

  1. package com.github.houbb.rpc.common.rpc.domain; 
  2.  
  3.  
  4. /** 
  5.  * 序列化相关处理 
  6.  * @author binbin.hou 
  7.  * @since 0.0.6 
  8.  */ 
  9. public interface RpcResponse extends BaseRpc { 
  10.  
  11.  
  12.     /** 
  13.      * 异常信息 
  14.      * @return 异常信息 
  15.      * @since 0.0.6 
  16.      */ 
  17.     Throwable error(); 
  18.  
  19.  
  20.     /** 
  21.      * 请求结果 
  22.      * @return 请求结果 
  23.      * @since 0.0.6 
  24.      */ 
  25.     Object result(); 
  26.  
  27.  

BaseRpc

  1. package com.github.houbb.rpc.common.rpc.domain; 
  2.  
  3.  
  4. import java.io.Serializable
  5.  
  6.  
  7. /** 
  8.  * 序列化相关处理 
  9.  * @author binbin.hou 
  10.  * @since 0.0.6 
  11.  */ 
  12. public interface BaseRpc extends Serializable { 
  13.  
  14.  
  15.     /** 
  16.      * 获取唯一标识号 
  17.      * (1)用来唯一标识一次调用,便于获取该调用对应的响应信息。 
  18.      * @return 唯一标识号 
  19.      */ 
  20.     String seqId(); 
  21.  
  22.  
  23.     /** 
  24.      * 设置唯一标识号 
  25.      * @param traceId 唯一标识号 
  26.      * @return this 
  27.      */ 
  28.     BaseRpc seqId(final String traceId); 
  29.  
  30.  

ServiceFactory-服务工厂

为了便于对所有的 service 实现类统一管理,这里定义 service 工厂类。

ServiceFactory

  1. package com.github.houbb.rpc.server.service; 
  2.  
  3.  
  4. import com.github.houbb.rpc.server.config.service.ServiceConfig; 
  5. import com.github.houbb.rpc.server.registry.ServiceRegistry; 
  6.  
  7.  
  8. import java.util.List; 
  9.  
  10.  
  11. /** 
  12.  * 服务方法类仓库管理类-接口 
  13.  * 
  14.  * 
  15.  * (1)对外暴露的方法,应该尽可能的少。 
  16.  * (2)对于外部的调用,后期比如 telnet 治理,可以使用比如有哪些服务列表? 
  17.  * 单个服务有哪些方法名称? 
  18.  * 
  19.  * 等等基础信息的查询,本期暂时全部隐藏掉。 
  20.  * 
  21.  * (3)前期尽可能的少暴露方法。 
  22.  * @author binbin.hou 
  23.  * @since 0.0.6 
  24.  * @see ServiceRegistry 服务注册,将服务信息放在这个类中,进行统一的管理。 
  25.  * @see ServiceMethod 方法信息 
  26.  */ 
  27. public interface ServiceFactory { 
  28.  
  29.  
  30.     /** 
  31.      * 注册服务列表信息 
  32.      * @param serviceConfigList 服务配置列表 
  33.      * @return this 
  34.      * @since 0.0.6 
  35.      */ 
  36.     ServiceFactory registerServices(final List<ServiceConfig> serviceConfigList); 
  37.  
  38.  
  39.     /** 
  40.      * 直接反射调用 
  41.      * (1)此处对于方法反射,为了提升性能,所有的 class.getFullName() 进行拼接然后放进 key 中。 
  42.      * 
  43.      * @param serviceId 服务名称 
  44.      * @param methodName 方法名称 
  45.      * @param paramTypeNames 参数类型名称列表 
  46.      * @param paramValues 参数值 
  47.      * @return 方法调用返回值 
  48.      * @since 0.0.6 
  49.      */ 
  50.     Object invoke(final String serviceId, final String methodName, 
  51.                   List<String> paramTypeNames, final Object[] paramValues); 
  52.  
  53.  

DefaultServiceFactory

作为默认实现,如下:

  1. package com.github.houbb.rpc.server.service.impl; 
  2.  
  3.  
  4. import com.github.houbb.heaven.constant.PunctuationConst; 
  5. import com.github.houbb.heaven.util.common.ArgUtil; 
  6. import com.github.houbb.heaven.util.lang.reflect.ReflectMethodUtil; 
  7. import com.github.houbb.heaven.util.util.CollectionUtil; 
  8. import com.github.houbb.rpc.common.exception.RpcRuntimeException; 
  9. import com.github.houbb.rpc.server.config.service.ServiceConfig; 
  10. import com.github.houbb.rpc.server.service.ServiceFactory; 
  11.  
  12.  
  13. import java.lang.reflect.InvocationTargetException; 
  14. import java.lang.reflect.Method; 
  15. import java.util.HashMap; 
  16. import java.util.List; 
  17. import java.util.Map; 
  18.  
  19.  
  20. /** 
  21.  * 默认服务仓库实现 
  22.  * @author binbin.hou 
  23.  * @since 0.0.6 
  24.  */ 
  25. public class DefaultServiceFactory implements ServiceFactory { 
  26.  
  27.  
  28.     /** 
  29.      * 服务 map 
  30.      * @since 0.0.6 
  31.      */ 
  32.     private Map<String, Object> serviceMap; 
  33.  
  34.  
  35.     /** 
  36.      * 直接获取对应的 method 信息 
  37.      * (1)key: serviceId:methodName:param1@param2@param3 
  38.      * (2)value: 对应的 method 信息 
  39.      */ 
  40.     private Map<String, Method> methodMap; 
  41.  
  42.  
  43.     private static final DefaultServiceFactory INSTANCE = new DefaultServiceFactory(); 
  44.  
  45.  
  46.     private DefaultServiceFactory(){} 
  47.  
  48.  
  49.     public static DefaultServiceFactory getInstance() { 
  50.         return INSTANCE; 
  51.     } 
  52.  
  53.  
  54.     /** 
  55.      * 服务注册一般在项目启动的时候,进行处理。 
  56.      * 属于比较重的操作,而且一个服务按理说只应该初始化一次。 
  57.      * 此处加锁为了保证线程安全。 
  58.      * @param serviceConfigList 服务配置列表 
  59.      * @return this 
  60.      */ 
  61.     @Override 
  62.     public synchronized ServiceFactory registerServices(List<ServiceConfig> serviceConfigList) { 
  63.         ArgUtil.notEmpty(serviceConfigList, "serviceConfigList"); 
  64.  
  65.  
  66.         // 集合初始化 
  67.         serviceMap = new HashMap<>(serviceConfigList.size()); 
  68.         // 这里只是预估,一般为2个服务。 
  69.         methodMap = new HashMap<>(serviceConfigList.size()*2); 
  70.  
  71.  
  72.         for(ServiceConfig serviceConfig : serviceConfigList) { 
  73.             serviceMap.put(serviceConfig.id(), serviceConfig.reference()); 
  74.         } 
  75.  
  76.  
  77.         // 存放方法名称 
  78.         for(Map.Entry<String, Object> entry : serviceMap.entrySet()) { 
  79.             String serviceId = entry.getKey(); 
  80.             Object reference = entry.getValue(); 
  81.  
  82.  
  83.             //获取所有方法列表 
  84.             Method[] methods = reference.getClass().getMethods(); 
  85.             for(Method method : methods) { 
  86.                 String methodName = method.getName(); 
  87.                 if(ReflectMethodUtil.isIgnoreMethod(methodName)) { 
  88.                     continue
  89.                 } 
  90.  
  91.  
  92.                 List<String> paramTypeNames = ReflectMethodUtil.getParamTypeNames(method); 
  93.                 String key = buildMethodKey(serviceId, methodName, paramTypeNames); 
  94.                 methodMap.put(key, method); 
  95.             } 
  96.         } 
  97.  
  98.  
  99.         return this; 
  100.     } 
  101.  
  102.  
  103.  
  104.  
  105.     @Override 
  106.     public Object invoke(String serviceId, String methodName, List<String> paramTypeNames, Object[] paramValues) { 
  107.         //参数校验 
  108.         ArgUtil.notEmpty(serviceId, "serviceId"); 
  109.         ArgUtil.notEmpty(methodName, "methodName"); 
  110.  
  111.  
  112.         // 提供 cache,可以根据前三个值快速定位对应的 method 
  113.         // 根据 method 进行反射处理。 
  114.         // 对于 paramTypes 进行 string 连接处理。 
  115.         final Object reference = serviceMap.get(serviceId); 
  116.         final String methodKey = buildMethodKey(serviceId, methodName, paramTypeNames); 
  117.         final Method method = methodMap.get(methodKey); 
  118.  
  119.  
  120.         try { 
  121.             return method.invoke(reference, paramValues); 
  122.         } catch (IllegalAccessException | InvocationTargetException e) { 
  123.             throw new RpcRuntimeException(e); 
  124.         } 
  125.     } 
  126.  
  127.  
  128.     /** 
  129.      * (1)多个之间才用 : 分隔 
  130.      * (2)参数之间采用 @ 分隔 
  131.      * @param serviceId 服务标识 
  132.      * @param methodName 方法名称 
  133.      * @param paramTypeNames 参数类型名称 
  134.      * @return 构建完整的 key 
  135.      * @since 0.0.6 
  136.      */ 
  137.     private String buildMethodKey(String serviceId, String methodName, List<String> paramTypeNames) { 
  138.         String param = CollectionUtil.join(paramTypeNames, PunctuationConst.AT); 
  139.         return serviceId+PunctuationConst.COLON+methodName+PunctuationConst.COLON 
  140.                 +param; 
  141.     } 
  142.  
  143.  

ServiceRegistry-服务注册类

接口

  1. package com.github.houbb.rpc.server.registry; 
  2.  
  3.  
  4. /** 
  5.  * 服务注册类 
  6.  * (1)每个应用唯一 
  7.  * (2)每个服务的暴露协议应该保持一致 
  8.  * 暂时不提供单个服务的特殊处理,后期可以考虑添加 
  9.  * 
  10.  * @author binbin.hou 
  11.  * @since 0.0.6 
  12.  */ 
  13. public interface ServiceRegistry { 
  14.  
  15.  
  16.     /** 
  17.      * 暴露的 rpc 服务端口信息 
  18.      * @param port 端口信息 
  19.      * @return this 
  20.      * @since 0.0.6 
  21.      */ 
  22.     ServiceRegistry port(final int port); 
  23.  
  24.  
  25.     /** 
  26.      * 注册服务实现 
  27.      * @param serviceId 服务标识 
  28.      * @param serviceImpl 服务实现 
  29.      * @return this 
  30.      * @since 0.0.6 
  31.      */ 
  32.     ServiceRegistry register(final String serviceId, final Object serviceImpl); 
  33.  
  34.  
  35.     /** 
  36.      * 暴露所有服务信息 
  37.      * (1)启动服务端 
  38.      * @return this 
  39.      * @since 0.0.6 
  40.      */ 
  41.     ServiceRegistry expose(); 
  42.  
  43.  

实现

  1. package com.github.houbb.rpc.server.registry.impl; 
  2.  
  3.  
  4. import com.github.houbb.heaven.util.common.ArgUtil; 
  5. import com.github.houbb.rpc.common.config.protocol.ProtocolConfig; 
  6. import com.github.houbb.rpc.server.config.service.DefaultServiceConfig; 
  7. import com.github.houbb.rpc.server.config.service.ServiceConfig; 
  8. import com.github.houbb.rpc.server.core.RpcServer; 
  9. import com.github.houbb.rpc.server.registry.ServiceRegistry; 
  10. import com.github.houbb.rpc.server.service.impl.DefaultServiceFactory; 
  11.  
  12.  
  13. import java.util.ArrayList; 
  14. import java.util.List; 
  15.  
  16.  
  17. /** 
  18.  * 默认服务端注册类 
  19.  * @author binbin.hou 
  20.  * @since 0.0.6 
  21.  */ 
  22. public class DefaultServiceRegistry implements ServiceRegistry { 
  23.  
  24.  
  25.     /** 
  26.      * 单例信息 
  27.      * @since 0.0.6 
  28.      */ 
  29.     private static final DefaultServiceRegistry INSTANCE = new DefaultServiceRegistry(); 
  30.  
  31.  
  32.     /** 
  33.      * rpc 服务端端口号 
  34.      * @since 0.0.6 
  35.      */ 
  36.     private int rpcPort; 
  37.  
  38.  
  39.     /** 
  40.      * 协议配置 
  41.      * (1)默认只实现 tcp 
  42.      * (2)后期可以拓展实现 web-service/http/https 等等。 
  43.      * @since 0.0.6 
  44.      */ 
  45.     private ProtocolConfig protocolConfig; 
  46.  
  47.  
  48.     /** 
  49.      * 服务配置列表 
  50.      * @since 0.0.6 
  51.      */ 
  52.     private List<ServiceConfig> serviceConfigList; 
  53.  
  54.  
  55.     private DefaultServiceRegistry(){ 
  56.         // 初始化默认参数 
  57.         this.serviceConfigList = new ArrayList<>(); 
  58.         this.rpcPort = 9527; 
  59.     } 
  60.  
  61.  
  62.     public static DefaultServiceRegistry getInstance() { 
  63.         return INSTANCE; 
  64.     } 
  65.  
  66.  
  67.     @Override 
  68.     public ServiceRegistry port(int port) { 
  69.         ArgUtil.positive(port, "port"); 
  70.  
  71.  
  72.         this.rpcPort = port; 
  73.         return this; 
  74.     } 
  75.  
  76.  
  77.     /** 
  78.      * 注册服务实现 
  79.      * (1)主要用于后期服务调用 
  80.      * (2)如何根据 id 获取实现?非常简单,id 是唯一的。 
  81.      * 有就是有,没有就抛出异常,直接返回。 
  82.      * (3)如果根据 {@link com.github.houbb.rpc.common.rpc.domain.RpcRequest} 获取对应的方法。 
  83.      * 
  84.      * 3.1 根据 serviceId 获取唯一的实现 
  85.      * 3.2 根据 {@link Class#getMethod(String, Class[])} 方法名称+参数类型唯一获取方法 
  86.      * 3.3 根据 {@link java.lang.reflect.Method#invoke(Object, Object...)} 执行方法 
  87.      * 
  88.      * @param serviceId 服务标识 
  89.      * @param serviceImpl 服务实现 
  90.      * @return this 
  91.      * @since 0.0.6 
  92.      */ 
  93.     @Override 
  94.     @SuppressWarnings("unchecked"
  95.     public synchronized DefaultServiceRegistry register(final String serviceId, final Object serviceImpl) { 
  96.         ArgUtil.notEmpty(serviceId, "serviceId"); 
  97.         ArgUtil.notNull(serviceImpl, "serviceImpl"); 
  98.  
  99.  
  100.         // 构建对应的其他信息 
  101.         ServiceConfig serviceConfig = new DefaultServiceConfig(); 
  102.         serviceConfig.id(serviceId).reference(serviceImpl); 
  103.         serviceConfigList.add(serviceConfig); 
  104.  
  105.  
  106.         return this; 
  107.     } 
  108.  
  109.  
  110.     @Override 
  111.     public ServiceRegistry expose() { 
  112.         // 注册所有服务信息 
  113.         DefaultServiceFactory.getInstance() 
  114.                 .registerServices(serviceConfigList); 
  115.  
  116.  
  117.         // 暴露 netty server 信息 
  118.         new RpcServer(rpcPort).start(); 
  119.         return this; 
  120.     } 
  121.  
  122.  

ServiceConfig 是一些服务的配置信息,接口定义如下:

  1. package com.github.houbb.rpc.server.config.service; 
  2.  
  3.  
  4. /** 
  5.  * 单个服务配置类 
  6.  * 
  7.  * 简化用户使用: 
  8.  * 在用户使用的时候,这个类应该是不可见的。 
  9.  * 直接提供对应的服务注册类即可。 
  10.  * 
  11.  * 后续拓展 
  12.  * (1)版本信息 
  13.  * (2)服务端超时时间 
  14.  * 
  15.  * @author binbin.hou 
  16.  * @since 0.0.6 
  17.  * @param <T> 实现类泛型 
  18.  */ 
  19. public interface ServiceConfig<T> { 
  20.  
  21.  
  22.     /** 
  23.      * 获取唯一标识 
  24.      * @return 获取唯一标识 
  25.      * @since 0.0.6 
  26.      */ 
  27.     String id(); 
  28.  
  29.  
  30.     /** 
  31.      * 设置唯一标识 
  32.      * @param id 标识信息 
  33.      * @return this 
  34.      * @since 0.0.6 
  35.      */ 
  36.     ServiceConfig<T> id(String id); 
  37.  
  38.  
  39.     /** 
  40.      * 获取引用实体实现 
  41.      * @return 实体实现 
  42.      * @since 0.0.6 
  43.      */ 
  44.     T reference(); 
  45.  
  46.  
  47.     /** 
  48.      * 设置引用实体实现 
  49.      * @param reference 引用实现 
  50.      * @return this 
  51.      * @since 0.0.6 
  52.      */ 
  53.     ServiceConfig<T> reference(T reference); 
  54.  
  55.  

测试

maven 引入

引入服务端的对应 maven 包:

  1. <dependency> 
  2.     <groupId>com.github.houbb</groupId> 
  3.     <artifactId>rpc-server</artifactId> 
  4.     <version>0.0.6</version> 
  5. </dependency> 

服务端启动

  1. // 启动服务 
  2. DefaultServiceRegistry.getInstance() 
  3.         .register(ServiceIdConst.CALC, new CalculatorServiceImpl()) 
  4.         .expose(); 

这里注册了一个计算服务,并且设置对应的实现。

和以前实现类似,此处不再赘述。

启动日志:

  1. [DEBUG] [2021-10-05 13:39:42.638] [main] [c.g.h.l.i.c.LogFactory.setImplementation] - Logging initialized using 'class com.github.houbb.log.integration.adaptors.stdout.StdOutExImpl' adapter. 
  2. [INFO] [2021-10-05 13:39:42.645] [Thread-0] [c.g.h.r.s.c.RpcServer.run] - RPC 服务开始启动服务端 
  3. 十月 05, 2021 1:39:43 下午 io.netty.handler.logging.LoggingHandler channelRegistered 
  4. 信息: [id: 0xec4dc74f] REGISTERED 
  5. 十月 05, 2021 1:39:43 下午 io.netty.handler.logging.LoggingHandler bind 
  6. 信息: [id: 0xec4dc74f] BIND: 0.0.0.0/0.0.0.0:9527 
  7. 十月 05, 2021 1:39:43 下午 io.netty.handler.logging.LoggingHandler channelActive 
  8. 信息: [id: 0xec4dc74f, L:/0:0:0:0:0:0:0:0:9527] ACTIVE 
  9. [INFO] [2021-10-05 13:39:43.893] [Thread-0] [c.g.h.r.s.c.RpcServer.run] - RPC 服务端启动完成,监听【9527】端口 

ps: 写到这里忽然发现忘记添加对应的 register 日志了,这里可以添加对应的 registerListener 拓展。

 

责任编辑:姜华 来源: 今日头条
相关推荐

2021-10-27 08:10:15

Java 客户端 Java 基础

2021-10-19 08:58:48

Java 语言 Java 基础

2021-10-14 08:39:17

Java Netty Java 基础

2021-10-13 08:21:52

Java websocket Java 基础

2021-10-20 08:05:18

Java 序列化 Java 基础

2021-10-29 08:07:30

Java timeout Java 基础

2019-09-23 19:30:27

reduxreact.js前端

2024-01-02 12:17:44

Go传统远程

2020-07-02 15:32:23

Kubernetes容器架构

2015-11-17 16:11:07

Code Review

2019-01-18 12:39:45

云计算PaaS公有云

2018-04-18 07:01:59

Docker容器虚拟机

2011-08-17 09:14:03

FlexJava

2011-04-01 14:50:56

Java的反射机制

2010-05-26 17:35:08

配置Xcode SVN

2018-09-14 17:16:22

云计算软件计算机网络

2023-02-20 09:55:00

微服务框架单体架构

2017-09-13 14:01:51

数据库MongoDB数据库即服务

2021-03-16 11:30:33

Python遗传算法神经网络

2015-05-06 09:36:05

Java语言从零开始学习
点赞
收藏

51CTO技术栈公众号