正反向代理
正向代理的工作原理就像一个跳板,正向代理是一个位于客户端和原始服务器(origin server)之间的服务器。为了从原始服务器取得内容,客户端向代理发送一个请求并指定目标(原始服务器),然后代理向原始服务器转交请求并将获得的内容返回给客户端。
反向代理服务器对于客户端而言它就像是原始服务器,并且客户端不需要进行任何特别的设置。客户端向反向代理的命名空间(name-space)中的内容发送普通请求,接着反向代理服务器将判断向何处(原始服务器)转交请求,并将获得的内容返回给客户端,就像这些内容原本就是它自己的一样。
心得:正向代理,用户知道代理后面有原始服务器,代理可以向原始服务器隐瞒用户信息。反向代理,用户认为代理是原始服务器
工作流程
用户访问域名->DNS解析域名到反向代理服务器的ip->反向代理服务器接受请求,查找并返回本地缓存,无缓存->请求源服务器上的内容->缓存并返回给用户
client visits domain->dns analyze domain to front ip->front accept requst,read & return mc,if mc is empty->request storage->write mc & return
模块划分
结构划分
核心模块:HTTP模块、EVENT模块和MAIL模块
基础模块:HTTP Access模块、HTTP FastCGI模块、HTTP Proxy模块和HTTP Rewrite模块
第三方模块:HTTP Upstream Request Hash模块、Notice模块和HTTP Access Key模块
功能划分
Core(核心模块):构建nginx基础服务、管理其他模块
Handlers(处理器模块):此类模块直接处理请求,并进行输出内容和修改headers信息等操作。如果handlers(处理模块)把请求反向代理到后端的服务器,就变成另外一类的模块:load-balancers(负载均衡模块)
Filters (过滤器模块):此类模块主要对其他处理器模块输出的内容进行修改操作,最后由Nginx输出
Proxies (代理类模块):此类模块是Nginx的HTTP Upstream之类的模块,这些模块主要与后端一些服务比如FastCGI等进行交互,实现服务代理和负载均衡等功能。
模块处理
接到HTTP请求->
根据配置文件,找到Handlers->
有load-banlancer则选择后台服务器->
Handlers处理后,将输出输出给Filters->
Filters依次处理输出->
响应给客户端
Nginx的负载均衡模块采用两种方法:
轮转法,它处理请求就像纸牌游戏一样从头到尾分发;
IP哈希法,在众多请求的情况下,它确保来自同一个IP的请求会分发到相同的后端服务器。
请求处理
一个master进程,多个worker进程。一般worker进程个数是根据服务器CPU核数来决定的。
master进程读取并验证配置文件nginx.conf;管理worker进程;每一个Worker进程都维护一个线程(避免线程切换),处理连接和请求。
热部署
所谓热部署,就是配置文件nginx.conf修改后,不需要stop Nginx,不需要中断请求,就能让配置文件生效。 (-s reload)
修改配置文件后,-s reload重新加载配置文件,生成新的worker进程,处理新请求。老worker在处理完当前请求后杀掉。
高并发下的高效处理
epoll可以同时监控多个事件,并在某个事件准备就绪时,将该事件放入队列中。
Nginx采用epoll模型,worker只需要循环读取epoll队列即可。
多进程处理模型
master根据配置建立监听的socket fd,再fork多个worker,这些worker都监听同ip端口的socket fd->
当有请求时,workers抢锁(accept_mutex)注册读事件,抢到锁的worker处理请求。
进程之间是独立的,worker异常不会影响其它workers。
worker进程会竞争监听客户端的连接请求,因为一个worker可以建立多个连接(worker_connections设定),可能会出现所有请求都被一个worker获取到,导致其它worker空闲,单个worker忙。继而导致响应超时。
ngx_accept_disabled标识控制一个worker进程是否需要去竞争获取accept_mutex选项,进而获取accept事件。当ngx_accept_disabled大于0时,不会去尝试获取accept_mutex锁,并且将ngx_accept_disabled减1,于是,每次执行到此处时,都会去减1,直到等于0。因此,当ngx_accept_disabled大于0时,worker不会获取新请求,确保请求的公平分配。
ngx_accept_disabled值:nginx单进程的所有连接总数的八分之一,减去剩下的空闲连接数量。
HTTP请求处理过程
在建立连接过程中,对于nginx监听到的每个客户端连接,都会将它的读事件的handler设置为ngx_http_init_request函数,这个函数就是请求处理的入口。在处理请求时,主要就是要解析http请求,比如:uri,请求行等,然后再根据请求生成响应。
phase handlers就是包含若干个处理阶段的一些 handler。在每一个阶段,包含有若干个handler,再处理到某个阶段的时候,依次调用该阶段的 handler 对 HTTP Request 进行处理。通常情况下,一个phase handler 对这个request进行处理,并产生一些输出。通常phase handler是与定义在配置文件中的某个location相关联的。
phase handler 通常执行以下几项任务:获取 location 配置、产生适当的响应、发送 response header、发送 response body。
当 Nginx 读取到一个 HTTP Request 的 header 的时候,Nginx 首先查找与这个请求关联的虚拟主机的配置。然后如下处理:
NGX_HTTP_POST_READ_PHASE: 读取请求内容阶段
NGX_HTTP_SERVER_REWRITE_PHASE: Server 请求地址重写阶段
NGX_HTTP_FIND_CONFIG_PHASE: 配置查找阶段
NGX_HTTP_REWRITE_PHASE: Location请求地址重写阶段
NGX_HTTP_POST_REWRITE_PHASE: 请求地址重写提交阶段
NGX_HTTP_PREACCESS_PHASE: 访问权限检查准备阶段
NGX_HTTP_ACCESS_PHASE: 访问权限检查阶段
NGX_HTTP_POST_ACCESS_PHASE: 访问权限检查提交阶段
NGX_HTTP_TRY_FILES_PHASE: 配置项 try_files 处理阶段
NGX_HTTP_CONTENT_PHASE: 内容产生阶段
NGX_HTTP_LOG_PHASE: 日志模块处理阶段
在内容产生阶段,需要把request交给content handler处理。可由location指定handler,也可依次尝试:
如果一个 location 里面有配置 random_index on,那么随机选择一个文件,发送给客户端。
如果一个 location 里面有配置 index 指令,那么发送 index 指令指明的文件,给客户端。
如果一个 location 里面有配置 autoindex on,那么就发送请求地址对应的服务端路径下的文件列表给客户端。
如果这个 request 对应的 location 上有设置 gzip_static on,那么就查找是否有对应的.gz文件存在,有的话,就发送这个给客户端(客户端支持 gzip 的情况下)。
请求的 URI 如果对应一个静态文件,static module 就发送静态文件的内容到客户端。
内容产生阶段完成以后,生成的输出会被传递到 filter 模块去进行处理。所有的 filter 模块都被组织成一条链。输出会依次穿越所有的 filter,直到有一个 filter 模块的返回值表明已经处理完成。
请求完整的处理过程如下图