OpenResty 的两个基石:NGINX 和 LuaJIT。
在 OpenResty 的开发中,我们需要注意下面几点:
这样可以最大限度地提高可读性、可维护性和可扩展性。
下面这段 NGINX 配置,就是一个典型的反例,可以说是把配置项当成了代码来使用,在使用 OpenResty 进行开发时需要避免。
location ~ ^/mobile/(web/app.htm) { set $type $1; set $orig_args $args; if ( $http_user_Agent ~ "(iPhone|iPad|Android)" ) { rewrite ^/mobile/(.*) http://touch.foo.com/mobile/$1 last; } proxy_pass http://foo.com/$type?$orig_args; }
NGINX 通过配置文件来控制自身行为,它的配置可以看作是一个简单 的 DSL。NGINX 在进程启动的时候读取配置,并加载到内存中。如果修改了配置文件,需要重启或者重载 NGINX,再次读取后才能生效。只有 NGINX 的商业版本,才会在运行时, 以 API 的形式提供部分动态的能力。
如下为一段简单的nginx配置文件:
worker_processes auto; pid logs/nginx.pid; error_log logs/error.log notice; worker_rlimit_nofile 65535; events { worker_connections 16384; } http { server { listen 80; listen 443 ssl; location / { proxy_pass https://foo.com; } } } stream { server { listen 53 udp; }
基础概念:
1.每个指令都有自己适用的上下文(Context),也就是NGINX配置文件中指令的作用域。
最上层的是 main,里面是和具体业务无关的一些指令,比如上面出现的 worker_processes、pid 和 error_log,都属于 main 这个上下文。另外,上下文是有层级关系的,比如 location 的上下文是 server, server 的上下文是 http,http 的上下文是 main。
指令不能运行在错误的上下文中,NGINX 在启动时会检测 nginx.conf 是否合法。比如把 listen 80; 从 server 上下文换到 main 上下文,然后启动 NGINX 服务,会看到类似这样的报错:
"listen" directive is not allowed here ......
2.NGINX 不仅可以处理 HTTP 请求 和 HTTPS 流量,还可以处理 UDP 和 TCP 流量。
其中,七层的放在 HTTP 中,四层的放在 stream中。在 OpenResty 里面, lua-nginx-module 和 streamlua-nginx-module 分别和这俩对应。
NGINX 支持的功能,OpenResty 并不一定支持,需要看 OpenResty 的版本号。
OpenResty 的版本号是和 NGINX 保持一致的,所以很容易识别。比如 NGINX 在 2018 年 3 月份发布的 1.13.10 版本中,增加了对 gRPC 的支持,但 OpenResty 在 2019 年 4 月份时的最新版本是 1.13.6.2,由此 可以推断 OpenResty 还不支持 gRPC。
NGINX 启动后,会有一个 Master 进程和多个 Worker 进程(也可以只有一个 Worker 进程)。
Master 进程,扮演“管理者”的角色,并不负责处理终端的请求,它是用来管理 Worker 进程的,包括接受管理员发送的信号量、监控 Worker 的运行状态。当 Worker 进程异常退出时, Master 进程会重新启动一个新的 Worker 进程。
Worker 进程则是“一线员工”,用来处理终端用户的请求。它是从 Master 进程 fork 出来的,彼此之间相互独立,互不影响。多进程的模式比 Apache多线程的模式要先进很多,没有线程间加锁,也方便调试。即使某个进程崩溃退出了,也不会影响其他 Worker 进程正常工作。
OpenResty 在 NGINX Master-Worker 模式的前提下,又增加了独有的特权进程(privileged agent)。 这个进程并不监听任何端口,和 NGINX 的 Master 进程拥有同样的权限,所以可以做一些需要高权限才能 完成的任务,比如对本地磁盘文件的一些写操作等。
如果特权进程与 NGINX 二进制热升级的机制互相配合,OpenResty 就可以实现自我二进制热升级的整个流程,而不依赖任何外部的程序。
减少对外部程序的依赖,尽量在 OpenResty 进程内解决问题,不仅方便部署、降低运维成本,也可以降低程序出错的概率。可以说,OpenResty 中的特权进程、ngx.pipe 等功能,都是出于这个目的。
执行阶段也是 NGINX 重要的特性,与 OpenResty 的具体实现密切相关。NGINX 有 11 个执行阶段,可以从 ngx_http_core_module.h 的源码中看到:
typedef enum { NGX_HTTP_POST_READ_PHASE = 0, NGX_HTTP_SERVER_REWRITE_PHASE, NGX_HTTP_FIND_CONFIG_PHASE, NGX_HTTP_REWRITE_PHASE, NGX_HTTP_POST_REWRITE_PHASE, NGX_HTTP_PREACCESS_PHASE, NGX_HTTP_ACCESS_PHASE, NGX_HTTP_POST_ACCESS_PHASE, NGX_HTTP_PRECONTENT_PHASE, NGX_HTTP_CONTENT_PHASE, NGX_HTTP_LOG_PHASE } ngx_http_phases;
OpenResty 也有 11 个 *_by_lua指令,它们和 NGINX 阶段的关系如下图所示(图片来 自 lua-nginx-module 文档):
其中, init_by_lua 只会在 Master 进程被创建时执行,init_worker_by_lua 只会在每个 Worker 进程被创建时执行。其他的 *_by_lua 指令则是由终端请求触发,会被反复执行。
原文:https://www.cnblogs.com/liekkas01/p/12723444.html