`
Donald_Draper
  • 浏览: 981175 次
社区版块
存档分类
最新评论

netty 通道处理器上下文定义

阅读更多
netty Inboudn/Outbound通道Invoker:http://donald-draper.iteye.com/blog/2388233
netty 异步任务-ChannelFuture:http://donald-draper.iteye.com/blog/2388297
netty 管道线定义-ChannelPipeline:http://donald-draper.iteye.com/blog/2388453
netty 默认Channel管道线初始化:http://donald-draper.iteye.com/blog/2388613
netty 默认Channel管道线-添加通道处理器:http://donald-draper.iteye.com/blog/2388726
netty 默认Channel管道线-通道处理器移除与替换:http://donald-draper.iteye.com/blog/2388793
netty 默认Channel管道线-Inbound和Outbound事件处理:http://donald-draper.iteye.com/blog/2389148
引言:
在前面的几篇文章中我们看了Channle管道的默认实现,每个通道拥有一个Channel管道,管道用于管理通道处理器,管道以上下文模式管理通道处理器,每个通道上下文拥有一个前驱和后继上下文,可以说,即通道上下文在管道中是一个双向链表,上下文链表的头部为HeadContext,尾部为TailContext。管道主要通过上下文的inbound和oubound标志判断上下文类型。管道处理Inbound事件首先从头部上下文开始,直到尾部上下文,最后默认直接丢弃。 管道处理Outbound相关事件,从尾部上下文到头部上下文,到达头部时,交由上下文属管道关联的Channel的Unsafe处理。
今天我们来看一下通道处理器下文接口的定义:
package io.netty.channel;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.netty.util.Attribute;
import io.netty.util.AttributeKey;
import io.netty.util.AttributeMap;
import io.netty.util.concurrent.EventExecutor;

import java.nio.channels.Channels;

/**
 * Enables a {@link ChannelHandler} to interact with its {@link ChannelPipeline}
 * and other handlers. Among other things a handler can notify the next {@link ChannelHandler} in the
 * {@link ChannelPipeline} as well as modify the {@link ChannelPipeline} it belongs to dynamically.
 *通道处理器上下文ChannelHandlerContext,使通道处理器可以与管道和管道中其他处理器进行交互。
 当IO事件发生时,处理可以将事件转发给所属管道的下一个通道处理器,同时可以动态修改处理器所属的管道。
 * <h3>Notify</h3>
 *通知
 * You can notify the closest handler in the same {@link ChannelPipeline} by calling one of the various methods
 * provided here.
 *你可以使用提供的方法,通知邻近的通道处理器,事件触发。
 * Please refer to {@link ChannelPipeline} to understand how an event flows.
 *同时可以参考管道来理解事件流
 * <h3>Modifying a pipeline</h3>
 *修改管道
 * You can get the {@link ChannelPipeline} your handler belongs to by calling
 * {@link #pipeline()}.  A non-trivial application could insert, remove, or
 * replace handlers in the pipeline dynamically at runtime.
 *可以使用通道处理器上下文的#pipeline方法,获取处理器所属管道。引用在运行时环境
 下,可以插入移除替换管道中的处理器
 * <h3>Retrieving for later use</h3>
 *用于获取相关信息
 * You can keep the {@link ChannelHandlerContext} for later use, such as
 * triggering an event outside the handler methods, even from a different thread.
 在通道处理器方法之外的事件触发,甚至一个不同的线程中,你可以保存通道处理器上下文,以便使用。
 * <pre>
 下面是一个保存上下文信息的实例
 * public class MyHandler extends {@link ChannelDuplexHandler} {
 *
 *     <b>private {@link ChannelHandlerContext} ctx;</b>
 *
 *     public void beforeAdd({@link ChannelHandlerContext} ctx) {
 *         <b>this.ctx = ctx;</b>
 *     }
 *
 *     public void login(String username, password) {
 *         ctx.write(new LoginMessage(username, password));
 *     }
 *     ...
 * }
 * </pre>
 *
 * <h3>Storing stateful information</h3>
 *存储信息,不过当前已经被遗弃
 * {@link #attr(AttributeKey)} allow you to
 * store and access stateful information that is related with a handler and its
 * context.  Please refer to {@link ChannelHandler} to learn various recommended
 * ways to manage stateful information.
 *#attr(AttributeKey)方法运行你存储与通道处理器和上下文关联的信息。参考通道处理器学习更多管理
 处理器和上下文属性方式。
 * <h3>A handler can have more than one context</h3>
 *一个处理可以有多个关联上下文
 * Please note that a {@link ChannelHandler} instance can be added to more than
 * one {@link ChannelPipeline}.  It means a single {@link ChannelHandler}
 * instance can have more than one {@link ChannelHandlerContext} and therefore
 * the single instance can be invoked with different
 * {@link ChannelHandlerContext}s if it is added to one or more
 * {@link ChannelPipeline}s more than once.
 需要注意的是,通道处理器实例可以添加到多个管道中。意味着一个通道处理器可以有多个上下文,
 如果通道处理器添加不止一个管道中,那么实例可以被多个上下文调用。
 * <p>
 * For example, the following handler will have as many independent {@link AttributeKey}s
 * as how many times it is added to pipelines, regardless if it is added to the
 * same pipeline multiple times or added to different pipelines multiple times:
 比如,下面一个处理器由于多次添加到通道中,可以有很多独立的属性,不管是添加一个通道多次,
 还是不同的管道多次。
 * <pre>
 * public class FactorialHandler extends {@link ChannelInboundHandlerAdapter} {
 *
 *   private final {@link AttributeKey}<{@link Integer}> counter = {@link AttributeKey}.valueOf("counter");
 *
 *   // This handler will receive a sequence of increasing integers starting
 *   // from 1.
 *   {@code @Override}
 *   public void channelRead({@link ChannelHandlerContext} ctx, Object msg) {
 *     Integer a = ctx.attr(counter).get();
 *
 *     if (a == null) {
 *       a = 1;
 *     }
 *
 *     attr.set(a * (Integer) msg);
 *   }
 * }
 *
 * // Different context objects are given to "f1", "f2", "f3", and "f4" even if
 * // they refer to the same handler instance.  Because the FactorialHandler
 * // stores its state in a context object (using an {@link AttributeKey}), the factorial is
 * // calculated correctly 4 times once the two pipelines (p1 and p2) are active.
 * FactorialHandler fh = new FactorialHandler();
 *
 即使参考相同的处理器实例,但相应的上下文 "f1", "f2", "f3", and "f4",并不相同。
 由于处理器存储着一个上下文属性,一旦管道线激活,将会调用4次。
 * {@link ChannelPipeline} p1 = {@link Channels}.pipeline();
 * p1.addLast("f1", fh);
 * p1.addLast("f2", fh);
 *
 * {@link ChannelPipeline} p2 = {@link Channels}.pipeline();
 * p2.addLast("f3", fh);
 * p2.addLast("f4", fh);
 * </pre>
 *
 * <h3>Additional resources worth reading</h3>
 * <p>另外值得阅读的资源
 * Please refer to the {@link ChannelHandler}, and
 * {@link ChannelPipeline} to find out more about inbound and outbound operations,
 * what fundamental differences they have, how they flow in a  pipeline,  and how to handle
 * the operation in your application.
 请参考通道处理器和管道,获取更多的Inbound和Outbound操作信息,及两种操作的基本不同点,如何在管道中传输和
 在应用中如何处理操作。

 */
public interface ChannelHandlerContext extends AttributeMap, ChannelInboundInvoker, ChannelOutboundInvoker {

    /**
     * Return the {@link Channel} which is bound to the {@link ChannelHandlerContext}.
     获取通道处理器上下文关联通道
     */
    Channel channel();

    /**
     * Returns the {@link EventExecutor} which is used to execute an arbitrary task.
     获取上下文事件执行器,用于执行任务
     */
    EventExecutor executor();

    /**
     * The unique name of the {@link ChannelHandlerContext}.The name was used when then {@link ChannelHandler}
     * was added to the {@link ChannelPipeline}. This name can also be used to access the registered
     * {@link ChannelHandler} from the {@link ChannelPipeline}.
     通道上下文的名字,即通道处理器添加到管道时的名字。此名字可以从管道获取对应的通道处理器
     */
    String name();

    /**
     * The {@link ChannelHandler} that is bound this {@link ChannelHandlerContext}.
     获取上下文关联的通道处理器
     */
    ChannelHandler handler();

    /**
     * Return {@code true} if the {@link ChannelHandler} which belongs to this context was removed
     * from the {@link ChannelPipeline}. Note that this method is only meant to be called from with in the
     * {@link EventLoop}.
     判断当前通道处理器关联上下文是否从管道移除。此方法在事件循环中调用
     */
    boolean isRemoved();
   //触发Inbound事件方法
    @Override
    ChannelHandlerContext fireChannelRegistered();

    @Override
    ChannelHandlerContext fireChannelUnregistered();

    @Override
    ChannelHandlerContext fireChannelActive();

    @Override
    ChannelHandlerContext fireChannelInactive();

    @Override
    ChannelHandlerContext fireExceptionCaught(Throwable cause);

    @Override
    ChannelHandlerContext fireUserEventTriggered(Object evt);

    @Override
    ChannelHandlerContext fireChannelRead(Object msg);

    @Override
    ChannelHandlerContext fireChannelReadComplete();

    @Override
    ChannelHandlerContext fireChannelWritabilityChanged();

    @Override
    ChannelHandlerContext read();

    @Override
    ChannelHandlerContext flush();

    /**
     * Return the assigned {@link ChannelPipeline}
     获取所属管道
     */
    ChannelPipeline pipeline();

    /**
     * Return the assigned {@link ByteBufAllocator} which will be used to allocate {@link ByteBuf}s.
     获取通道上下文的字节buf分配器,用于分配buf
     */
    ByteBufAllocator alloc();

    /**
     * @deprecated Use {@link Channel#attr(AttributeKey)}
     获取指定key的属性值,已丢弃
     */
    @Deprecated
    @Override
    <T> Attribute<T> attr(AttributeKey<T> key);

    /**
     * @deprecated Use {@link Channel#hasAttr(AttributeKey)}
     判断是否拥有属性值
     */
    @Deprecated
    @Override
    <T> boolean hasAttr(AttributeKey<T> key);
}

总结:
通道处理器上下文ChannelHandlerContext,使通道处理器可以与管道和管道中其他处理器进行交互。当IO事件发生时,处理可以将事件转发给所属管道的下一个通道处理器,同时可以动态修改处理器所属的管道。通过上下文可以获取关联通道,处理器,事件执行器,上下文名,所属管道等信息。同时可以通过AttributeKey存储上下文属性,用alloc方法获取通道上下文的字节buf分配器,用于分配buf。


附:

//AttributeMap
package io.netty.util;

/**
 * Holds {@link Attribute}s which can be accessed via {@link AttributeKey}.
 *
 * Implementations must be Thread-safe.
 */
public interface AttributeMap {
    /**
     * Get the {@link Attribute} for the given {@link AttributeKey}. This method will never return null, but may return
     * an {@link Attribute} which does not have a value set yet.
     */
    <T> Attribute<T> attr(AttributeKey<T> key);

    /**
     * Returns {@code} true if and only if the given {@link Attribute} exists in this {@link AttributeMap}.
     */
    <T> boolean hasAttr(AttributeKey<T> key);
}

//AttributeKey
/**
 * Key which can be used to access {@link Attribute} out of the {@link AttributeMap}. Be aware that it is not be
 * possible to have multiple keys with the same name.
 *
 * @param <T>   the type of the {@link Attribute} which can be accessed via this {@link AttributeKey}.
 */
@SuppressWarnings("UnusedDeclaration") // 'T' is used only at compile time
public final class AttributeKey<T> extends AbstractConstant<AttributeKey<T>> {

    private static final ConstantPool<AttributeKey<Object>> pool = new ConstantPool<AttributeKey<Object>>() {


//ConstantPool
/**
 * A pool of {@link Constant}s.
 *
 * @param <T> the type of the constant
 */
public abstract class ConstantPool<T extends Constant<T>> {

    private final ConcurrentMap<String, T> constants = PlatformDependent.newConcurrentHashMap();

    private final AtomicInteger nextId = new AtomicInteger(1);


//ByteBufAllocator
/**
 * Implementations are responsible to allocate buffers. Implementations of this interface are expected to be
 * thread-safe.
 */
public interface ByteBufAllocator {

    ByteBufAllocator DEFAULT = ByteBufUtil.DEFAULT_ALLOCATOR;

    /**
     * Allocate a {@link ByteBuf}. If it is a direct or heap buffer
     * depends on the actual implementation.
     */
    ByteBuf buffer();

    /**
     * Allocate a {@link ByteBuf} with the given initial capacity.
     * If it is a direct or heap buffer depends on the actual implementation.
     */
    ByteBuf buffer(int initialCapacity);

    /**
     * Allocate a {@link ByteBuf} with the given initial capacity and the given
     * maximal capacity. If it is a direct or heap buffer depends on the actual
     * implementation.
     */
    ByteBuf buffer(int initialCapacity, int maxCapacity);

    /**
     * Allocate a {@link ByteBuf}, preferably a direct buffer which is suitable for I/O.
     */
    ByteBuf ioBuffer();

    /**
     * Allocate a {@link ByteBuf}, preferably a direct buffer which is suitable for I/O.
     */
    ByteBuf ioBuffer(int initialCapacity);

    /**
     * Allocate a {@link ByteBuf}, preferably a direct buffer which is suitable for I/O.
     */
    ByteBuf ioBuffer(int initialCapacity, int maxCapacity);

    /**
     * Allocate a heap {@link ByteBuf}.
     */
    ByteBuf heapBuffer();

    /**
     * Allocate a heap {@link ByteBuf} with the given initial capacity.
     */
    ByteBuf heapBuffer(int initialCapacity);

    /**
     * Allocate a heap {@link ByteBuf} with the given initial capacity and the given
     * maximal capacity.
     */
    ByteBuf heapBuffer(int initialCapacity, int maxCapacity);

    /**
     * Allocate a direct {@link ByteBuf}.
     */
    ByteBuf directBuffer();

    /**
     * Allocate a direct {@link ByteBuf} with the given initial capacity.
     */
    ByteBuf directBuffer(int initialCapacity);

    /**
     * Allocate a direct {@link ByteBuf} with the given initial capacity and the given
     * maximal capacity.
     */
    ByteBuf directBuffer(int initialCapacity, int maxCapacity);

    /**
     * Allocate a {@link CompositeByteBuf}.
     * If it is a direct or heap buffer depends on the actual implementation.
     */
    CompositeByteBuf compositeBuffer();

    /**
     * Allocate a {@link CompositeByteBuf} with the given maximum number of components that can be stored in it.
     * If it is a direct or heap buffer depends on the actual implementation.
     */
    CompositeByteBuf compositeBuffer(int maxNumComponents);

    /**
     * Allocate a heap {@link CompositeByteBuf}.
     */
    CompositeByteBuf compositeHeapBuffer();

    /**
     * Allocate a heap {@link CompositeByteBuf} with the given maximum number of components that can be stored in it.
     */
    CompositeByteBuf compositeHeapBuffer(int maxNumComponents);

    /**
     * Allocate a direct {@link CompositeByteBuf}.
     */
    CompositeByteBuf compositeDirectBuffer();

    /**
     * Allocate a direct {@link CompositeByteBuf} with the given maximum number of components that can be stored in it.
     */
    CompositeByteBuf compositeDirectBuffer(int maxNumComponents);

    /**
     * Returns {@code true} if direct {@link ByteBuf}'s are pooled
     */
    boolean isDirectBufferPooled();

    /**
     * Calculate the new capacity of a {@link ByteBuf} that is used when a {@link ByteBuf} needs to expand by the
     * {@code minNewCapacity} with {@code maxCapacity} as upper-bound.
     */
    int calculateNewCapacity(int minNewCapacity, int maxCapacity);
 }

0
0
分享到:
评论

相关推荐

    Netty架构源码剖析_netty_

    这种模型避免了频繁的上下文切换,提高了系统性能。 深入源码分析,我们可以看到Netty如何优雅地处理了线程安全、内存池管理、心跳机制、解码编码、零拷贝等高级特性。例如,Netty通过内部的DirectBufferPool和...

    netty-4.1.17.Final.jar

    它使用了单线程事件循环(Event Loop)处理多个连接,大大减少了线程上下文切换的开销。同时,Netty的线程池设计可以确保并发处理大量连接时的高效性。 标签"java"表明这是Java编程语言的一部分,"netty-all"意味着...

    Java_NIO框架Netty教程.pdf

    Netty会调用`channelConnected`方法并传入`ChannelHandlerContext`(通道处理器上下文)和`ChannelStateEvent`(通道状态事件),在该方法中编写处理逻辑。 同样的,客户端需要使用`ClientBootstrap`来启动客户端,...

    整合netty实时通讯

    这个模型允许高效地处理并发连接,减少了线程上下文切换的开销。 - Netty 提供了一套丰富的 ChannelHandler,用于处理进/出站数据,如解码、编码、日志记录等。这些处理器形成一个处理管道,数据流经管道中的每个...

    netty需要的包

    4. **线程模型优化**: 通过EventLoopGroup,Netty能够高效地分配线程资源,避免过多线程间的上下文切换。 三、Netty的使用 1. **创建ServerBootstrap**: 服务器启动器,用于配置服务器的参数,如事件循环组、绑定...

    netty4与spring集成

    1. **Spring 上下文**: 在集成中,我们需要将 Netty 服务器配置到 Spring 的上下文中,这样可以通过 Spring 管理 Netty 的生命周期,如启动、停止等。这可以通过创建一个 `ApplicationContext` 并在其内部注册 Netty...

    Netty example

    - **ChannelHandlerContext**: 在 ChannelHandler 之间传递上下文信息,用于触发事件或调用其他处理器。 - **Pipeline**: 一个处理器链,当事件发生时,会在链上顺序执行处理器。 此外,Netty 还支持多种协议,如 ...

    netty框架,服务端、客户端代码示例

    当数据到达时,事件会被添加到事件循环的队列中,由事件循环进行处理,这样可以避免线程上下文切换的开销。同时,Netty的 ByteBuf 提供了零拷贝特性,减少了内存复制,提高了性能。 在实际项目中,Netty可以用来...

    java netty学习资料

    2. **ChannelHandlerContext**:它在处理链中提供了上下文信息,允许处理器互相通信并处理I/O事件。 3. **ByteBuf**:Netty的高效字节缓冲区,用于存储和传输网络数据。 4. **ChannelPipeline**:一个处理器链,每个...

    Netty5学习指南

    通过使用NIO(非阻塞I/O),Netty可以高效地处理I/O操作,避免了线程上下文切换带来的开销。此外,Netty还包含了一套灵活的缓冲区机制(ByteBuf),用于高效地管理网络数据的读写。 Netty 的架构基于事件驱动模型,...

    netty通讯示例

    3. **ChannelHandlerContext**:在事件处理器之间传递上下文信息,可以用来调用`writeAndFlush()`等方法进行数据发送。 4. **ByteBuf**:Netty的高效字节缓冲区,用于数据读写。 5. **Handler的生命周期方法**:如`...

    netty聊天室实例

    - 在处理链中,`ChannelHandlerContext`是上下文对象,用于触发I/O事件、获取引用到下一个处理器、关闭通道等。 6. **多路复用与NIO选择器**: - Netty利用Java NIO的多路复用器(Selector)来监听和调度多个连接...

    java应用netty服务端和客户端

    4. **ChannelHandlerContext**:在Handler之间传递,提供上下文信息,用于发送和接收数据,以及与管道进行交互。 5. **ChannelInboundHandlerAdapter** 和 `ChannelOutboundHandlerAdapter`:分别处理入站和出站事件...

    netty4.x 与 spring 集成

    - 可以使用`EventExecutor`来提交任务到Netty的工作线程,确保任务在正确的上下文中执行。 6. **日志集成** - 集成Spring的Log4j或Logback,统一应用的日志输出。 - Netty有内置的日志框架,需要配置以使用...

    netty-3.7.0官方API所有jar包

    - **ChannelHandlerContext**: 在处理链中的上下文对象,用于触发和处理事件。 - **Pipeline**: 处理链,由多个处理器(ChannelHandler)组成,每个处理器负责特定的处理任务。 5. **应用场景**: Netty广泛应用...

    netty实战-netty.zip

    10. **零拷贝**:Netty通过组合使用DirectByteBuffer和FileRegion,实现了数据传输的零拷贝,减少了CPU上下文切换和内存复制,提升了效率。 通过“netty实战-netty”这个压缩包,开发者可以学习到如何使用上述技术...

    Netty简介.pdf(长连接)

    4. **ChannelHandlerContext**:上下文对象,用于在事件处理器之间传递消息和调用处理方法。 5. **Pipeline**:处理器链,每个连接都有一个处理器链,处理进来的数据或触发出去的操作。 Netty的异步模型基于Java ...

    Netty全套PDF

    1. **异步事件驱动**:Netty采用了事件驱动模型,通过EventLoop和EventLoopGroup来处理I/O事件,这种模型可以显著提高并发性能,减少线程间的上下文切换。 2. **零拷贝**:Netty实现了零拷贝技术,通过直接内存和...

    Netty权威指南 第2版 带书签目录 完整版

    - 这种设计可以优化资源分配,避免过多线程导致的上下文切换开销。 5. **编码与解码**: - Netty提供了一系列的编解码器,如LengthFieldBasedFrameDecoder用于处理带有长度字段的协议,LineBasedFrameDecoder用于...

    springboot+netty 实现简单的一对一聊天

    - 为每个用户创建一个会话上下文,存储用户信息和连接状态,以支持一对一聊天。 4. **客户端连接与身份验证**: - 客户端使用JavaScript的WebSocket API连接到服务器,通常会携带一个认证令牌。 - 服务器端在`...

Global site tag (gtag.js) - Google Analytics