Netty in the chain of responsibility pattern

Applicable scene:

  • For a request, if there is one object a chance to handle it, but in the end is not clear which object will handle the request, we can consider using the Chain of Responsibility pattern to achieve it, make a request to move back from the head of the chain, until a node on the chain successfully handled it so far

advantage:

  • The sender does not need to know the request sent by itself in the end will be disposed of which object to achieve a decoupling of the sender and the recipient
  • It simplifies the design of the sender object
  • You can dynamically add nodes and delete nodes

Disadvantages:

  • All requests are traversing the chain from the head, loss of performance
  • Very poor case, does not guarantee that the request will be processed

Customizing a chain of responsibility

There is no longer a pointer in java, if we want to create a linked list, this can only add class attributes in this class because we want to create a linked list, so it is necessary to work

You need to provide a set way for the current node can set your own next node

Logic processing request, abstract methods designed to allow different nodes to achieve according to their needs

public abstract class Approver {
Approver approver;
String name;
// todo 抽象父类中可以存在构造函数,但是当我们创建子类时,必须要有一个参数的构造函数,
// todo 让子类一个参数的构造函数,来给这个函数初始化
public Approver (String name){
    this.name=name;
}

public abstract void ProcessRequest(PurchaseRequest request);

// 如果当前的处理器处理不了,就会往下传播
public void setApprover( Approver approver){
    this.approver=approver;
}
}

PurchaseRequest, the request needs to be processed, according to their needs vary

Followed by nodes in different functions on the list must achieve above abstract class Approver, override its abstract methods, add their specific functions

test:

    // 创建出各个节点
    Approver1 approver1 = new Approver1();
    Approver2 approver2 = new Approver2();
    Approver3 approver3 = new Approver3();

    // 设置他们关系
    approver1.setApprover(approver2);
    approver2.setApprover(approver3);

    // 发起请求
    Client client = new Client();
    PurchaseRequest purchaseRequest = client.sendRequest();

    // 处理请求
    tom.ProcessRequest(purchaseRequest);

The request to the first node in the chain of responsibility, she will automatically propagate back down until there is a node successfully handled it

Netty chain of responsibility design

netty design of the pipeline, on the use of a chain of responsibility design pattern, the underlying data structure used doubly linked list, each of the processors in the chain will be linked together

The arrival of each client request, netty believe that all of the processor pipeline had the opportunity to deal with it, therefore, requests the stack, and start all over again next node spread, has been propagated to the end node (tail came msg node will be freed)

netty chain of responsibility pattern components

  • Responsibility processor interface
    • The pipeline processor of its realization
  • Add Remove responsibilities processor interface
  • Context
    • By this context, desired data can be obtained, properties
  • Responsibility termination mechanism
    • Each node in the pipeline, may terminate propagation of an event

netty responsibilities processor interface

Responsibility processor interface, pipeline all the handler top-level abstract interface, which provides all of the handler must be unified to add, remove, capture abnormal behavior

public interface ChannelHandler {

// todo 当handler被添加到真实的上下文中,并且准备处理事件时被调用
// todo handler 被添加进去的回调
void handlerAdded(ChannelHandlerContext ctx) throws Exception;

//  todo 是 handler 被移出的后的 回调
void handlerRemoved(ChannelHandlerContext ctx) throws Exception;

@Deprecated
void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception;

@Inherited
@Documented
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface Sharable {
    // no value
}
}

netty responsibility for processing interface, a more fine-grained partitioning done, the processor is divided into two, one is a slave processor ChannelInboundHandler, a slave processor and the other is ChannelOutboundHandlerthat the two interfaces are inherited fromChannelHandler

Add Remove responsibilities processor interface

netty All processors are finally added to the pipeline, so add an interface to delete the responsibility of the processor's behavior in netty has been stipulated in channelPipeline

public interface ChannelPipeline
        extends ChannelInboundInvoker, ChannelOutboundInvoker, Iterable<Entry<String, ChannelHandler>> {

    ChannelPipeline addFirst(String name, ChannelHandler handler);

    ChannelPipeline addFirst(EventExecutorGroup group, String name, ChannelHandler handler);

    ChannelPipeline addLast(String name, ChannelHandler handler);

    ChannelPipeline addLast(EventExecutorGroup group, String name, ChannelHandler handler);

    ChannelPipeline addBefore(String baseName, String name, ChannelHandler handler);

 ...

Context

The pipeline handler context is encapsulated in the following, the context, can easily get channel current node belongs and its thread actuator

// todo AttributeMap -- 让ChannelHandlerContext 可以存储自定义的属性
// todo ChannelInboundInvoker -- 让ChannelHandlerContext 可以进行 InBound事件的传播,读事件,read 或者是  注册事件 active事件
// todo ChannelOutboundInvoker -- 让ChannelHandlerContext 可以传播写事件
public interface ChannelHandlerContext extends AttributeMap, ChannelInboundInvoker, ChannelOutboundInvoker {
 
    // todo 获取ChannelHandlerContext所对应的这个Channel对象
    Channel channel();

    // todo 获取事件执行器
    EventExecutor executor();
...

Responsibility termination mechanism

Responsibility termination mechanism

  • Any node in the pipeline, as long as we do not go down the spread of hand, this event will terminate the current node spread
  • For inbound data, the default will be delivered to the end node, recycling, if we do not propagate to the next step, the event will be terminated in the current node, do not forget to recycle msg
  • For outbound data, with the use of unsafe target header node, the data also means that the client will write termination event

Propagation of an event

The spread of the underlying events is used for the operation of the list

private AbstractChannelHandlerContext findContextInbound() {
    AbstractChannelHandlerContext ctx = this;
    do {
        ctx = ctx.next;
    } while (!ctx.inbound);
    return ctx;
}

Guess you like

Origin www.cnblogs.com/ZhuChangwu/p/11241304.html