当前位置: 首页 > 科技观察

Java手写RPC-Netty4从无到有实现客户端和服务器

时间:2023-03-17 14:13:57 科技观察

可见前面代码基于socket的实现很简单,但是实际生产中一般使用netty。至于netty的优点可以参考:为什么选择netty?[1]http://houbb.github.io/2019/05/10/netty-definitive-gudie-04-why-netty代码实现maven并引入io.nettynetty-all${netty.version}引入netty对应的maven包,这里是4.1.17.Final。服务端代码实现netty的服务端启动代码比较固定。packagecom.github.houbb.rpc.server.core;importcom.github.houbb.log.integration.core.Log;importcom.github.houbb.log.integration.core.LogFactory;importcom.github.houbb.rpc.server。constant.RpcServerConst;importcom.github.houbb.rpc.server.handler.RpcServerHandler;importio.netty.bootstrap.ServerBootstrap;importio.netty.channel.*;importio.netty.channel.nio.NioEventLoopGroup;importio.netty.channel。socket.nio.NioServerSocketChannel;/***rpc服务端*@authorbinbin.hou*@since0.0.1*/publicclassRpcServerextendsThread{privatestaticfinalLoglog=LogFactory.getLog(RpcServer.class);/***端口号*/privatefinalintport;publicRpcServer(){this.port=RpcServerConst.DEFAULT_PORT;}publicRpcServer(intport){this.port=port;}@Overridepublicvoidrun(){//启动服务端log.info("RPC服务开始启动服务端");EventLoopGroupbossGroup=newNioEventLoopGroup();EventLoopGroupworkerGroup=newNioEventLoopGroup();try{ServerBootstrapserverBootstrap=newServerBootstrap();serverBootstrap.group(workerGroup,bossGroup).channel(NioServerSocketChannel.class).childHandler(newChannelInitializer(){@OverrideprotectedvoidinitChannel(Channelch)throwsException{ch.pipeline().addLast(newRpcServerHandler());}})//这个参数还没有被接受的连接out.option(ChannelOption.SO_BACKLOG,128)//这个参数只是客户端一段时间后没有响应,服务端会发一个ack包来判断客户端是否还活着.childOption(ChannelOption.SO_KEEPALIVE,true);//Bindport,starttoreceiveincominglinksChannelFuturechannelFuture=serverBootstrap.bind(port).syncUninterruptibly();log.info("RPCserverstartupiscomplete,listening【"+port+"】Port");channelFuture.channel().closeFuture().syncUninterruptibly();log.info("RPCserverclosecomplete");}catch(Exceptione){log.error("RPCserviceexception",e);}finally{workerGroup.shutdownGracefully();bossGroup.shutdownGracefully();}}}Forthesakeofsimplicity,theserverstartupportnumberisfixed,andtheRpcServerConstconstantclasscontentisasfollows:publicfinalclassRpcServerConst{privateRpcServerConst(){}/***defaultport*@since0.0.1*/publicstaticfinalintDEFAULT_PORT=9627;}RpcServerHandler当然,还有一个比较核心的类就是RpcServerHandlerpublicclassRpcServerHandlerextendsSimpleChannelInboundHandler{@OverrideprotectedvoidchannelRead0(ChannelHandlerContextctx,Objectmsg)throwsException{//donothingnow}}目前是空实现,后续可以添加对应的日志输出andlogicalprocessing.Thecodeoftheteststartuptestisverysimple:/***Servicestartupcodetest*@paramargsparameter*/publicstaticvoidmain(String[]args){newRpcServer().start();}Indicatesthatwehaveimplementedtheimplementationoftheserverabove,thisLet'stakealookattheclientclientcodeimplementation.代码实现RpcClient/**Copyright(c)2019.houbinbinInc.*rpcAllrightsreserved.*/packagecom.github.houbb.rpc.client.core;importcom.github.houbb.log.integration.core.Log;importcom.github.houbb.log.integration.core.LogFactory;importcom.github.houbb.rpc.client.handler.RpcClientHandler;importio.netty.bootstrap.Bootstrap;importio.netty.channel.Channel;importio.netty.channel.ChannelFuture;importio.netty.channel.ChannelInitializer;importio.netty.channel.ChannelOption;importio.netty.channel.EventLoopGroup;importio.netty.channel.nio.NioEventLoopGroup;importio.netty.channel.socket.nio.NioSocketChannel;importio.netty.handler.logging.LogLevel;importio.netty.handler.logging.LoggingHandler;/***

rpc客户端

**
创建时间:2019/10/1611:21下午
*
项目:rpc
**@authorhoubinbin*@since0.0.2*/publicclassRpcClienttextendsThread{privatestaticfinalLoglog=LogFactory.getLog(RpcClient.class);/***监听端口号*/privatefinalintport;publicRpcClient(intport){this.port=port;}publicRpcClient(){this(9527);}@Overridepublicvoidrun(){//启动服务器log.info("RPC服务开始启动客户端");EventLoopGroupworkerGroup=newNioEventLoopGroup();try{Bootstrapbootstrap=newBootstrap();ChannelFuturechannelFuture=bootstrap.group(workerGroup).channel(NioSocketChannel.class).option(ChannelOption.SO_KEEPALIVE,true).handler(newChannelInitializer(){@OverrideprotectedvoidinitChannel()通道。pipeline().addLast(newLoggingHandler(LogLevel.INFO)).addLast(newRpcClientHandler());}}).connect("localhost",port).syncUninterruptibly();log.info("RPC服务启动客户端完成,监听端口:“+端口”;channelFuture.channel().closeFuture().syncUninterruptibly();log.info("RPC服务启动,客户端关闭");}catch(Exceptione){log.error("RPC客户端遇到异常",e);}finally{workerGroup.shutdownGracefully();}}}.connect("localhost",port)声明了客户端需要连接的服务器,与服务器的端口一致RpcClientHandler客户端处理类也是比较简单,暂时留空。/**版权所有(c)2019.houbinbinInc.*rpcAllrightsreserved.*/packagecom.github.houbb.rpc.client.handler;importio.netty.channel.ChannelHandlerContext;importio.netty.channel.SimpleChannelInboundHandler;/***

客户端处理类

**
创建时间:2019/10/1611:30pm
*
Project:rpc
**@authorhoubinbin*@since0.0.2*/publicclassRpcClientHandlerextendsSimpleChannelInboundHandler{@OverrideprotectedvoidchannelRead0(ChannelHandlerContextctx,Objectmsg)throwsException{//donothing.}}启动测试服务器首先启动服务器。然后客户端启动客户端连接服务器,实现如下:/***服务启动代码测试*@paramargs参数*/publicstaticvoidmain(String[]args){newRpcClient().start();}总结为了方便大家学习,以上源码已经开源:https://github.com/houbb/rpc我是一匹老马,期待与大家的下一次重逢。参考资料[1]为什么选择netty?:http://houbb.github.io/2019/05/10/netty-definitive-gudie-04-why-netty