自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Java 從零開(kāi)始手寫(xiě) RPC—如何實(shí)現(xiàn)客戶(hù)端調(diào)用服務(wù)端?

開(kāi)發(fā) 后端
寫(xiě)完了客戶(hù)端和服務(wù)端,那么如何實(shí)現(xiàn)客戶(hù)端和服務(wù)端的調(diào)用呢?下面就讓我們一起來(lái)看一下。希望本文對(duì)你有所幫助!

[[429717]]

寫(xiě)完了客戶(hù)端和服務(wù)端,那么如何實(shí)現(xiàn)客戶(hù)端和服務(wù)端的調(diào)用呢?

下面就讓我們一起來(lái)看一下。

接口定義

計(jì)算方法

  1. package com.github.houbb.rpc.common.service; 
  2.  
  3.  
  4. import com.github.houbb.rpc.common.model.CalculateRequest; 
  5. import com.github.houbb.rpc.common.model.CalculateResponse; 
  6.  
  7.  
  8. /** 
  9.  * <p> 計(jì)算服務(wù)接口 </p> 
  10.  * 
  11.  * <pre> Created: 2018/8/24 下午4:47  </pre> 
  12.  * <pre> Project: fake  </pre> 
  13.  * 
  14.  * @author houbinbin 
  15.  * @since 0.0.1 
  16.  */ 
  17. public interface Calculator { 
  18.  
  19.  
  20.     /** 
  21.      * 計(jì)算加法 
  22.      * @param request 請(qǐng)求入?yún)?nbsp;
  23.      * @return 返回結(jié)果 
  24.      */ 
  25.     CalculateResponse sum(final CalculateRequest request); 
  26.  
  27.  

pojo

對(duì)應(yīng)的參數(shù)對(duì)象:

  • CalculateRequest
  1. package com.github.houbb.rpc.common.model; 
  2.  
  3.  
  4. import java.io.Serializable
  5.  
  6.  
  7. /** 
  8.  * <p> 請(qǐng)求入?yún)?nbsp;</p> 
  9.  * 
  10.  * <pre> Created: 2018/8/24 下午5:05  </pre> 
  11.  * <pre> Project: fake  </pre> 
  12.  * 
  13.  * @author houbinbin 
  14.  * @since 0.0.3 
  15.  */ 
  16. public class CalculateRequest implements Serializable { 
  17.  
  18.  
  19.     private static final long serialVersionUID = 6420751004355300996L; 
  20.  
  21.  
  22.     /** 
  23.      * 參數(shù)一 
  24.      */ 
  25.     private int one; 
  26.  
  27.  
  28.     /** 
  29.      * 參數(shù)二 
  30.      */ 
  31.     private int two; 
  32.  
  33.  
  34.     public CalculateRequest() { 
  35.     } 
  36.  
  37.  
  38.     public CalculateRequest(int one, int two) { 
  39.         this.one = one; 
  40.         this.two = two; 
  41.     } 
  42.  
  43.  
  44.     //getter setter toString 
  45.  
  46.  
  • CalculateResponse
  1. package com.github.houbb.rpc.common.model; 
  2.  
  3.  
  4. import java.io.Serializable
  5.  
  6.  
  7. /** 
  8.  * <p> 請(qǐng)求入?yún)?nbsp;</p> 
  9.  * 
  10.  * <pre> Created: 2018/8/24 下午5:05  </pre> 
  11.  * <pre> Project: fake  </pre> 
  12.  * 
  13.  * @author houbinbin 
  14.  * @since 0.0.3 
  15.  */ 
  16. public class CalculateResponse implements Serializable { 
  17.  
  18.  
  19.     private static final long serialVersionUID = -1972014736222511341L; 
  20.  
  21.  
  22.     /** 
  23.      * 是否成功 
  24.      */ 
  25.    private boolean success; 
  26.  
  27.  
  28.     /** 
  29.      * 二者的和 
  30.      */ 
  31.    private int sum
  32.  
  33.  
  34.     public CalculateResponse() { 
  35.     } 
  36.  
  37.  
  38.     public CalculateResponse(boolean success, int sum) { 
  39.         this.success = success; 
  40.         this.sum = sum
  41.     } 
  42.  
  43.  
  44.     //getter setter toString 

客戶(hù)端

核心部分

RpcClient 需要添加對(duì)應(yīng)的 Handler,調(diào)整如下:

  1. Bootstrap bootstrap = new Bootstrap(); 
  2. ChannelFuture channelFuture = bootstrap.group(workerGroup) 
  3.         .channel(NioSocketChannel.class) 
  4.         .option(ChannelOption.SO_KEEPALIVE, true
  5.         .handler(new ChannelInitializer<Channel>(){ 
  6.             @Override 
  7.             protected void initChannel(Channel ch) throws Exception { 
  8.                 ch.pipeline() 
  9.                         .addLast(new LoggingHandler(LogLevel.INFO)) 
  10.                         .addLast(new CalculateRequestEncoder()) 
  11.                         .addLast(new CalculateResponseDecoder()) 
  12.                         .addLast(new RpcClientHandler()); 
  13.             } 
  14.         }) 
  15.         .connect(RpcConstant.ADDRESS, port) 
  16.         .syncUninterruptibly(); 

netty 中的 handler 泳道設(shè)計(jì)的非常優(yōu)雅,讓我們的代碼可以非常靈活地進(jìn)行拓展。

接下來(lái)我們看一下對(duì)應(yīng)的實(shí)現(xiàn)。

RpcClientHandler

  1. package com.github.houbb.rpc.client.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.client.core.RpcClient; 
  7. import com.github.houbb.rpc.common.model.CalculateRequest; 
  8. import com.github.houbb.rpc.common.model.CalculateResponse; 
  9. import io.netty.channel.ChannelHandlerContext; 
  10. import io.netty.channel.SimpleChannelInboundHandler; 
  11.  
  12.  
  13. /** 
  14.  * <p> 客戶(hù)端處理類(lèi) </p> 
  15.  * 
  16.  * <pre> Created: 2019/10/16 11:30 下午  </pre> 
  17.  * <pre> Project: rpc  </pre> 
  18.  * 
  19.  * @author houbinbin 
  20.  * @since 0.0.2 
  21.  */ 
  22. public class RpcClientHandler extends SimpleChannelInboundHandler { 
  23.  
  24.  
  25.     private static final Log log = LogFactory.getLog(RpcClient.class); 
  26.  
  27.  
  28.     @Override 
  29.     public void channelActive(ChannelHandlerContext ctx) throws Exception { 
  30.         CalculateRequest request = new CalculateRequest(1, 2); 
  31.  
  32.  
  33.         ctx.writeAndFlush(request); 
  34.         log.info("[Client] request is :{}", request); 
  35.     } 
  36.  
  37.  
  38.     @Override 
  39.     protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception { 
  40.         CalculateResponse response = (CalculateResponse)msg; 
  41.         log.info("[Client] response is :{}", response); 
  42.     } 
  43.  
  44.  

這里比較簡(jiǎn)單,channelActive 中我們直接發(fā)起調(diào)用,入?yún)⒌膶?duì)象為了簡(jiǎn)單,此處固定寫(xiě)死。

channelRead0 中監(jiān)聽(tīng)服務(wù)端的相應(yīng)結(jié)果,并做日志輸出。

CalculateRequestEncoder

請(qǐng)求參數(shù)是一個(gè)對(duì)象,netty 是無(wú)法直接傳輸?shù)?,我們將其轉(zhuǎn)換為基本對(duì)象:

  1. package com.github.houbb.rpc.client.encoder; 
  2.  
  3.  
  4. import com.github.houbb.rpc.common.model.CalculateRequest; 
  5. import io.netty.buffer.ByteBuf; 
  6. import io.netty.channel.ChannelHandlerContext; 
  7. import io.netty.handler.codec.MessageToByteEncoder; 
  8.  
  9.  
  10. /** 
  11.  * @author binbin.hou 
  12.  * @since 0.0.3 
  13.  */ 
  14. public class CalculateRequestEncoder extends MessageToByteEncoder<CalculateRequest> { 
  15.  
  16.  
  17.     @Override 
  18.     protected void encode(ChannelHandlerContext ctx, CalculateRequest msg, ByteBuf out) throws Exception { 
  19.         int one = msg.getOne(); 
  20.         int two = msg.getTwo(); 
  21.  
  22.  
  23.         out.writeInt(one); 
  24.         out.writeInt(two); 
  25.     } 
  26.  
  27.  

CalculateResponseDecoder

針對(duì)服務(wù)端的響應(yīng),也是同理。

我們需要把基本的類(lèi)型,封裝轉(zhuǎn)換為我們需要的對(duì)象。

  1. package com.github.houbb.rpc.client.decoder; 
  2.  
  3.  
  4. import com.github.houbb.rpc.common.model.CalculateResponse; 
  5. import io.netty.buffer.ByteBuf; 
  6. import io.netty.channel.ChannelHandlerContext; 
  7. import io.netty.handler.codec.ByteToMessageDecoder; 
  8.  
  9.  
  10. import java.util.List; 
  11.  
  12.  
  13. /** 
  14.  * 響應(yīng)參數(shù)解碼 
  15.  * @author binbin.hou 
  16.  * @since 0.0.3 
  17.  */ 
  18. public class CalculateResponseDecoder extends ByteToMessageDecoder { 
  19.  
  20.  
  21.     @Override 
  22.     protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception { 
  23.         boolean success = in.readBoolean(); 
  24.         int sum = in.readInt(); 
  25.  
  26.  
  27.         CalculateResponse response = new CalculateResponse(success, sum); 
  28.         out.add(response); 
  29.     } 
  30.  
  31.  

服務(wù)端

設(shè)置處理類(lèi)

RpcServer 中的處理類(lèi)要稍微調(diào)整一下,其他的保持不變。

  1. ServerBootstrap serverBootstrap = new ServerBootstrap(); 
  2. serverBootstrap.group(workerGroup, bossGroup) 
  3.         .channel(NioServerSocketChannel.class) 
  4.         // 打印日志 
  5.         .handler(new LoggingHandler(LogLevel.INFO)) 
  6.         .childHandler(new ChannelInitializer<Channel>() { 
  7.             @Override 
  8.             protected void initChannel(Channel ch) throws Exception { 
  9.                 ch.pipeline() 
  10.                         .addLast(new CalculateRequestDecoder()) 
  11.                         .addLast(new CalculateResponseEncoder()) 
  12.                         .addLast(new RpcServerHandler()); 
  13.             } 
  14.         }) 
  15.         // 這個(gè)參數(shù)影響的是還沒(méi)有被accept 取出的連接 
  16.         .option(ChannelOption.SO_BACKLOG, 128) 
  17.         // 這個(gè)參數(shù)只是過(guò)一段時(shí)間內(nèi)客戶(hù)端沒(méi)有響應(yīng),服務(wù)端會(huì)發(fā)送一個(gè) ack 包,以判斷客戶(hù)端是否還活著。 
  18.         .childOption(ChannelOption.SO_KEEPALIVE, true); 

RpcServerHandler

一開(kāi)始這里是空實(shí)現(xiàn),我們來(lái)添加一下對(duì)應(yīng)的實(shí)現(xiàn)。

  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.model.CalculateRequest; 
  7. import com.github.houbb.rpc.common.model.CalculateResponse; 
  8. import com.github.houbb.rpc.common.service.Calculator; 
  9. import com.github.houbb.rpc.server.service.CalculatorService; 
  10. import io.netty.channel.ChannelHandlerContext; 
  11. import io.netty.channel.SimpleChannelInboundHandler; 
  12.  
  13.  
  14. /** 
  15.  * @author binbin.hou 
  16.  * @since 0.0.1 
  17.  */ 
  18. public class RpcServerHandler extends SimpleChannelInboundHandler { 
  19.  
  20.  
  21.     private static final Log log = LogFactory.getLog(RpcServerHandler.class); 
  22.  
  23.  
  24.     @Override 
  25.     public void channelActive(ChannelHandlerContext ctx) throws Exception { 
  26.         final String id = ctx.channel().id().asLongText(); 
  27.         log.info("[Server] channel {} connected " + id); 
  28.     } 
  29.  
  30.  
  31.     @Override 
  32.     protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception { 
  33.         final String id = ctx.channel().id().asLongText(); 
  34.  
  35.  
  36.         CalculateRequest request = (CalculateRequest)msg; 
  37.         log.info("[Server] receive channel {} request: {} from ", id, request); 
  38.  
  39.  
  40.         Calculator calculator = new CalculatorService(); 
  41.         CalculateResponse response = calculator.sum(request); 
  42.  
  43.  
  44.         // 回寫(xiě)到 client 端 
  45.         ctx.writeAndFlush(response); 
  46.         log.info("[Server] channel {} response {}", id, response); 
  47.     } 
  48.  
  49.  

讀取到客戶(hù)端的訪(fǎng)問(wèn)之后,我們獲取到計(jì)算的入?yún)? CalculateRequest,然后調(diào)用 sum 方法,獲取到對(duì)應(yīng)的 CalculateResponse,將結(jié)果通知客戶(hù)端。

CalculateRequestDecoder

這里和客戶(hù)端是一一對(duì)應(yīng)的,我們首先把 netty 傳遞的基本類(lèi)型轉(zhuǎn)換為 CalculateRequest 對(duì)象。

  1. package com.github.houbb.rpc.server.decoder; 
  2.  
  3.  
  4. import com.github.houbb.rpc.common.model.CalculateRequest; 
  5. import io.netty.buffer.ByteBuf; 
  6. import io.netty.channel.ChannelHandlerContext; 
  7. import io.netty.handler.codec.ByteToMessageDecoder; 
  8.  
  9.  
  10. import java.util.List; 
  11.  
  12.  
  13. /** 
  14.  * 請(qǐng)求參數(shù)解碼 
  15.  * @author binbin.hou 
  16.  * @since 0.0.3 
  17.  */ 
  18. public class CalculateRequestDecoder extends ByteToMessageDecoder { 
  19.  
  20.  
  21.     @Override 
  22.     protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception { 
  23.         int one = in.readInt(); 
  24.         int two = in.readInt(); 
  25.  
  26.  
  27.         CalculateRequest request = new CalculateRequest(one, two); 
  28.         out.add(request); 
  29.     } 
  30.  
  31.  

CalculateResponseEncoder

這里和客戶(hù)端類(lèi)似,我們需要把 response 轉(zhuǎn)換為基本類(lèi)型進(jìn)行網(wǎng)絡(luò)傳輸。

  1. package com.github.houbb.rpc.server.encoder; 
  2.  
  3.  
  4. import com.github.houbb.rpc.common.model.CalculateResponse; 
  5. import io.netty.buffer.ByteBuf; 
  6. import io.netty.channel.ChannelHandlerContext; 
  7. import io.netty.handler.codec.MessageToByteEncoder; 
  8.  
  9.  
  10. /** 
  11.  * @author binbin.hou 
  12.  * @since 0.0.3 
  13.  */ 
  14. public class CalculateResponseEncoder extends MessageToByteEncoder<CalculateResponse> { 
  15.  
  16.  
  17.     @Override 
  18.     protected void encode(ChannelHandlerContext ctx, CalculateResponse msg, ByteBuf out) throws Exception { 
  19.         boolean success = msg.isSuccess(); 
  20.         int result = msg.getSum(); 
  21.         out.writeBoolean(success); 
  22.         out.writeInt(result); 
  23.     } 
  24.  
  25.  

CalculatorService

服務(wù)端對(duì)應(yīng)的實(shí)現(xiàn)類(lèi)。

  1. public class CalculatorService implements Calculator { 
  2.  
  3.  
  4.     @Override 
  5.     public CalculateResponse sum(CalculateRequest request) { 
  6.         int sum = request.getOne()+request.getTwo(); 
  7.  
  8.  
  9.         return new CalculateResponse(truesum); 
  10.     } 
  11.  
  12.  

測(cè)試

服務(wù)端

啟動(dòng)服務(wù)端:

  1. new RpcServer().start(); 

服務(wù)端啟動(dòng)日志:

  1. [DEBUG] [2021-10-05 11:53:11.795] [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 11:53:11.807] [Thread-0] [c.g.h.r.s.c.RpcServer.run] - RPC 服務(wù)開(kāi)始啟動(dòng)服務(wù)端 
  3. 十月 05, 2021 11:53:13 上午 io.netty.handler.logging.LoggingHandler channelRegistered 
  4. 信息: [id: 0xd399474f] REGISTERED 
  5. 十月 05, 2021 11:53:13 上午 io.netty.handler.logging.LoggingHandler bind 
  6. 信息: [id: 0xd399474f] BIND: 0.0.0.0/0.0.0.0:9527 
  7. 十月 05, 2021 11:53:13 上午 io.netty.handler.logging.LoggingHandler channelActive 
  8. 信息: [id: 0xd399474f, L:/0:0:0:0:0:0:0:0:9527] ACTIVE 
  9. [INFO] [2021-10-05 11:53:13.101] [Thread-0] [c.g.h.r.s.c.RpcServer.run] - RPC 服務(wù)端啟動(dòng)完成,監(jiān)聽(tīng)【9527】端口 

客戶(hù)端

啟動(dòng)客戶(hù)端:

  1. new RpcClient().start(); 

日志如下:

  1. [DEBUG] [2021-10-05 11:54:12.158] [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 11:54:12.164] [Thread-0] [c.g.h.r.c.c.RpcClient.run] - RPC 服務(wù)開(kāi)始啟動(dòng)客戶(hù)端 
  3. 十月 05, 2021 11:54:13 上午 io.netty.handler.logging.LoggingHandler channelRegistered 
  4. 信息: [id: 0x4d75c580] REGISTERED 
  5. 十月 05, 2021 11:54:13 上午 io.netty.handler.logging.LoggingHandler connect 
  6. 信息: [id: 0x4d75c580] CONNECT: /127.0.0.1:9527 
  7. 十月 05, 2021 11:54:13 上午 io.netty.handler.logging.LoggingHandler channelActive 
  8. 信息: [id: 0x4d75c580, L:/127.0.0.1:54030 - R:/127.0.0.1:9527] ACTIVE 
  9. [INFO] [2021-10-05 11:54:13.403] [Thread-0] [c.g.h.r.c.c.RpcClient.run] - RPC 服務(wù)啟動(dòng)客戶(hù)端完成,監(jiān)聽(tīng)端口:9527 
  10. 十月 05, 2021 11:54:13 上午 io.netty.handler.logging.LoggingHandler write 
  11. 信息: [id: 0x4d75c580, L:/127.0.0.1:54030 - R:/127.0.0.1:9527] WRITE: 8B 
  12.          +-------------------------------------------------+ 
  13.          |  0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f | 
  14. +--------+-------------------------------------------------+----------------+ 
  15. |00000000| 00 00 00 01 00 00 00 02                         |........        | 
  16. +--------+-------------------------------------------------+----------------+ 
  17. 十月 05, 2021 11:54:13 上午 io.netty.handler.logging.LoggingHandler flush 
  18. 信息: [id: 0x4d75c580, L:/127.0.0.1:54030 - R:/127.0.0.1:9527] FLUSH 
  19. [INFO] [2021-10-05 11:54:13.450] [nioEventLoopGroup-2-1] [c.g.h.r.c.c.RpcClient.channelActive] - [Client] request is :CalculateRequest{one=1, two=2} 
  20. 十月 05, 2021 11:54:13 上午 io.netty.handler.logging.LoggingHandler channelRead 
  21. 信息: [id: 0x4d75c580, L:/127.0.0.1:54030 - R:/127.0.0.1:9527] READ: 5B 
  22.          +-------------------------------------------------+ 
  23.          |  0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f | 
  24. +--------+-------------------------------------------------+----------------+ 
  25. |00000000| 01 00 00 00 03                                  |.....           | 
  26. +--------+-------------------------------------------------+----------------+ 
  27. 十月 05, 2021 11:54:13 上午 io.netty.handler.logging.LoggingHandler channelReadComplete 
  28. 信息: [id: 0x4d75c580, L:/127.0.0.1:54030 - R:/127.0.0.1:9527] READ COMPLETE 
  29. [INFO] [2021-10-05 11:54:13.508] [nioEventLoopGroup-2-1] [c.g.h.r.c.c.RpcClient.channelRead0] - [Client] response is :CalculateResponse{success=truesum=3} 

可以看到,輸出了對(duì)應(yīng)的請(qǐng)求參數(shù)和響應(yīng)結(jié)果。

當(dāng)然,此時(shí)服務(wù)端也有對(duì)應(yīng)的新增日志:

  1. 十月 05, 2021 11:54:13 上午 io.netty.handler.logging.LoggingHandler channelRead 
  2. 信息: [id: 0xd399474f, L:/0:0:0:0:0:0:0:0:9527] READ: [id: 0xbc9f5927, L:/127.0.0.1:9527 - R:/127.0.0.1:54030] 
  3. 十月 05, 2021 11:54:13 上午 io.netty.handler.logging.LoggingHandler channelReadComplete 
  4. 信息: [id: 0xd399474f, L:/0:0:0:0:0:0:0:0:9527] READ COMPLETE 
  5. [INFO] [2021-10-05 11:54:13.432] [nioEventLoopGroup-2-1] [c.g.h.r.s.h.RpcServerHandler.channelActive] - [Server] channel {} connected 00e04cfffe360988-00001d34-00000001-2a80d950d8166c0c-bc9f5927 
  6. [INFO] [2021-10-05 11:54:13.495] [nioEventLoopGroup-2-1] [c.g.h.r.s.h.RpcServerHandler.channelRead0] - [Server] receive channel 00e04cfffe360988-00001d34-00000001-2a80d950d8166c0c-bc9f5927 request: CalculateRequest{one=1, two=2} from  
  7. [INFO] [2021-10-05 11:54:13.505] [nioEventLoopGroup-2-1] [c.g.h.r.s.h.RpcServerHandler.channelRead0] - [Server] channel 00e04cfffe360988-00001d34-00000001-2a80d950d8166c0c-bc9f5927 response CalculateResponse{success=truesum=3} 

 

責(zé)任編輯:姜華 來(lái)源: 今日頭條
相關(guān)推薦

2021-10-14 08:39:17

Java Netty Java 基礎(chǔ)

2021-10-21 08:21:10

Java Reflect Java 基礎(chǔ)

2021-10-27 08:10:15

Java 客戶(hù)端 Java 基礎(chǔ)

2021-10-13 08:21:52

Java websocket Java 基礎(chǔ)

2021-10-20 08:05:18

Java 序列化 Java 基礎(chǔ)

2009-08-21 15:36:41

服務(wù)端與客戶(hù)端

2009-08-21 15:54:40

服務(wù)端與客戶(hù)端

2021-10-29 08:07:30

Java timeout Java 基礎(chǔ)

2010-03-18 17:47:07

Java 多客戶(hù)端通信

2023-11-17 09:13:36

2024-03-06 14:58:52

客戶(hù)端微服務(wù)架構(gòu)

2009-08-21 15:59:22

服務(wù)端與客戶(hù)端通信

2011-09-09 09:44:23

WCF

2009-08-21 16:14:52

服務(wù)端與客戶(hù)端通信

2023-03-06 08:01:56

MySQLCtrl + C

2010-05-31 10:11:32

瘦客戶(hù)端

2023-04-03 08:13:05

MySQLCtrl + C

2010-11-19 14:22:04

oracle服務(wù)端

2014-06-01 11:03:13

VDI零客戶(hù)端

2013-05-09 09:33:59

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)