Netty中的责任链

设计模式 - 责任链模式

责任链模式(Chain of Responsibility Pattern)是一种是行为型设计模式,它为请求创建了一个处理对象的链。其链中每一个节点都看作是一个对象,每个节点处理的请求均不同,且内部自动维护一个下一节点对象。当一个请求从链式的首端发出时,会沿着链的路径依次传递给每一个节点对象,直至有对象处理这个请求为止。

责任链模式主要解决了发起请求和具体处理请求的过程解耦,职责链上的处理者负责处理请求,用户只需将请求发送到职责链上即可,无需关心请求的处理细节和请求的传递。

责任链模式的实现

责任链模式的实现主要有四个要素:处理器抽象类,具体的处理器实现类,保存处理器信息,处理执行。

伪代码示例:

  1. // *** 集合形式存储 类似tomcat中的filters ***
  2. // 处理器抽象类
  3. class AbstractHandler{void doHandler(Object arg0)}
  4. // 处理器具体实现类
  5. class Handler1 extends AbstractHandler{assert coutine;}
  6. class Handler2 extends AbstractHandler{assert coutine;}
  7. class Handler3 extends AbstractHandler{assert coutine;}
  8. // 创建集合并存储所有处理器实例信息
  9. List handlers = new List();
  10. handlers.add(handler1, handler2, handler3);
  11. // 处理请求,调用处理器
  12. void process(request){
  13. for(handler in handlers){
  14. handler.doHandler(request);
  15. }
  16. }
  17. // 发起请求调用,通过责任链处理请求
  18. call.process(request);
  19. // *** 链表形式调用 netty中的用法 ***
  20. // 处理器抽象类
  21. class AbstractHandler{
  22. AbstractHandler next;//下一节点
  23. void doHandler(Object arg0)
  24. }
  25. // 处理器具体实现类
  26. class Handler1 extends AbstractHandler{assert coutine;}
  27. class Handler2 extends AbstractHandler{assert coutine;}
  28. class Handler3 extends AbstractHandler{assert coutine;}
  29. // 将处理器串成链表存储
  30. pipeline = 头[handler1 -> handler2 -> handler3]尾;
  31. // 处理请求,从头到尾调用处理器
  32. void process(request){
  33. handler = pipeline.findOne; //查找第一个
  34. while(handler != null){
  35. handler.doHandler(request);
  36. handler = handler.next;
  37. }
  38. }

链表形式的责任链实现的具体代码示例:

  1. // 链表形式调用 netty中的用法
  2. public class PipelineDemo {
  3. // 初始化的时候造一个head,作为责任链的开始,但是并没有具体的处理
  4. public HandlerChainContext head =
  5. new HandlerChainContext(
  6. new AbstractHandler() {
  7. @Override
  8. void doHandler(HandlerChainContext handlerChainContext, Object arg0) {
  9. handlerChainContext.runNext(arg0);
  10. }
  11. });
  12. public void processRequest(Object arg0) {
  13. this.head.handler(arg0);
  14. }
  15. public void addLast(AbstractHandler handler) {
  16. HandlerChainContext context = head;
  17. while (context.next != null) {
  18. context = context.next;
  19. }
  20. context.next = new HandlerChainContext(handler);
  21. }
  22. public static void main(String[] args) {
  23. PipelineDemo pipelineChainDemo = new PipelineDemo();
  24. pipelineChainDemo.addLast(new Handler2());
  25. pipelineChainDemo.addLast(new Handler1());
  26. pipelineChainDemo.addLast(new Handler1());
  27. pipelineChainDemo.addLast(new Handler2());
  28. // 发起请求
  29. pipelineChainDemo.processRequest("火车呜呜呜~~");
  30. }
  31. }
  32. // handler上下文,我主要负责维护链,和链的执行
  33. class HandlerChainContext {
  34. HandlerChainContext next; // 下一节点
  35. AbstractHandler handler;
  36. public HandlerChainContext(AbstractHandler handler) {
  37. this.handler = handler;
  38. }
  39. void handler(Object arg0) {
  40. this.handler.doHandler(this, arg0);
  41. }
  42. // 继续执行下一个
  43. void runNext(Object arg0) {
  44. if (this.next != null) {
  45. this.next.handler(arg0);
  46. }
  47. }
  48. }
  49. // 处理器抽象类
  50. abstract class AbstractHandler {
  51. // 处理器
  52. abstract void doHandler(HandlerChainContext handlerChainContext, Object arg0);
  53. }
  54. // 处理器具体实现类
  55. class Handler1 extends AbstractHandler {
  56. @Override
  57. void doHandler(HandlerChainContext handlerChainContext, Object arg0) {
  58. arg0 = arg0.toString() + "..handler1的小尾巴.....";
  59. System.out.println("我是Handler1的实例,我在处理:" + arg0);
  60. // 继续执行下一个
  61. handlerChainContext.runNext(arg0);
  62. }
  63. }
  64. // 处理器具体实现类
  65. class Handler2 extends AbstractHandler {
  66. @Override
  67. void doHandler(HandlerChainContext handlerChainContext, Object arg0) {
  68. arg0 = arg0.toString() + "..handler2的小尾巴.....";
  69. System.out.println("我是Handler2的实例,我在处理:" + arg0);
  70. // 继续执行下一个
  71. handlerChainContext.runNext(arg0);
  72. }
  73. }
  74. // 输出结果:
  75. 我是Handler2的实例,我在处理:火车呜呜呜~~..handler2的小尾巴.....
  76. 我是Handler1的实例,我在处理:火车呜呜呜~~..handler2的小尾巴.......handler1的小尾巴.....
  77. 我是Handler1的实例,我在处理:火车呜呜呜~~..handler2的小尾巴.......handler1的小尾巴.......handler1的小尾巴.....
  78. 我是Handler2的实例,我在处理:火车呜呜呜~~..handler2的小尾巴.......handler1的小尾巴.......handler1的小尾巴.......handler2的小尾巴.....

