Nginx 模块在定义服务时,一般是通过配置server里面的listen端口来完成。根据不同的listen语法,可以实现下了几种功能。
1. 最简单的,可以通过不同ip和port,对应某一个服务。
server1 {
listen 1.2.3.4:2121;
上面的配置,可以让所有到1.2.3.4端口是2121的连接进行server1规定的服务。
2. 通过指定port 范围,实现多个port对应一个服务。
server2 {
listen 1.2.3.4:2121-2123;
上面的配置就可以实现所有到ip地址1.2.3.4端口从2121到2123的连接都指向同样的服务server2。
3. 如果Nginx所在的服务器有多个ip 地址,可以通过不同的ip和相同的port组合实现不同的服务。
server3 {
listen 1.2.3.4:2121;
server4{
listen 2.3.4.5:2121;
当客户端连接 1.2.3.4:2121 时,提供server3的服务。连接2.3.4.5:2121时,提供server4的服务。
4. 如果Nginx所在的服务器有多个ip 地址,通过配置监听所有ip地址上相同的某些port。
server5 {
listen 2121;
server6{
listen *:2121;
上述两种配置的功能是一样的,通过省略ip地址或者用*表示ip地址,可以达到只要连接到达任何一个ip地址的端口2121都可以进行server5或者server6的目的。
5. 如果Nginx所在的服务器有多个ip 地址,可以通过如下配置,针对同一个port,让特定ip的连接进行某个服务,剩余ip的连接进 行另外的服务。
server7 {
listen *:2121;
server8{
listen 1.2.3.4:2121;
连接到1.2.3.4:2121的连接进行server8的服务。连接别的ip地址的2121port进行server7的服务。
二 实现原理
在进行代码分析之前,让我们先来看看与stream模块的listening port相关的数据结构是如何组织的。用户配置的server listen属性,最终需要生成ngx_listen_t结构。
图一 stream 模块监听端口相关数据结构
从配置listen到生成ngx_listen_t的流程如下。其中需要经过两次数据结构的转换。
-
在配置解析阶段,server配置的listen port生成的ngx_stream_listen_t结构被存放到下图的右上角的红色线框中。也就是stream模块对应的ngx_stream_core_main_conf_t结构中的listen字段所对应的链表。
-
然后把链表ngx_stream_listen_t转换成ngx_stream_conf_port_t结构。通过这个转换可以把所有端口相同的ngx_stream_listen_t合并成一个ngx_stream_conf_port_t结构。并且把这些具有相同端口的ngx_stream_listen_t结构对应的地址存放到生成的那个ngx_stream_conf_port_t结构的地址数组中.
-
最后通过ngx_stream_optimize_servers函数,把ngx_stream_conf_port_t结构转化成ngx_listen_t结构。转换的原则是:如果没有通配监听(listen *:2121或者listen 2121),每一对唯一的host address和port生成一个ngx_listen_t。相反,如果有通配监听,所有相同的port (2121)对应的所有的地址,只生成一个ngx_listen_t结构,同时把所有的对应的port的地址存放到ngx_listen_t结构的addrs数组中。
server {
listen *:2121;
proxy_timeout 65534;
proxy_pass vpnftp1;
alg ftp;
server {
listen 10.250.64.103:2121;
proxy_timeout 65534;
proxy_pass vpnftp;
alg ftp;
server {
listen 60.60.60.77:2121;
proxy_timeout 65534;
proxy_pass vpnftp;
alg ftp;
上述例子会在上述转换过程中,会生成3个ngx_stream_listen_t,1个 ngx_stream_conf_port_t,因为有通配符的存在只会1 个ngx_listen_t.
server {
listen 10.250.64.103:2121;
proxy_timeout 65534;
proxy_pass vpnftp;
alg ftp;
server {
listen 60.60.60.77:2121;
proxy_timeout 65534;
proxy_pass vpnftp;
alg ftp;
上述例子会在上述转换过程中,会生成2个ngx_stream_listen_t,1个 ngx_stream_conf_port_t,因为没有通配符所以生成2 个ngx_listen_t。
server {
listen 60.60.60.77:2122;
proxy_timeout 65534;
proxy_pass vpnftp;
alg ftp;
server {
listen 60.60.60.77:2121;
proxy_timeout 65534;
proxy_pass vpnftp;
alg ftp;
上述例子会在上述转换过程中,会生成2个ngx_stream_listen_t,2个 ngx_stream_conf_port_t, 2个ngx_listen_t.
server {
listen *:2121;
proxy_timeout 65534;
proxy_pass vpnftp;
alg ftp;
server {
listen 10.250.64.103:2121-2123;
proxy_timeout 65534;
proxy_pass vpnftp;
alg ftp;
server {
listen 60.60.60.77:2121;
proxy_timeout 65534;
proxy_pass vpnftp;
alg ftp;
上述例子会在上述转换过程中,会生成5个ngx_stream_listen_t,3个 ngx_stream_conf_port_t, 3个ngx_listen_t.
三 代码流程
在配置解析过程中,对应于stream模块配置解析入口是ngx_stream_block.在此函数中,对于stream server中对应的每一个listen字段,相应的解析函数是ngx_stream_core_listen。
函数的大体流程是:
-
调用ngx_parse_url -> ngx_parse_inet_url 生成了ngx_url_t数据结构。在ngx_url_t这个结构中,会存放listen定义的所有的port和可能的地址。如果语法是 listen 2121. 则会生成一个port,和一个INADDR_ANY地址。如果语法是listen *:2121,也会生成一个port,和一个INADDR_ANY地址。如果语法是listen 1.2.3.4:2121,生成一个port,和一个1.2.3.4的地址。如果语法是listen 1.2.3.4:2121-2123 则生成3个port和一个1.2.3.4的地址。如果语法是listen hostname:2121-2123则会生成3个port并且根据对hostname的域名解析得到的地址个数生成相应的地址数量。最后通过ngx_inet_add_addr函数把总数为port_num * addr_num数量的addr存放到ngx_url_t结构中。
-
生成上述的结构ngx_url_t后,根据结构中地址的个数 (port_num * addr_num)生成相应数量的ngx_stream_listen_t添加到ngx_stream_core_main_conf_t结构中的listen成员中。同时解析比如reuse,sndbuf,rcvbuf等属性。
-
通过函数ngx_stream_add_ports把上述的listen成员中的ngx_stream_listen_t数据按照相同的port number生成一个ngx_stream_conf_port_t的原则把所有的ngx_stream_listen_t结构转换成ngx_stream_conf_port_t结构。对于原来ngx_stream_listen_t中port number相同但是地址不相同的情况把所有的地址都组合起来存放到同一个ngx_stream_conf_port_t结构中的addr数组中。
-
通过函数ngx_stream_optimize_servers把上述的ngx_stream_conf_port_t结构定义的port转变成ngx_listening_t结构。转换的规则是:对于有通配匹配的情况(list *:2121或者listen 2121)的端口,如果有几个server对应的port number是一样的,则会生成唯一的一个ngx_listen_t结构,然后把几个server对应的地址存放到ngx_listen_t的地址数组中。对于没有通配匹配的端口,则会根据唯一的地址和端口对生成一个唯一的ngx_listen_t结构。每一个结构中只包含一个addr_t结构。
当连接初次建立时,(对于udp协议路径是ngx_event_recvmsg,对于tcp协议路径是ngx_event_accept),ngx_stream_init_connection函数得到调用。此时如果对应connection上的ngx_listen_t对应的addr有多个。(针对listen *情况),根据连接的Nginx侧的连接信息来确定使用的server是哪一个。通过这个server来连接upstream结构和server的context.
为了支持监听端口的通配匹配,Nginx做了很多额外的工作进行了数据结构的两次转化。但是也没有想到更好的办法可以省略这两次转换。
另外,这篇文章更多是帮助自己理解代码而写的,希望对大家也有帮助。
一 简介Nginx 模块在定义服务时,一般是通过配置server里面的listen端口来完成。根据不同的listen语法,可以实现下了几种功能。 1. 最简单的,可以通过不同ip和port,对应某一个服务。server1 { listen 1.2.3.4:2121;}上面的配置,可以让所有到1.2.3.4端口是2121的连接进行server1规...
Nginx
监听端口
管理 每监听一个TCP端口,都将使用一个独立的ngx_http_conf_port_t结构体表示。ngx_http_conf_port_ttypedef struct {
//socket地址家族
ngx_int_t family; //
监听端口
in_port_t port; //
监听端口
下对应
1、安装
nginx
./configure --prefix=/usr/local/
nginx
--with-http_stub_status_module --with-http_ssl_module --with-
stream
--with-
stream
_ssl_preread_module --with-
stream
_ssl_module --user=
nginx
--group=
nginx
2、配置
nginx
#user nobody;
worker_processes 1;#error_log l
worker_processes 1; //主从进程
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
#pid logs/
nginx
.pid;
events {
worker_connections 1024;
http {
include mime.types;
default_type app
nginx
-1.9.0 已发布,该版本增加了
stream
模块
用于一般的TCP 代理和负载均衡,ngx_
stream
_core_module 这个
模块
在1.90版本后将被启用。但是并不会默认安装,
需要在编译时通过指定 --with-
stream
参数来激活这个
模块
。
1)配置
Nginx
编译文件参数
./configure --with-
stream
2)编译、安装,make && make install
make & ma...
通过查看
Nginx
的并发连接,我们可以更清除的知道网站的负载情况。
Nginx
并发查看有两种方法(之所以这么说,是因为笔者只知道两种),一种是通过web界面,一种是通过命令,web查看要比命令查看显示的结果精确一些。下面介绍这两种查看方法;
1.通过浏览器查看
通过web界面查看时
Nginx
需要开启status
模块
,也就是安装
Nginx
时加上 –with-http...
nginx
的
stream
模块
是用于
处理
TCP和UDP流量的
模块
。它允许你在不破坏原始数据流的情况下,对流量进行路由、载均衡和代理等操作。下是
stream
模块
的一些常见配置指令的详解:
1. `
stream
`:定义
stream
模块
的全局配置块。
stream
{
2. `up
stream
`:定义上游服务器列表。可以使用`server`指令指定上游服务器的地址和端口。
up
stream
backend {
server backend1.example.com:12345;
server backend2.example.com:12345;
3. `server`:定义
stream
模块
的监听服务器。可以使用`proxy_pass`指令将流量代理到上游服务器。
server {
listen 12345;
proxy_pass backend;
4. `proxy_pass`:将流量代理到指定的上游服务器。
proxy_pass backend;
5. `resolver`:指定解析器的地址,用于解析上游服务器的域名。
resolver 8.8.8.8;
6. `balancer`:定义负载均衡的算法和参数。
up
stream
backend {
server backend1.example.com:12345 weight=5;
server backend2.example.com:12345;
balancer least_conn;
7. `ssl_preread`:基于SSL握手前的数据,用于决定将流量路由到哪个上游服务器。