①首先使用基于长度的帧解码器解决粘包半包问题,然后使用自定义的编解码器解析出ByteBuf中的数据,并将其封装为RpcMessage对象,接着在下一个Handler的channelRead方法中判断是否是心跳请求,如果是的话就将RpcMessage中data属性的值设为pong,如果不是的话就通过反射的方式执行方法调用,得到结果后写回给客户端。
②使用反射主要是为了避免客户端与服务实现类的直接依赖,我根据我的项目解释下,在项目启动时,会将带有@RpcService注解的bean作为value存入到一个ConcurrentHashMap中,这个bean就是服务实现类的实例,存入的key是它的接口名+分组名+版本号。然后在服务端处理请求时,就可以根据请求对象中的接口名、分组名和版本号在ConcurrentHashMap中找到对应的bean,但由于这个bean的引用类型是Object,所以我们无法直接调用它的方法。但通过反射,我们可以根据请求对象中的方法名、参数类型和参数值动态地获取方法引用和执行方法调用,这意味着客户端在发送请求时不需要确定具体的服务实现类,只需要通过接口名、方法名、参数等信息就能够调用远程服务,避免了客户端与服务实现类的直接依赖。
Object service = serviceProvider.getService(rpcRequest.getRpcServiceName());
Method method = service.getClass().getMethod(rpcRequest.getMethodName(),
rpcRequest.getParamTypes());
result = method.invoke(service, rpcRequest.getParameters());