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

Java 從零開始手寫 RPC-Netty4 實現(xiàn)客戶端和服務(wù)端

開發(fā) 后端
Netty是由JBOSS提供的一個java開源框架,現(xiàn)為 Github上的獨立項目。Netty提供異步的、事件驅(qū)動的網(wǎng)絡(luò)應(yīng)用程序框架和工具,用以快速開發(fā)高性能、高可靠性的網(wǎng)絡(luò)服務(wù)器和客戶端程序。

[[428830]]

說明

上一篇代碼基于 socket 的實現(xiàn)非常簡單,但是對于實際生產(chǎn),一般使用 netty。

至于 netty 的優(yōu)點可以參考:

為什么選擇 netty?[1]

http://houbb.github.io/2019/05/10/netty-definitive-gudie-04-why-netty

java 從零開始手寫 RPC (02)-netty4 實現(xiàn)客戶端和服務(wù)端

代碼實現(xiàn)

maven 引入

  1. <dependency> 
  2.     <groupId>io.netty</groupId> 
  3.     <artifactId>netty-all</artifactId> 
  4.     <version>${netty.version}</version> 
  5. </dependency> 

引入 netty 對應(yīng)的 maven 包,此處為 4.1.17.Final。

服務(wù)端代碼實現(xiàn)

