欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

Nginx内的设计模式解析

最编程 2024-08-05 22:12:19
...

参考书籍《nginx完全开发指南:使用C、C#和OpenResty》

PS:这里的分类只是依据模式在Nginx里的应用的层次,模式本身应用并无限制。即使这样,这种划分也不一定精准,有的模式可能跨越两个层次。所以这样的分类只是方便理解和阅读。

一、框架级别的设计模式

1. 反应器(Reactor)

反应器模式是一种I/O事件处理的设计模式,它管理多个事件源,并通过多路分离器把就绪事件分发到相应的handler,极大的提高了并发处理能力。Linux、FreeBSD里的epoll、kqueue等系统调用都是反应器模式的具体应用,是高性能Web服务器的实现基础。Nginx也正是利用了epoll、kqueue才能无阻塞地处理海量并发连接。所以反应器是nginx快速高效的根本秘密。(redis也是反应器模式)。

关于反应器和主动器,可以看我的这篇介绍

2. 外观模式(Facade)

外观模式整理底层的系统API,分类、重命名或者简单包装,最后给出一个统一易用的接口,它可以屏蔽不同操作系统之间的差异,增强软件的可移植性。nginx为了能过跨平台运行,大量应用了外观模式,使用宏、函数等手段,重定义了许多系统函数,减少了UNIX平台实现差异产生的影响。

3. 桥接(Bridge)

桥接模式分离了架构设计与实现,架构是稳定的,而实现可以任意变化,增强了系统的灵活性。Nginx的模块架构就应用了桥接模式,它使用了nginx_module_t定义模块,结构体里有若干函数指针和扩展字段,然后桥接实现了丰富多彩的core、conf、event、stream、http等功能模块,搭建起整个Nginx框架。

4. 模板方法(Template)

模板方法模式确定了操作的主要步骤和流程,并在关键节点定义了回调函数,允许外界实现回调函数来扩展或增强原操作的功能,是框架设计中最常用最基本的模式。作为开发框架,Nginx在配置解析阶段、请求处理阶段都定义了数量繁多的回调函数,模块可以根据自身的需求实现特定的回调函数。

5. 策略(Strategy)

最明显的,load-balance模块,封装了不同的负载均衡算法。另外,各种handler/filter/upstream模块,其实也可以算是策略模式,在配置文件替换不同的模块,就可以改变Nginx的行为。

二、业务级别的模式

1. 对象池

其实就是一个池化的概念。Nginx里的内存池是对象池的典型应用。另外nginx_pool_t/nginx_http_request_body_t使用链表保存闲置的nginx_chain_t,当需要使用缓冲区时直接取出来使用。

2. 职责链

Nginx的Stream/Http框架实现了处理引擎和过滤引擎,是职责链模式的具体应用,它们把stream/http模块组织成链表,逐个地加工处理客户端请求。其中处理引擎本身是二维职责链,分多个阶段,每个阶段里的模块也组织成职责链,而且在处理过程中由于URL重写的原因还可以在链表里跳转,导致职责链从头执行。

3. 命令模式

命令模式把请求封装成一个对象,让对象携带尽可能多的相关信息,可以简化后续的处理操作,通常配合职责链模式一起使用。显然,Nginx在处理http请求时的nginx_http_request_t结构体就是命令对象,它存储了非常多的信息,如连接、配置、数据、状态、变量、子请求等,在各个模块之间反复传递,由模块职责链进行处理。

4. 备忘录模式(Memento)

备忘录模式捕获一个对象的内部状态,并在对象之外保存这个对象为“备忘”,这样当对象再次启动时就可以通过备忘录恢复原状态,无差错地继续执行。

Nginx在请求结构体里设计的ctx成员就是备忘录,它为每个模块提供了保存运行时数据的空间,模块可以把任何数据作为“备忘”存储在ctx里,不会因为框架的异步机制导致运行状态不一致。

5. 中介者模式(Mediator)

中介者扮演“中间人”的角色,系统里的每个对象只与中介者通信,简化对象之间的多对多联系,协调保证它们共同工作。中介者模式的缺点是它必须维护所有的连接关系,很容易造成自身过度复杂。

nginx_http_upstream_module里定义的upstream框架就是中介者模式(同时也应用了模板模式),它协调load-balance模块和upstream模块共同工作,获取上游服务器的地址,然后转发下游的请求和上游的响应数据。

三、代码级别的模式

1. 组合

组合模式描述的是整体-部分的关系,使客户端可以一致地使用组合结构或其中单个对象,这里的“组合”和类关系那个“组合”是两个不同的概念。

原文地址:https://www.cnblogs.com/jdbc2nju/p/16038536.html