Netty中的ChannelPipeline责任链

pipeline管道保存了通道所有处理器信息,创建channel时自动创建一个专有的pipeline,入站事件和出站事件会调用pipeline上的处理器

入站事件和出站事件

入站事件:通常指IO线程生成了入站数据
(通俗理解:从socket底层自己往上冒上来的事件都是入站)
比如EventLoop收到selector的OP_READ事件,入站处理器调用socketChannel.read(ByteBuffer)接受到数据后,这将导致通道的ChannelPipeline中包含的下一个中的channelRead方法被调用

出站事件:通常指IO线程执行实际的输出操作
(通俗理解:想主动往socket底层操作的事件的都是出站)
比如bind方法用意时请求server socket绑定到给定的SocketAddress,这将导致通道的ChannelPipeline中包含的下一个出站处理器中的bind方法被调用

Pipeline中的handler

ChannelHandler:用于处理IO事件或拦截IO操作,并转发到ChannelPipeline中的下一个处理器。这个顶级接口定义功能很弱,事件使用时会实现下面两大子接口:处理入站IO事件的ChannelInBoundHandler,处理出站IO事件的ChannelOutBoundHandler

适配器:为了开发的方便,避免所有的handler去实现一遍接口方法,Netty提供了简单的实现类:
ChannelInBoundHandlerAdapter处理入站IO事件,
ChannelOutBoundHandlerAdapter处理出站IO事件,
ChannelDuplexHandler支持同时处理入站和出站事件

ChannelHandlerContext:实际存储在Pipeline中的对象并非ChannelHandler,而是上下文对象,将handler包裹在上下文对象中,通过上下文属的ChannelPipeline交互,向上或向下传递事件或者修改pipeline都是通过上下文对象。

ChannelPipeline是线程安全的,ChannelHandler可以在任何时候添加或删除。
例如,可以在即将交换敏感信息时插入加密处理程序,并在交换后删除。
一般操作,初始化的时候增加进去,较少删除。

Pipeline中管理handler的API:

handler的执行分析

分析register入站事件的处理

分析bind出站事件的处理

分析accept入站事件的处理

分析read入站事件的处理

小结

用户在管道中有一个或多个channelhandler来接受IO事件和请求IO操作

一个典型的服务器会在每个通道的管道中都有以下处理程序,但是根据协议和业务逻辑的复杂性和特征,可能会有所不同:
协议解码器 - 将二进制数据转换为Java对象
协议编码器 - 将Java对象转换成二进制数据
业务逻辑处理器 - 执行实际的业务逻辑

责任链模式的运用,保证了Netty的高度可扩展性