netty 的服務(wù)端啟動代碼是比較固定的。

  1. package com.github.houbb.rpc.server.core; 
  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.server.constant.RpcServerConst; 
  7. import com.github.houbb.rpc.server.handler.RpcServerHandler; 
  8. import io.netty.bootstrap.ServerBootstrap; 
  9. import io.netty.channel.*; 
  10. import io.netty.channel.nio.NioEventLoopGroup; 
  11. import io.netty.channel.socket.nio.NioServerSocketChannel; 
  12.  
  13.  
  14. /** 
  15.  * rpc 服務(wù)端 
  16.  * @author binbin.hou 
  17.  * @since 0.0.1 
  18.  */ 
  19. public class RpcServer extends Thread { 
  20.  
  21.  
  22.     private static final Log log = LogFactory.getLog(RpcServer.class); 
  23.  
  24.  
  25.     /** 
  26.      * 端口號 
  27.      */ 
  28.     private final int port; 
  29.  
  30.  
  31.     public RpcServer() { 
  32.         this.port = RpcServerConst.DEFAULT_PORT; 
  33.     } 
  34.  
  35.  
  36.     public RpcServer(int port) { 
  37.         this.port = port; 
  38.     } 
  39.  
  40.  
  41.     @Override 
  42.     public void run() { 
  43.         // 啟動服務(wù)端 
  44.         log.info("RPC 服務(wù)開始啟動服務(wù)端"); 
  45.  
  46.  
  47.         EventLoopGroup bossGroup = new NioEventLoopGroup(); 
  48.         EventLoopGroup workerGroup = new NioEventLoopGroup(); 
  49.  
  50.  
  51.         try { 
  52.             ServerBootstrap serverBootstrap = new ServerBootstrap(); 
  53.             serverBootstrap.group(workerGroup, bossGroup) 
  54.                     .channel(NioServerSocketChannel.class) 
  55.                     .childHandler(new ChannelInitializer<Channel>() { 
  56.                         @Override 
  57.                         protected void initChannel(Channel ch) throws Exception { 
  58.                             ch.pipeline().addLast(new RpcServerHandler()); 
  59.                         } 
  60.                     }) 
  61.                     // 這個參數(shù)影響的是還沒有被accept 取出的連接 
  62.                     .option(ChannelOption.SO_BACKLOG, 128) 
  63.                     // 這個參數(shù)只是過一段時間內(nèi)客戶端沒有響應(yīng),服務(wù)端會發(fā)送一個 ack 包,以判斷客戶端是否還活著。 
  64.                     .childOption(ChannelOption.SO_KEEPALIVE, true); 
  65.  
  66.  
  67.             // 綁定端口,開始接收進來的鏈接 
  68.             ChannelFuture channelFuture = serverBootstrap.bind(port).syncUninterruptibly(); 
  69.             log.info("RPC 服務(wù)端啟動完成,監(jiān)聽【" + port + "】端口"); 
  70.  
  71.  
  72.             channelFuture.channel().closeFuture().syncUninterruptibly(); 
  73.             log.info("RPC 服務(wù)端關(guān)閉完成"); 
  74.         } catch (Exception e) { 
  75.             log.error("RPC 服務(wù)異常", e); 
  76.         } finally { 
  77.             workerGroup.shutdownGracefully(); 
  78.             bossGroup.shutdownGracefully(); 
  79.         } 
  80.     } 
  81.  
  82.  

為了簡單,服務(wù)端啟動端口號固定,RpcServerConst 常量類內(nèi)容如下:

  1. public final class RpcServerConst { 
  2.  
  3.  
  4.     private RpcServerConst(){} 
  5.  
  6.  
  7.     /** 
  8.      * 默認端口 
  9.      * @since 0.0.1 
  10.      */ 
  11.     public static final int DEFAULT_PORT = 9627; 
  12.  
  13.  

RpcServerHandler

當然,還有一個比較核心的類就是 RpcServerHandler

  1. public class RpcServerHandler extends SimpleChannelInboundHandler { 
  2.     @Override 
  3.     protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception { 
  4.         // do nothing now 
  5.     } 

目前是空實現(xiàn),后續(xù)可以添加對應(yīng)的日志輸出及邏輯處理。

測試

啟動測試的代碼非常簡單:

  1. /** 
  2.  * 服務(wù)啟動代碼測試 
  3.  * @param args 參數(shù) 
  4.  */ 
  5. public static void main(String[] args) { 
  6.     new RpcServer().start(); 

說明

上面我們實現(xiàn)了服務(wù)端的實現(xiàn),這一節(jié)來一起看一下 client 客戶端代碼實現(xiàn)。

代碼實現(xiàn)

RpcClient

  1. /* 
  2.  * Copyright (c)  2019. houbinbin Inc. 
  3.  * rpc All rights reserved. 
  4.  */ 
  5.  
  6.  
  7. package com.github.houbb.rpc.client.core; 
  8.  
  9.  
  10. import com.github.houbb.log.integration.core.Log; 
  11. import com.github.houbb.log.integration.core.LogFactory; 
  12. import com.github.houbb.rpc.client.handler.RpcClientHandler; 
  13.  
  14.  
  15. import io.netty.bootstrap.Bootstrap; 
  16. import io.netty.channel.Channel; 
  17. import io.netty.channel.ChannelFuture; 
  18. import io.netty.channel.ChannelInitializer; 
  19. import io.netty.channel.ChannelOption; 
  20. import io.netty.channel.EventLoopGroup; 
  21. import io.netty.channel.nio.NioEventLoopGroup; 
  22. import io.netty.channel.socket.nio.NioSocketChannel; 
  23. import io.netty.handler.logging.LogLevel; 
  24. import io.netty.handler.logging.LoggingHandler; 
  25.  
  26.  
  27. /** 
  28.  * <p> rpc 客戶端 </p> 
  29.  * 
  30.  * <pre> Created: 2019/10/16 11:21 下午  </pre> 
  31.  * <pre> Project: rpc  </pre> 
  32.  * 
  33.  * @author houbinbin 
  34.  * @since 0.0.2 
  35.  */ 
  36. public class RpcClient extends Thread { 
  37.  
  38.  
  39.     private static final Log log = LogFactory.getLog(RpcClient.class); 
  40.  
  41.  
  42.     /** 
  43.      * 監(jiān)聽端口號 
  44.      */ 
  45.     private final int port; 
  46.  
  47.  
  48.     public RpcClient(int port) { 
  49.         this.port = port; 
  50.     } 
  51.  
  52.  
  53.     public RpcClient() { 
  54.         this(9527); 
  55.     } 
  56.  
  57.  
  58.     @Override 
  59.     public void run() { 
  60.         // 啟動服務(wù)端 
  61.         log.info("RPC 服務(wù)開始啟動客戶端"); 
  62.  
  63.  
  64.         EventLoopGroup workerGroup = new NioEventLoopGroup(); 
  65.  
  66.  
  67.         try { 
  68.             Bootstrap bootstrap = new Bootstrap(); 
  69.             ChannelFuture channelFuture = bootstrap.group(workerGroup) 
  70.                     .channel(NioSocketChannel.class) 
  71.                     .option(ChannelOption.SO_KEEPALIVE, true
  72.                     .handler(new ChannelInitializer<Channel>(){ 
  73.                         @Override 
  74.                         protected void initChannel(Channel ch) throws Exception { 
  75.                             ch.pipeline() 
  76.                                     .addLast(new LoggingHandler(LogLevel.INFO)) 
  77.                                     .addLast(new RpcClientHandler()); 
  78.                         } 
  79.                     }) 
  80.                     .connect("localhost", port) 
  81.                     .syncUninterruptibly(); 
  82.  
  83.  
  84.             log.info("RPC 服務(wù)啟動客戶端完成,監(jiān)聽端口:" + port); 
  85.             channelFuture.channel().closeFuture().syncUninterruptibly(); 
  86.             log.info("RPC 服務(wù)開始客戶端已關(guān)閉"); 
  87.         } catch (Exception e) { 
  88.             log.error("RPC 客戶端遇到異常", e); 
  89.         } finally { 
  90.             workerGroup.shutdownGracefully(); 
  91.         } 
  92.     } 
  93.  
  94.  

.connect("localhost", port) 聲明了客戶端需要連接的服務(wù)端,此處和服務(wù)端的端口保持一致。

RpcClientHandler

客戶端處理類也比較簡單,暫時留空。

  1. /* 
  2.  * Copyright (c)  2019. houbinbin Inc. 
  3.  * rpc All rights reserved. 
  4.  */ 
  5.  
  6.  
  7. package com.github.houbb.rpc.client.handler; 
  8.  
  9.  
  10. import io.netty.channel.ChannelHandlerContext; 
  11. import io.netty.channel.SimpleChannelInboundHandler; 
  12.  
  13.  
  14. /** 
  15.  * <p> 客戶端處理類 </p> 
  16.  * 
  17.  * <pre> Created: 2019/10/16 11:30 下午  </pre> 
  18.  * <pre> Project: rpc  </pre> 
  19.  * 
  20.  * @author houbinbin 
  21.  * @since 0.0.2 
  22.  */ 
  23. public class RpcClientHandler extends SimpleChannelInboundHandler { 
  24.  
  25.  
  26.     @Override 
  27.     protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception { 
  28.         // do nothing. 
  29.     } 
  30.  
  31.  

啟動測試

服務(wù)端

首先啟動服務(wù)端。

客戶端

然后啟動客戶端連接服務(wù)端,實現(xiàn)如下:

  1. /** 
  2.  * 服務(wù)啟動代碼測試 
  3.  * @param args 參數(shù) 
  4.  */ 
  5. public static void main(String[] args) { 
  6.     new RpcClient().start(); 

小結(jié)

為了便于大家學(xué)習,以上源碼已經(jīng)開源:

https://github.com/houbb/rpc

我是老馬,期待與你的下次重逢。

References

[1] 為什么選擇 netty?: http://houbb.github.io/2019/05/10/netty-definitive-gudie-04-why-netty

 

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

2021-10-19 08:58:48

Java 語言 Java 基礎(chǔ)

2021-10-21 08:21:10

Java Reflect Java 基礎(chǔ)

2021-10-27 08:10:15

Java 客戶端 Java 基礎(chǔ)

2022-06-14 15:07:04

IPC客戶端服務(wù)端

2021-10-13 08:21:52

Java websocket Java 基礎(chǔ)

2018-12-20 08:50:53

TCPIP服務(wù)器

2010-03-01 16:10:32

Linux Samba

2012-05-07 13:55:41

JavaJava Web

2021-10-20 08:05:18

Java 序列化 Java 基礎(chǔ)

2010-03-19 09:26:34

Java Socket

2010-01-11 13:05:24

VNC server配

2022-01-05 08:03:23

C#通信Rest

2009-08-21 15:36:41

服務(wù)端與客戶端

2009-08-21 15:54:40

服務(wù)端與客戶端

2021-10-29 08:07:30

Java timeout Java 基礎(chǔ)

2010-03-18 17:47:07

Java 多客戶端通信

2023-11-17 09:13:36

2018-04-12 10:55:41

Android服務(wù)器數(shù)據(jù)

2011-03-28 17:24:26

2011-09-09 09:44:23

WCF
點贊
收藏

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