欢迎来到皮皮网网首页

【influxdb源码分析】【开源网站设计源码】【源码编程的教学】channel future 源码

来源:浪峰源码 时间:2024-12-23 01:29:41

1.关于Netty中线程的小结
2.多通道协议有哪些?
3.Netty中的Channel之数据冲刷与线程安全(writeAndFlush)
4.netty系列之:小白福利!手把手教你做一个简单的代理服务器

channel future 源码

关于Netty中线程的小结

        1. 一个EventLoopGroup当中会包含一个或者多个EventLoop.

2. 一个EventLoop在它的整个生命周期中都只会与唯一一个Thread进行绑定

3. 所有由EventLoop所处理的各种I/O事件都将在它所关联的那个Thread上进行处理

4. 一个Channel在它的整个生命周期中只会注册在一个EventLoop上

5. 一个EventLoop在运行过程当中,会被分配给一个或者多个Channel.

        一: 在Netty中,Channel的实现一定是线程安全的;基于此,我们可以存储一个Channel的引用,并且在需要向远程端点发送数据时,通过这个引用来调用Channel相应的方法;即使当时有很多线程都在使用它也不会出现多线程问题;而且,消息一定会按照顺序发送出去.

        二: 我们在业务开发中,不要将长时间执行的耗时任务放入到EventLoop的执行队列中,因为它将会一直阻塞该线程所对应的所有Channel上的其他任务,如果我们需要进行阻塞调用或是耗时的操作,可以使用一个专门的线程池来处理.

        通常会有两种方法

        1.在ChannelHandler的回调方法中,使用自己定义的线程池,这样就可以实现异步调用

        2.借助于Netty提供的向ChannelPipeline添加ChannelHandler时调用的addLast方法来传递EventExecutor.

        这个也说明了,默认情况下,调用addLast(handler),ChannelHandler中的回调方法都是由I/O线程执行的,如果调用ChannelPipeline addlast(EventExecutorGroup group,ChannelHandler...handler);方法,那么ChannelHandler中的回调方法就是由参数中的group线程组来执行的.

        此外,JDK所提供的Future只能通过手工方式检查执行结果,而这个操作是会阻塞的;

        Netty针对ChannelFuture进行了增强,通过ChannelFutueListener以回调的方式来获取执行结果,去除了手工检查阻塞的操作;

        但同时ChannelFutureListener的operationComplete方法是由I/O线程执行的,因此要注意的是不要在这里执行耗时操作.

多通道协议有哪些?

       多通道协议,在TCP三次握手后,协议双方会“私下”协商一个或多个通道,用于传输信令或数据。例如:FTP、influxdb源码分析H.、Netty。

       Netty的主要目的是基于NIO构建具有网络和业务逻辑组件的分离和松耦合的高性能协议服务器。它可以实现多种协议,例如HTTP或自己的特定协议。

       Netty有一系列丰富的特性:有一套统一的API来处理异步和同步编程模式;使用非常灵活;简单但却强大的线程机制;业务组件分离方便重用;极小的缩减不必要的Memory Copy。

扩展资料

       netty核心组件

       1、Channel

       Channel是Java NIO的基础。表示一个开放的开源网站设计源码连接,能够执行IO操作,例如读取和写入。简单的说,Channel 就是代表连接,实体之间的连接,程序之间的连接,文件之间的连接,设备之间的连接。同时也是数据入站和出站的载体。

       2、Future

       Netty 通道中的每个IO操作都是非阻塞的。这意味着调用后立即返回所有操作。标准Java库中有一个Future接口,但是源码编程的教学对于Netty而言并不方便-我们只能向Future询问操作的完成情况,或在操作完成之前阻塞当前线程。这就是Netty拥有自己的ChannelFuture接口的原因。可以将回调传递给ChannelFuture,该回调将在操作完成时被调用。

Netty中的Channel之数据冲刷与线程安全(writeAndFlush)

       在Netty框架中,`ChannelHandlerContext`用于处理与`Channel`交互。要了解数据冲刷与线程安全,需先理解`Channel`及其相关组件。

       数据冲刷通常在`channelRead`方法中进行。在这个方法中,可利用`ChannelHandlerContext`获取`Channel`实例,从而冲刷数据。

       冲刷数据前,需要创建一个`ByteBuf`对象。知识付费源码网址`ByteBuf`是Netty提供的对`byte[]`和`ByteBuffer NIO`的抽象,其描述为“零个或多个字节的随机和顺序可访问的序列”。使用`Unpooled`工具类创建`ByteBuf`,然后通过`copiedBuffer`方法获取新的缓冲区,内容为指定的UTF-8编码的字符串。

       数据冲刷后,会得到一个`ChannelFuture`对象。该对象是异步I/O操作的结果,继承自`Future`接口,用于监听冲刷结果。

       要测试线程安全,可以使用`Executor`来模拟多线程执行数据冲刷。`Executor`简化了线程管理,只需传递`Runnable`即可执行任务。节节攀升指标源码测试代码中,使用`retain`方法保留`ByteBuf`对象,理解非保留和保留派生缓冲区的差异。

       Netty的`Channel`实现是线程安全的,因此可以安全地在多个线程间共享引用,保证消息顺序发送。

       总结,Netty中的`Channel`数据冲刷涉及`ByteBuf`创建、`ChannelFuture`监听及线程安全测试。深入了解这些组件及其交互,能更高效地进行网络应用开发。