Java网络编程--Netty中的责任链的更多相关文章

  1. 网络编程Netty入门:责任链模式介绍

    目录 责任链模式 责任链模式的简单实现 Netty中的ChannelPipeline责任链 服务端接收客户端连接 pipeline初始化 入站事件和出站事件 Pipeline中的Handler Pip ...

  2. Java网络编程 -- Netty中的ByteBuf

    由于JDK中提供的ByteBuffer无法动态扩容,并且API使用复杂等原因,Netty中提供了ByteBuf.Bytebuf的API操作更加便捷,可以动态扩容,提供了多种ByteBuf的实现,以及高 ...

  3. Netty中的责任链模式

    适用场景: 对于一个请求来说,如果有个对象都有机会处理它,而且不明确到底是哪个对象会处理请求时,我们可以考虑使用责任链模式实现它,让请求从链的头部往后移动,直到链上的一个节点成功处理了它为止 优点: ...

  4. Java网络编程 -- Netty入门

    Netty简介 Netty是一个高性能,高可扩展性的异步事件驱动的网络应用程序框架,它极大的简化了TCP和UDP客户端和服务器端网络开发.它是一个NIO框架,对Java NIO进行了良好的封装.作为一 ...

  5. Java网络编程和NIO详解9:基于NIO的网络编程框架Netty

    Java网络编程和NIO详解9:基于NIO的网络编程框架Netty 转自https://sylvanassun.github.io/2017/11/30/2017-11-30-netty_introd ...

  6. Java网络编程基础(Netty预备知识)

    今天在家休息,闲来无事,写篇博客,陶冶下情操~~~ =================我是分割线================ 最近在重新学习Java网络编程基础,以便后续进行Netty的学习. 整 ...

  7. Java网络编程和NIO详解1:JAVA 中原生的 socket 通信机制

    Java网络编程和NIO详解1:JAVA 中原生的 socket 通信机制 JAVA 中原生的 socket 通信机制 摘要:本文属于原创,欢迎转载,转载请保留出处:https://github.co ...

  8. Java网络编程与NIO详解11:Tomcat中的Connector源码分析(NIO)

    本文转载 https://www.javadoop.com 本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.c ...

  9. Java网络编程与NIO详解10:深度解读Tomcat中的NIO模型

    本文转自:http://www.sohu.com/a/203838233_827544 本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 ht ...

随机推荐

  1. windows的磁盘操作之七——获取当前所有的物理磁盘号 加备注

     windows的磁盘操作之七--获取当前所有的物理磁盘号 2011-07-28 17:47:56 标签:windows API DeviceIoControl 物理磁盘 驱动器号 原创作品,允许转载 ...

  2. win10下配置chromedrive。

    0x01:查看自己chrome的版本号 点击chrome右上角菜单栏,帮助,关于Google chrome,在这里,你可以看到自己chrome的版本号. 0x02:下载对应的chrome drive ...

  3. 三维动画形变算法(Linear rotation-invariant coordinates和As-Rigid-As-Possible)

    在三维网格形变算法中,个人比较喜欢下面两个算法,算法的效果都比较不错, 不同的是文章[Lipman et al. 2005]算法对控制点平移不太敏感.下面分别介绍这两个算法: 文章[Lipman et ...

  4. unity_UGUI养成之路02

    1.技能的冷确效果 2.背包的分页效果 1创建背包的总面板,并添加ToggleGroup组件 2.物品面板的实现 3.背包分页的实现 注意:添加了Toggle组件的游戏对象不能再添加button组件. ...

  5. 基于Taro与Typescript开发的网易云音乐小程序

    基于Taro与网易云音乐api开发,技术栈主要是:typescript+taro+taro-ui+redux,目前主要是着重小程序端的展示,主要也是借此项目强化下上述几个技术栈的使用,通过这个项目也可 ...

  6. 2. Sentinel源码分析—Sentinel是如何进行流量统计的?

    这一篇我还是继续上一篇没有讲完的内容,先上一个例子: private static final int threadCount = 100; public static void main(Strin ...

  7. python控制窗口移动(画圆)

    import win32con import win32gui import time import math notepad = win32gui.FindWindow("Notepad& ...

  8. Badboy中创建Suite, test, step和Template

    参考: http://leafwf.blog.51cto.com/872759/1111744 http://www.51testing.com/html/00/130600-1367743.html ...

  9. 牛客2018国庆集训派对Day3 I Metropolis 多源最短路径

    传送门:https://www.nowcoder.com/acm/contest/203/I 题意: 求每个大都会到最近的一个大都会的距离. 思路: 把每个大都会设为起点,跑一遍最短路.在跑最短路的时 ...

  10. POJ 3268 Silver Cow Party 单向最短路

    Silver Cow Party Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 22864   Accepted: 1044 ...