java Netty 之Hello World
先看看服务端和客户端的代码:
public class HelloServer { public static void main(String args[]) { // Server服务启动器 ServerBootstrap bootstrap = new ServerBootstrap( new NioServerSocketChannelFactory( Executors.newCachedThreadPool(), Executors.newCachedThreadPool())); // 设置一个处理客户端消息和各种消息事件的类(Handler) bootstrap .setPipelineFactory(new ChannelPipelineFactory() { @Override public ChannelPipeline getPipeline() throws Exception { return Channels .pipeline(new HelloServerHandler()); } }); // 开放8000端口供客户端访问。 bootstrap.bind(new InetSocketAddress(8000)); } private static class HelloServerHandler extends SimpleChannelHandler { /** * 当有客户端绑定到服务端的时候触发,打印"Hello world, I'm server." * * @alia OneCoder * @author lihzh */ @Override public void channelConnected( ChannelHandlerContext ctx, ChannelStateEvent e) { System.out.println("Hello world, I'm server."); } } }
public class HelloClient { public static void main(String args[]) { // Client服务启动器 ClientBootstrap bootstrap = new ClientBootstrap( new NioClientSocketChannelFactory( Executors.newCachedThreadPool(), Executors.newCachedThreadPool())); // 设置一个处理服务端消息和各种消息事件的类(Handler) bootstrap.setPipelineFactory(new ChannelPipelineFactory() { @Override public ChannelPipeline getPipeline() throws Exception { return Channels.pipeline(new HelloClientHandler()); } }); // 连接到本地的8000端口的服务端 bootstrap.connect(new InetSocketAddress( "127.0.0.1", 8000)); } private static class HelloClientHandler extends SimpleChannelHandler { /** * 当绑定到服务端的时候触发,打印"Hello world, I'm client." * * @alia OneCoder * @author lihzh */ @Override public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) { System.out.println("Hello world, I'm client."); } } }
注意两点:
1. 既然是分布式的,自然要分多个服务。Netty中,需要区分Server和Client服务。所有的Client都是绑定在Server上的,他们之间是不能通过Netty直接通信的。(自己采用的其他手段,不包括在内。)。白话一下这个通信过程,Server端开放端口,供Client连接,Client发起请求,连接到Server指定的端口,完成绑定。随后便可自由通信。其实就是普通Socket连接通信的过程。
2. Netty框架是基于事件机制的,简单说,就是发生什么事,就找相关处理方法。就跟着火了找119,事故了找110一个道理。所以,这里,我们处理的是当客户端和服务端完成连接以后的这个事件。什么时候完成的连接,Netty知道,他告诉我了,我就负责处理。这就是框架的作用。Netty,提供的事件还有很多,以后会慢慢的接触和介绍。
代码实现
ServerSocketChannelFactory
ServerBootstrap用一个ServerSocketChannelFactory 来实例化。ServerSocketChannelFactory 有两种选择,一种是NioServerSocketChannelFactory,一种是OioServerSocketChannelFactory。 前者使用NIO,后则使用普通的阻塞式IO。它们都需要两个线程池实例作为参数来初始化,一个是boss线程池,一个是worker线程池。
bootstrap.setPipelineFactory()
这里设置ChannelpipelineFactory,factory中要new一个我们自定义的Handler,Handler中重写相应事件的方法,这样我们就能在方法中写我们的业务。同时,我们自定义的Handler是继承SimpleChannelHandler。
ServerBootstrap.bind(int)
负责绑定端口,当这个方法执行后,ServerBootstrap就可以接受指定端口上的socket连接了。一个ServerBootstrap可以绑定多个端口。
boss线程和worker线程
boss线程
主要负责connet和accept
可以这么说,ServerBootstrap监听的一个端口对应一个boss线程,它们一一对应。比如你需要netty监听80和443端口,那么就会有两个boss线程分别负责处理来自两个端口的socket请求。在boss线程接收了socket连接请求后,会产生一个channel(一个打开的socket对应一个打开的channel),并把这个channel交给ServerBootstrap初始化时指定的ServerSocketChannelFactory来处理,boss线程则继续处理socket的请求。
worker线程
主要负责业务逻辑
ServerSocketChannelFactory则会从worker线程池中找出一个worker线程来继续处理这个请求。其中分为:OioServerSocketChannelFactory 和 NioServerSocketChannelFactory。
- OioServerSocketChannelFactory:就是IO,这个channel上所有的socket消息,从开始到channel(socket)关闭,都只由这个特定的worker来处理,也就是说一个打开的socket对应一个指定的worker线程,这个worker线程在socket没有关闭的情况下,也只能为这个socket处理消息,无法服务其他socket。
- NioServerSocketChannelFactory:就是NIO,每个worker可以服务不同的socket或者说channel,worker线程和channel不再有一一对应的关系。
结果
显然,NioServerSocketChannelFactory只需要少量活动的worker线程及能很好的处理众多的channel,而OioServerSocketChannelFactory则需要与打开channel等量的worker线程来服务。
如何选择
线程是一种资源,所以当netty服务器需要处理长连接的时候,最好选择NioServerSocketChannelFactory,这样可以避免创建大 量的worker线程。在用作http服务器的时候,也最好选择NioServerSocketChannelFactory,因为现代浏览器都会使用 http keepalive功能(可以让浏览器的不同http请求共享一个信道),这也是一种长连接。
worker线程的生命周期(life circle)
1. 当某个channel有消息到达或者有消息需要写入socket的时候,worker线程就会从线程池中取出一个。在worker线程中,消息会经过设定好的ChannelPipeline处理。ChannelPipeline就是一堆有顺序的filter,它分为两部分:UpstreamHandler和 DownStreamHandler。
2. 客户端送入的消息会首先由许多UpstreamHandler依次处理,处理得到的数据送入应用的业务逻辑handler,通常用SimpleChannelUpstreamHandler来实现这一部分。
private static class HelloClientHandler extends SimpleChannelHandler { /** * 当绑定到服务端的时候触发,打印"Hello world, I'm client." * * @alia OneCoder * @author lihzh */ @Override public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) { System.out.println("Hello world, I'm client."); } }
3. 对 于Nio当messageReceived()方法执行后,如果没有产生异常,worker线程就执行完毕了,它会被线程池回收。业务逻辑hanlder 会通过一些方法,把返回的数据交给指定好顺序的DownStreamHandler处理,处理后的数据如果需要,会被写入channel,进而通过绑定的 socket发送给客户端。这个过程是由另外一个线程池中的worker线程来完成的。
4. 对于Oio来说,从始到终,都是由一个指定的worker来处理。
减少worker线程的处理占用时间
worker 线程是由netty内部管理,统一调配的一种资源,所以最好应该尽快的把让worker线程执行完毕,返回给线程池回收利用。worker线程的大部分时 间消耗在在ChannelPipeline的各种handler中,而在这些handler中,一般是负责应用程序业务逻辑掺入的那个handler最占 时间,它通常是排在最后的UpstreamHandler。所以通过把这部分处理内容交给另外一个线程来处理,可以有效的减少worker线程的周期循环 时间。一般有两种方法:
- 开启一个新的线程来处理业务逻辑
- 另外构造一个线程池来提交业务逻辑处理任务(更优雅)
代码如下:
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception{ ... new Thread(...).start(); }
参考
http://blog.csdn.net/lichunan/article/details/45165783
相关推荐
01、Mina服务端helloWorld入门.flv 02、Mina客户端helloWorld入门.flv 03、Mina整体体系结构分析.flv 04、Mina学习之长短连接.flv 05、Mina学习之MinaIOService接口.flv 06、Mina学习之MinaIOFilter接口.flv ...
框架需要在netty框架( )上实现一个http服务器,功能如下: 根据对请求在 10 秒后给出“Hello World” 根据对请求,重定向到指定的 url 根据对请求统计信息: 请求总数唯一请求的数量(每个 IP 一个) 每个 IP 的...
近百节视频详细讲解,需要的小伙伴自行百度网盘下载,链接见附件,永久有效...2. Hello World 3. 组件 4. 双向通信 三. Netty 进阶 1. 粘包与半包 2. 协议设计与解析 3. 聊天室案例 四. 优化与源码 1. 优化 2. 源码分析
cassandra-netty-rest-simple 集成了Cassandra,Netty和JBoss RESTEasy的简单应用程序。 它提供了一个Hello World REST Web服务,可以通过。 调用服务时,它将Person的实例持久化到名为DEMO的Cassandra键空间中。
Test http://localhost:8082/resteasy/hello/world 教程 jax-rs规范用法: http://www.vogella.com/tutorials/REST/article.html resteasy 教程: http://code.freedomho.com/9541.html 名次解释 RESTEasy:RESTEasy...
:OK_hand: :netty-helloworld b。 『基础-通讯协议篇』 :OK_hand: :netty-http :OK_hand: netty-springboot-protobuf :OK_hand: netty-mqtt C。 『中级-数据传输篇』 Netty碰上关系型数据库 :monkey: ...
本书是为想要或者正在使用 Java 从事高性能网络编程的人而写的,循序渐进地介绍了 Netty 各个方面的内容。 本书共分为 4 个部分:第一部分详细地介绍 Netty 的相关概念以及核心组件,第二部分介绍 自定义协议经常...
Java访问权限控制,为Java操作文件、写入文件分配合适的权限,定义写到文件的信息、定义文件,输出到c:/hello.txt、写信息到文件、关闭输出流。 Java绘制图片火焰效果 1个目标文件 摘要:Java源码,图形操作,火焰...
Java访问权限控制,为Java操作文件、写入文件分配合适的权限,定义写到文件的信息、定义文件,输出到c:/hello.txt、写信息到文件、关闭输出流。 Java绘制图片火焰效果 1个目标文件 摘要:Java源码,图形操作,火焰...
netty-example 使用Netty的示例Web服务器,受启发例子 public class App { public static void main ( final String [] args ) throws Exception { new WebServer () // Simple GET request .get( " /hello " , ...
NettyHttp服务器基于Netty框架的简单Http Server Netty Framework 版本 4.0.26.Final 已使用(稳定来自 maven repo) -request 在 10 秒内显示“Hello World”。 -request 重定向到 。 -request 显示有关连接、请求...
netty-examples是基于netty4开发的应用实例:rpc server和client的实现Netty4Client简化netty client的应用,实现自动重连功能RPC HelloWorld 实例服务实现public interface HelloWorld {public Result queryUser...
netty_http_status一个任务需要在netty框架( )上实现一个http服务器,功能如下: 根据对请求在 10 秒后发送“Hello World” 根据对请求,重定向到指定的 url 根据对请求统计信息: 请求总数唯一请求的数量(每个 ...
驴使用Netty的Java节点式库。 需要JDK 8。用法 Http.createServer((req, res) -> { res.writeHead(200, new HttpHeader(contentType("text/plain"))); res.write("Hello World!");}).listen(3000);
根据对请求在 10 秒后发送“Hello World” 根据对请求,重定向到指定的 url 根据对请求统计信息: 请求总数 唯一请求的数量(每个 IP 一个) 每个 IP 的请求计数器,以包含列和 IP、请求数量、上次请求时间的...
RequestHandler.java-处理Hello World并重定向 尚不涉及其他两个类: ChannelSpeedCheckHandler.java-处理香奈儿统计信息(尚无法正常工作) StatisticsRequestHandler.java-忘记删除。 AB测试运行结果: ab -c ...
httpkids 面向孩子的基于netty的Web框架,需要Java10!...public class HelloWorld { public static void main ( String [] args ) { var rd = new KidsRequestDispatcher ( " /kids " , new Router
Netty HTTP 服务器 描述 它是一个基于 NIO 框架 Netty 的 HTTP 服务器,提供处理 HTTP 请求并将有关它们的... http://localhost:{port}/hello服务器等待 10 秒,然后发送包含“Hello World”字符串的 HTML 页面响应。
净休息简单将Netty与JBoss RESTEasy集成的简单应用程序。 它提供了一个Hello World REST Web服务,可以通过。 返回值将是UUID的字符串值。