netty系列之:小白福利!手把手教你做一个简单的代理服务器

       简介

       爱因斯坦说过:所有的伟大,都产生于简单的细节中。Netty为我们提供了如此强大的eventloop、channel通过对这些简单东西的有效利用,可以得到非常强大的应用程序,比如今天要讲的代理。

代理和反向代理

       相信只要是程序员应该都听过nginx服务器了,这个超级优秀nginx一个很重要的功能就是做反向代理。那么有小伙伴要问了,有反向代理肯定就有正向代理,那么他们两个有什么区别呢?

       先讲一下正向代理,举个例子,最近流量明星备受打击,虽然被打压,但是明星就是明星,一般人是见不到的,如果有人需要跟明星对话的话,需要首先经过明星的经纪人,有经纪人将话转达给明星。这个经纪人就是正向代理。我们通过正向代理来访问要访问的对象。

       那么什么是反向代理呢?比如现在出现了很多人工智能,假如我们跟智能机器人A对话,然后A把我们之间的对话转给了后面的藏着的人,这个人用他的智慧,回答了我们的对话,交由智能机器人A输出,最终实现了人工智能。这个过程就叫做反向代理。

netty实现代理的原理

       那么在netty中怎么实现这个代理服务器呢?

       首选我们首先代理服务器是一个服务器,所以我们需要在netty中使用ServerBootstrap创建一个服务器:

EventLoopGroupbossGroup=newNioEventLoopGroup(1);EventLoopGroupworkerGroup=newNioEventLoopGroup();try{ ServerBootstrapb=newServerBootstrap();b.group(bossGroup,workerGroup).channel(NioServerSocketChannel.class).handler(newLoggingHandler(LogLevel.INFO)).childHandler(newSimpleDumpProxyInitializer(REMOTE_HOST,REMOTE_PORT)).childOption(ChannelOption.AUTO_READ,false).bind(LOCAL_PORT).sync().channel().closeFuture().sync();

       在这个local服务器中,我们传入ProxyInitializer。在这个handler初始化器中,我们传入自定义的handler:

publicvoidinitChannel(SocketChannelch){ ch.pipeline().addLast(newLoggingHandler(LogLevel.INFO),newSimpleDumpProxyInboundHandler(remoteHost,remotePort));}

       在自定义的handler中,我们使用Bootstrap创建一个client,用来连接远程要代理的服务器,我们将这个client端的创建放在channelActive方法中:

//开启outbound连接Bootstrapb=newBootstrap();b.group(inboundChannel.eventLoop()).channel(ctx.channel().getClass()).handler(newSimpleDumpProxyOutboundHandler(inboundChannel)).option(ChannelOption.AUTO_READ,false);ChannelFuturef=b.connect(remoteHost,remotePort);

       然后在client建立好连接之后,就可以从inboundChannel中读取数据了:

outboundChannel=f.channel();f.addListener(future->{ if(future.isSuccess()){ //连接建立完毕,读取inbound数据inboundChannel.read();}else{ //关闭inboundchannelinboundChannel.close();}});

       因为是代理服务,所以需要将inboundChannel读取的数据,转发给outboundChannel,所以在channelRead中我们需要这样写:

publicvoidchannelRead(finalChannelHandlerContextctx,Objectmsg){ //将inboundChannel中的消息读取,并写入到outboundChannelif(outboundChannel.isActive()){ outboundChannel.writeAndFlush(msg).addListener((ChannelFutureListener)future->{ if(future.isSuccess()){ //flush成功,读取下一个消息ctx.channel().read();}else{ future.channel().close();}});}}

       当outboundChannel写成功之后,再继续inboundChannel的读取工作。

       同样对于client的outboundChannel来说,也有一个handler,在这个handler中,我们需要将outboundChannel读取到的数据反写会inboundChannel中:

publicvoidchannelRead(finalChannelHandlerContextctx,Objectmsg){ //将outboundChannel中的消息读取,并写入到inboundChannel中inboundChannel.writeAndFlush(msg).addListener((ChannelFutureListener)future->{ if(future.isSuccess()){ ctx.channel().read();}else{ future.channel().close();}});}

       当inboundChannel写成功之后,再继续outboundChannel的读取工作。

       如此一个简单的代理服务器就完成了。

实战

       如果我们将本地的端口,代理到www..com的端口,会发生什么情况呢?运行我们的程序,访问, 所以服务器端不认识我们的请求,从而报错。

总结

       本文的代理服务器之间简单的转发请求,并不能够处理上述的场景,那么该怎么解决上面的问题呢? 敬请期待我的后续文章!

       本文的例子可以参考:learn-netty4

       最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧等你来发现!

       欢迎关注我的公众号:「程序那些事」,懂技术,更懂你!