基于Netty4手把手实现一个带注册中心和注解的Dubbo框架

在本篇文章中,我们继续围绕进行优化,主要引入几个点

集成spring,实现注解驱动配置

集成zookeeper,实现服务注册

增加负载均衡实现

源代码,加「跟着Mic学架构」微信号,回复『rpc』获取。

增加注解驱动

主要涉及到的修改模块

netty-rpc-protocol

netty-rpc-provider

netty-rpc-protocol

当前模块主要修改的类如下。

image-20210908163139333

图7-1

下面针对netty-rpc-protocol模块的修改如下

增加注解驱动

这个注解的作用是用来指定某些服务为远程服务

@Target(ElementType.TYPE)// Target说明了Annotation所修饰的对象范围, TYPE:用于描述类、接口(包括注解类型) 或enum声明 @Retention(RetentionPolicy.RUNTIME)// Reteniton的作用是定义被它所注解的注解保留多久,保留至运行时。所以我们可以通过反射去获取注解信息。 @Component public @interface GpRemoteService { } SpringRpcProviderBean

这个类主要用来在启动NettyServer,以及保存bean的映射关系

@Slf4j public class SpringRpcProviderBean implements InitializingBean, BeanPostProcessor { private final int serverPort; private final String serverAddress; public SpringRpcProviderBean(int serverPort) throws UnknownHostException { this.serverPort = serverPort; InetAddress address=InetAddress.getLocalHost(); this.serverAddress=address.getHostAddress(); } @Override public void afterPropertiesSet() throws Exception { log.info("begin deploy Netty Server to host {},on port {}",this.serverAddress,this.serverPort); new Thread(()->{ try { new NettyServer(this.serverAddress,this.serverPort).startNettyServer(); } catch (Exception e) { log.error("start Netty Server Occur Exception,",e); e.printStackTrace(); } }).start(); } //bean实例化后调用 @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if(bean.getClass().isAnnotationPresent(GpRemoteService.class)){ //针对存在该注解的服务进行发布 Method[] methods=bean.getClass().getDeclaredMethods(); for(Method method: methods){ //保存需要发布的bean的映射 String key=bean.getClass().getInterfaces()[0].getName()+"."+method.getName(); BeanMethod beanMethod=new BeanMethod(); beanMethod.setBean(bean); beanMethod.setMethod(method); Mediator.beanMethodMap.put(key,beanMethod); } } return bean; } } Mediator

主要管理bean以及调用

BeanMethod @Data public class BeanMethod { private Object bean; private Method method; } Mediator

负责持有发布bean的管理,以及bean的反射调用

public class Mediator { public static Map<String,BeanMethod> beanMethodMap=new ConcurrentHashMap<>(); private volatile static Mediator instance=null; private Mediator(){ } public static Mediator getInstance(){ if(instance==null){ synchronized (Mediator.class){ if(instance==null){ instance=new Mediator(); } } } return instance; } public Object processor(RpcRequest rpcRequest){ String key=rpcRequest.getClassName()+"."+rpcRequest.getMethodName(); BeanMethod beanMethod=beanMethodMap.get(key); if(beanMethod==null){ return null; } Object bean=beanMethod.getBean(); Method method=beanMethod.getMethod(); try { return method.invoke(bean,rpcRequest.getParams()); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } return null; } } RpcServerProperties

定义配置属性

@Data @ConfigurationProperties(prefix = "gp.rpc") public class RpcServerProperties { private int servicePort; } RpcProviderAutoConfiguration

定义自动配置类

@Configuration @EnableConfigurationProperties(RpcServerProperties.class) public class RpcProviderAutoConfiguration { @Bean public SpringRpcProviderBean rpcProviderBean(RpcServerProperties rpcServerProperties) throws UnknownHostException { return new SpringRpcProviderBean(rpcServerProperties.getServicePort()); } } 修改RpcServerHandler

修改调用方式,直接使用Mediator的调用即可。

public class RpcServerHandler extends SimpleChannelInboundHandler<RpcProtocol<RpcRequest>> { @Override protected void channelRead0(ChannelHandlerContext ctx, RpcProtocol<RpcRequest> msg) throws Exception { RpcProtocol resProtocol=new RpcProtocol<>(); Header header=msg.getHeader(); header.setReqType(ReqType.RESPONSE.code()); Object result=Mediator.getInstance().processor(msg.getContent()); //主要修改这个部分 resProtocol.setHeader(header); RpcResponse response=new RpcResponse(); response.setData(result); response.setMsg("success"); resProtocol.setContent(response); ctx.writeAndFlush(resProtocol); } } netty-rpc-provider

这个模块中主要修改两个部分

application.properties

NettyRpcProviderMain

NettyRpcProviderMain @ComponentScan(basePackages = {"com.example.spring.annotation","com.example.spring.service","com.example.service"}) @SpringBootApplication public class NettyRpcProviderMain { public static void main(String[] args) throws Exception { SpringApplication.run(NettyRpcProviderMain.class, args); //去掉原来的实例化部分 } } application.properties

增加一个配置属性。

gp.rpc.servicePort=20880 UserServiceImpl

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zzpjzj.html