標籤:java
Netty學習筆記(一)
Netty是一個高效能的NIO架構,相比與IO編程需要編寫大量的代碼,Netty的使用更加簡單。Netty的主要功能是負責網路傳輸,dubbo,rocket MQ以及elasticsearch中都採用Netty做為網路傳輸架構。
Netty的特性(以下特性來自百度,但是我感覺對於開發人員來時主要還是用起來比較簡單。。。。。。)
1.設計
針對多種傳輸類型的統一介面 - 阻塞和非阻塞
簡單但更強大的執行緒模式
真正的不需連線的資料通訊端支援
連結邏輯支援複用
2.易用性
大量的 Javadoc 和 代碼執行個體
除了在 JDK 1.6 + 額外的限制。(一些特徵是只支援在Java 1.7 +。可選的功能可能有額外的限制。)
3.效能
比核心 Java API 更好的輸送量,較低的延時
資源消耗更少,這個得益於共用池和重用
減少記憶體拷貝
4.健壯性
消除由於慢,快,或重載串連產生的 OutOfMemoryError
消除經常發現在 NIO 在高速網路中的應用中的不公平的讀/寫比
5.安全
完整的 SSL / TLS 和 StartTLS 的支援
行在受限的環境例如 Applet 或 OSGI
6.社區
發布的更早和更頻繁
社區驅動
服務端:
public class Server {public static void main(String[] args) throws Exception{//1 建立線兩個程組 //一個是用於處理伺服器端接收用戶端串連的//一個是進行網路通訊的(網路讀寫的)EventLoopGroup pGroup = new NioEventLoopGroup();EventLoopGroup cGroup = new NioEventLoopGroup();//2 建立協助工具輔助類,用於伺服器通道的一系列配置ServerBootstrap b = new ServerBootstrap();b.group(pGroup, cGroup)//綁定倆個線程組 .channel(NioServerSocketChannel.class)//指定NIO的模式 .option(ChannelOption.SO_BACKLOG, 1024)//設定tcp緩衝區 //設定日誌 .handler(new LoggingHandler(LogLevel.INFO)) .childHandler(new ChannelInitializer<SocketChannel>() {protected void initChannel(SocketChannel sc) throws Exception {sc.pipeline().addLast(MarshallingCodeCFactory.buildMarshallingDecoder());sc.pipeline().addLast(MarshallingCodeCFactory.buildMarshallingEncoder());//用戶端與服務端在3s內沒有任何通訊則關閉響應通道 節省伺服器資源(用戶端服務端都需要配置)sc.pipeline().addLast(new ReadTimeoutHandler(3)); //3 在這裡配置具體資料接收方法的處理sc.pipeline().addLast(new ServerHandler());}});//4 進行綁定 ChannelFuture cf1 = b.bind(8765).sync();//ChannelFuture cf2 = b.bind(8766).sync();//5 等待關閉cf1.channel().closeFuture().sync();//cf2.channel().closeFuture().sync();pGroup.shutdownGracefully();cGroup.shutdownGracefully();}}public class ServerHandler extends ChannelHandlerAdapter{@Overridepublic void channelActive(ChannelHandlerContext ctx) throws Exception {}@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {Request request = (Request)msg;System.out.println("Server : " + request.getId() + ", " + request.getName() + ", " + request.getRequestMessage());Response response = new Response();response.setId(request.getId());response.setName("response" + request.getId());response.setResponseMessage("響應內容" + request.getId());ctx.writeAndFlush(response);//.addListener(ChannelFutureListener.CLOSE);監聽響應成功後斷開通道短連結方式}@Overridepublic void channelReadComplete(ChannelHandlerContext ctx) throws Exception {}@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {ctx.close();}}
用戶端:
public class Client {private static class SingletonHolder {static final Client instance = new Client();}public static Client getInstance(){return SingletonHolder.instance;}private EventLoopGroup group;private Bootstrap b;private ChannelFuture cf ;private Client(){group = new NioEventLoopGroup();b = new Bootstrap();b.group(group) .channel(NioSocketChannel.class) .handler(new LoggingHandler(LogLevel.INFO)) .handler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel sc) throws Exception { //通過JBOSS的Marshalling進行編碼解碼sc.pipeline().addLast(MarshallingCodeCFactory.buildMarshallingDecoder());sc.pipeline().addLast(MarshallingCodeCFactory.buildMarshallingEncoder());//用戶端與服務端在3s內沒有任何通訊則關閉響應通道 節省伺服器資源sc.pipeline().addLast(new ReadTimeoutHandler(3)); //sc.pipeline().addLast(new ClientHandler());} });}public void connect(){try {this.cf = b.connect("127.0.0.1", 8765).sync();System.out.println("遠程伺服器已經串連, 可以進行資料交換..");} catch (Exception e) {e.printStackTrace();}}public ChannelFuture getChannelFuture(){if(this.cf == null){this.connect();}if(!this.cf.channel().isActive()){this.connect();}return this.cf;}public static void main(String[] args) throws Exception{final Client c = Client.getInstance();//c.connect();ChannelFuture cf = c.getChannelFuture();for(int i = 1; i <= 3; i++ ){Request request = new Request();request.setId("" + i);request.setName("pro" + i);request.setRequestMessage("資料資訊" + i);cf.channel().writeAndFlush(request);TimeUnit.SECONDS.sleep(4);}cf.channel().closeFuture().sync();//通過new一個子線程來重新串連服務端new Thread(new Runnable() {@Overridepublic void run() {try {System.out.println("進入子線程...");ChannelFuture cf = c.getChannelFuture();System.out.println(cf.channel().isActive());System.out.println(cf.channel().isOpen());//再次發送資料Request request = new Request();request.setId("" + 4);request.setName("pro" + 4);request.setRequestMessage("資料資訊" + 4);cf.channel().writeAndFlush(request);cf.channel().closeFuture().sync();System.out.println("子線程結束.");} catch (InterruptedException e) {e.printStackTrace();}}}).start();System.out.println("中斷連線,主線程結束..");}}public class ClientHandler extends ChannelHandlerAdapter{@Overridepublic void channelActive(ChannelHandlerContext ctx) throws Exception {}@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {try {Response resp = (Response)msg;System.out.println("Client : " + resp.getId() + ", " + resp.getName() + ", " + resp.getResponseMessage());} finally {ReferenceCountUtil.release(msg);}}@Overridepublic void channelReadComplete(ChannelHandlerContext ctx) throws Exception {}@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {ctx.close();}}
Marshalling工廠:
public final class MarshallingCodeCFactory { /** * 建立Jboss Marshalling解碼器MarshallingDecoder * @return MarshallingDecoder */ public static MarshallingDecoder buildMarshallingDecoder() { //首先通過Marshalling工具類的精通方法擷取Marshalling執行個體對象 參數serial標識建立的是java序列化工廠對象。final MarshallerFactory marshallerFactory = Marshalling.getProvidedMarshallerFactory("serial");//建立了MarshallingConfiguration對象,配置了版本號碼為5 final MarshallingConfiguration configuration = new MarshallingConfiguration();configuration.setVersion(5);//根據marshallerFactory和configuration建立providerUnmarshallerProvider provider = new DefaultUnmarshallerProvider(marshallerFactory, configuration);//構建Netty的MarshallingDecoder對象,倆個參數分別為provider和單個訊息序列化後的最大長度MarshallingDecoder decoder = new MarshallingDecoder(provider, 1024);return decoder; } /** * 建立Jboss Marshalling編碼器MarshallingEncoder * @return MarshallingEncoder */ public static MarshallingEncoder buildMarshallingEncoder() {final MarshallerFactory marshallerFactory = Marshalling.getProvidedMarshallerFactory("serial");final MarshallingConfiguration configuration = new MarshallingConfiguration();configuration.setVersion(5);MarshallerProvider provider = new DefaultMarshallerProvider(marshallerFactory, configuration);//構建Netty的MarshallingEncoder對象,MarshallingEncoder用於實現序列化介面的POJO對象序列化為位元組MarshallingEncoder encoder = new MarshallingEncoder(provider);return encoder; }}
Netty學習筆記(一)