Tengine 基础原理和基本使用

1.Tengine简介
2.Tengine特性
3.Tengine工作原理和用途
- 3.1 Tengine处理HTTP请求流程
- 3.2 Tengine的模块化
- 3.3 Tengine进程模型
- 3.4 Tengine事件模型
- 3.5 Tengine信号
- 3.6 Tengine定时器
4.Tengine安装部署
- 4.1 安装依赖
- 4.2 编译
5.Tengine 文件目录结构
6.Tengine 配置文件详解
- 6.1 tengine主配置文件
- 6.2 状态检测配置文件
- 6.3 tengine常用配置
7.Tengine 安全防护
- 7.1 禁止web服务IP直接访问
- 7.2 连接和请求数限制
- 7.3 访问全站IP黑名单限制
- 7.4 下载防盗链配置
8.Tengine 重要模块
- 8.1 upstream负载均衡模块
- 8.2 rewrite重写模块
9.location 在匹配中的优先级
10.Tengine root 和 alias 的区别
11.Tengine TCP转发配置
12.Tengine 常用维护脚本或命令
13.参考文档

1.Tengine简介

Tengine是由淘宝网发起的Web服务器项目。它在Nginx的基础上,针对大访问量网站的需求,添加了很多高级功能和特性。Tengine的性能和稳定性已经在大型的网站如淘宝网,天猫商城等得到了很好的检验。它的最终目标是打造一个高效、稳定、安全、易用的Web平台。从2011年12月开始,Tengine成为一个开源项目,Tengine团队在积极地开发和维护着它。Tengine团队的核心成员来自于淘宝、搜狗等互联网企业。Tengine是社区合作的成果,我们欢迎大家参与其中,贡献自己的力量。

2.Tengine特性

  • 继承Nginx-1.8.1的所有特性,兼容Nginx的配置

  • 动态模块加载(DSO)支持。加入一个模块不再需要重新编译整个Tengine

  • 支持HTTP/2协议,HTTP/2模块替代SPDY模块

  • 流式上传到HTTP后端服务器或FastCGI服务器,大量减少机器的I/O压力

  • 更加强大的负载均衡能力,包括一致性hash模块、会话保持模块,还可以对后端的服务器进行主动健康检查,根据服务器状态自动上线下线,以及动态解析upstream中出现的域名

  • 输入过滤器机制支持,通过使用这种机制Web应用防火墙的编写更为方便

  • 支持设置proxy、memcached、fastcgi、scgi、uwsgi在后端失败时的重试次数

  • 动态脚本语言Lua支持。扩展功能非常高效简单

  • 支持按指定关键字(域名,url等)收集Tengine运行状态

  • 组合多个CSS、JavaScript文件的访问请求变成一个请求

  • 自动去除空白字符和注释从而减小页面的体积

  • 自动根据CPU数目设置进程个数和绑定CPU亲缘性

  • 监控系统的负载和资源占用从而对系统进行保护

  • 显示对运维人员更友好的出错信息,便于定位出错机器

  • 更强大的防攻击(访问速度限制)模块

  • 更方便的命令行参数,如列出编译的模块列表、支持的指令等

  • 可以根据访问文件类型设置过期时间

3.Tengine工作原理和用途

3.1 Tengine处理HTTP请求流程

http请求是典型的请求-响应类型的的网络协议。http是文件协议,所以我们在分析请求行与请求头,以及输出响应行与响应头,往往是一行一行的进行处理。通常在一个连接建立好后,读取一行数据,分析出请求行中包含的method、uri、http_version信息。然后再一行一行处理请求头,并根据请求method与请求头的信息来决定是否有请求体以及请求体的长度,然后再去读取请求体。得到请求后,我们处理请求产生需要输出的数据,然后再生成响应行,响应头以及响应体。在将响应发送给客户端之后,一个完整的请求就处理完了。处理流程图:

tengine-请求流程

3.2 Tengine的模块化

Nginx由内核和模块组成。Nginx的模块从结构上分为核心模块、基础模块和第三方模块:

  • 核心模块:HTTP模块、EVENT模块和MAIL模块

  • 基础模块:HTTP Access模块、HTTP FastCGI模块、HTTP Proxy模块和HTTP Rewrite模块,

  • 第三方模块:HTTP Upstream Request Hash模块、Notice模块和HTTP Access Key模块。
    用户根据自己的需要开发的模块都属于第三方模块。正是有了这么多模块的支撑,Nginx的功能才会如此强大,Nginx的模块从功能上分为如下三类。

  • Handlers(处理器模块):此类模块直接处理请求,并进行输出内容和修改headers信息等操作。Handlers处理器模块一般只能有一个。

  • Filters (过滤器模块):此类模块主要对其他处理器模块输出的内容进行修改操作,最后由Nginx输出。

  • Proxies (代理类模块):此类模块是Nginx的HTTP Upstream之类的模块,这些模块主要与后端一些服务比如FastCGI等进行交互,实现服务代理和负载均衡等功能。
    Nginx模块常规的HTTP请求和响应的过程:
    tengine-模块
    Nginx本身做的工作实际很少,当它接到一个HTTP请求时,它仅仅是通过查找配置文件将此次请求映射到一个location block,而此location中所配置的各个指令则会启动不同的模块去完成工作,因此模块可以看做Nginx真正的劳动工作者。通常一个location中的指令会涉及一个handler模块和多个filter模块(当然,多个location可以复用同一个模块)。handler模块负责处理请求,完成响应内容的生成,而filter模块对响应内容进行处理。

3.3 Tengine进程模型

Nginx默认采用多进程工作方式,Nginx启动后,会运行一个master进程和多个worker进程。其中master充当整个进程组与用户的交互接口,同时对进程进行监护,管理worker进程来实现重启服务、平滑升级、更换日志文件、配置文件实时生效等功能。worker用来处理基本的网络事件,worker之间是平等的,他们共同竞争来处理来自客户端的请求。
nginx的进程模型如图所示:

tengine-进程模型

请求到来时,如何分配均分worker进程来处理他们?

在创建master进程时,先建立需要监听的socket(listenfd),然后从master进程中fork()出多个worker进程,如此一来每个worker进程多可以监听用户请求的socket。一般来说,当一个连接进来后,所有在Worker都会收到通知,但是只有一个进程可以接受这个连接请求,其它的都失败,这是所谓的惊群现象。nginx提供了一个accept_mutex(互斥锁),有了这把锁之后,同一时刻,就只会有一个进程在accpet连接,这样就不会有惊群问题了。

先打开accept_mutex选项,只有获得了accept_mutex的进程才会去添加accept事件。nginx使用一个叫ngx_accept_disabled的变量来控制是否去竞争accept_mutex锁。ngx_accept_disabled = nginx单进程的所有连接总数 / 8 -空闲连接数量,当ngx_accept_disabled大于0时,不会去尝试获取accept_mutex锁,ngx_accept_disable越大,于是让出的机会就越多,这样其它进程获取锁的机会也就越大。不去accept,每个worker进程的连接数就控制下来了,其它进程的连接池就会得到利用,这样,nginx就控制了多进程间连接的平衡。

每个worker进程都有一个独立的连接池,连接池的大小是worker_connections。这里的连接池里面保存的其实不是真实的连接,它只是一个worker_connections大小的一个ngx_connection_t结构的数组。并且,nginx会通过一个链表free_connections来保存所有的空闲ngx_connection_t,每次获取一个连接时,就从空闲连接链表中获取一个,用完后,再放回空闲连接链表里面。一个nginx能建立的最大连接数,应该是worker_connections 乘以 worker_processes。当然,这里说的是最大连接数,对于HTTP请求本地资源来说,能够支持的最大并发数量是worker_connections 乘以 worker_processes,而如果是HTTP作为反向代理来说,最大并发数量应该是worker_connections 乘以 worker_processes/2。因为作为反向代理服务器,每个并发会建立与客户端的连接和与后端服务的连接,会占用两个连接。

3.4 Tengine事件模型

对于一个基本的web服务器来说,事件通常有三种类型,网络事件、信号的处理。Nginx每个worker里面只有一个主线程,多少个worker就能处理多少个并发,何来高并发呢?请求流程:首先,请求到来,要建立连接,然后再接收数据,接收数据后,再发送数据。具体到系统底层,就是读写事件,而当读写事件没有准备好时,不可操作。apache的常用工作方式:每个请求会独占一个工作线程,当并发数上到几千时,就同时有几千的线程在处理请求了。这对操作系统来说,是个不小的挑战,线程带来的内存占用非常大,线程的上下文切换带来的cpu开销很大,自然性能就上不去了,而这些开销完全是没有意义的。

Nginx采用异步非阻塞的方式来支持用户请求。Nginx支持select/poll/epoll/kqueue等事件模型。拿epoll为例,当事件没准备好时,放到epoll里面,事件准备好了,我们就去读写,当读写返回EAGAIN时,我们将它再次加入到epoll里面。这样,只要有事件准备好了,我们就去处理它,当事件都没有完全准备好时,就在epoll里面等着。这样,我们就可以并发处理大量的并发了,当然,这里的并发请求,是指未处理完的请求,线程只有一个,所以同时能处理的请求当然只有一个了,只是在请求间进行不断地切换而已,切换也是因为异步事件未准备好,而主动让出的。这里的切换是没有任何代价,你可以理解为循环处理多个准备好的事件,事实上就是这样的。与多线程相比,这种事件处理方式是有很大的优势的,不需要创建线程,每个请求占用的内存也很少,没有上下文切换,事件处理非常的轻量级。并发数再多也不会导致无谓的资源浪费(上下文切换),更多的并发数,只是会占用更多的内存而已。 现在的网络服务器基本都采用这种方式,这也是nginx性能高效的主要原因。

推荐设置worker的个数为cpu的核数,因为更多的worker数,只会导致进程来竞争cpu资源了,从而带来不必要的上下文切换。而且,nginx为了更好的利用多核特性,提供了cpu亲缘性的绑定选项,我们可以将某一个进程绑定在某一个核上,这样就不会因为进程的切换带来cache的失效。

3.5 Tengine信号

对nginx来说,有一些特定的信号,代表着特定的意义。信号会中断掉程序当前的运行,在改变状态后,继续执行。如果是系统调用,则可能会导致系统调用的失败,需要重新进行一次。如果nginx正在等待事件(epoll_wait时),如果程序收到信号,在信号处理函数处理完后,epoll_wait会返回错误,然后程序可再次进入epoll_wait调用。

3.6 Tengine定时器

由于epoll_wait等函数在调用的时候是可以设置一个超时时间的,所以nginx借助这个超时时间来实现定时器。nginx里面的定时器事件是放在一颗维护定时器的红黑树里面,每次在进入epoll_wait前,先从该红黑树里面拿到所有定时器事件的最小时间,在计算出epoll_wait的超时时间后进入epoll_wait。所以,当没有事件产生,也没有中断信号时,epoll_wait会超时,也就是说,定时器事件到了。这时,nginx会检查所有的超时事件,将他们的状态设置为超时,然后再去处理网络事件。由此可以看出,当我们写nginx代码时,在处理网络事件的回调函数时,通常做的第一个事情就是判断超时,然后再去处理网络事件

4.Tengine安装部署

4.1 安装依赖

1
yum -y install zlib zlib-devel openssl openssl-devel pcre pcre-devel   gcc gcc-c++ autoconf automake jemalloc jemalloc-devel

4.2 编译

1
2
3
4
5
6
7
8
9
10
11
12
tar -zxvf tengine-2.2.0.tar.gz
cd tengine-2.2.0
./configure --with-http_stub_status_module --with-http_ssl_module --with-http_gzip_static_module --with-http_concat_module --with-jemalloc --with-http_v2_module --with-http_secure_link_module
make && make install
#编译选项解析
./configure --with-http_stub_status_module #添加监控状态配置
--with-http_ssl_module #支持https
--with-http_gzip_static_module #支持静态文件预压缩
--with-http_concat_module #用于合并多个文件在一个响应报文中
--with-jemalloc #支持jemalloc内存管理
--with-http_v2_module #支持http_v2
--with-http_secure_link_module #防下载盗链支持

5.Tengine 文件目录结构

tengine-目录结构

1
2
3
4
5
6
7
8
9
10
11
12
13
|---certs :存放域名证书位置,自建的规范目录
|---client_body_temp:如果客户端POST一个比较大的文件,长度超过了nginx缓冲区的大小,需要把这个文件的部分或者全部内容暂存到client_body_temp目录下的临时文件
|---conf:主配置文件存放目录
|---conf.d:存放虚拟主机的配置文件,自建规范目录
|---fastcgi_temp:对于来自 FastCGI Server 的 Response,Nginx 将其缓冲到内存中,然后依次发送到客户端浏览器。缓冲区的大小由 fastcgi_buffers 和 fastcgi_buffer_size 两个值控制,fastcgi_buffers 控制 nginx 最多创建 8 个大小为 4K 的缓冲区,而 fastcgi_buffer_size 则是处理 Response 时第一个缓冲区的大小,不包含在前者中,超出部分存在这个目录
|---html:静态文件默认存放位置
|---include:存放编译代码头文件目录
|---logs:默认存放日志目录
|---modules:存放模块目录
|---proxy_temp:后端返回数据的临时存放目录
|---sbin:nginx二进制文件存放目录
|---scgi_temp:客户端可能会向服务器端请求大量的数据,服务器端收到的请求报文中的body中可能会有很多的数据,而这些数据都会存放内存中,倘若有很多的用户并发发出请求,服务器端内存无法存放,因此就会把数据临时存放在磁盘上的这些临时文件内
|---uwsgi_temp:代理服务器时缓存文件的存放路径

6.Tengine 配置文件详解

6.1 tengine主配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
#/usr/local/nginx/conf/nginx.conf
user nobody nobody; # 指定运行的用户和用户组
worker_processes auto; # 指定要开启的进程数,一般为CPU的核心数或两倍
worker_cpu_affinity auto; # cpu亲和性
worker_rlimit_nofile 102400; # 这个指令是指当一个nginx进程打开的最多文件描述符数目,理论值应该是最多打开文件数(ulimit -n)与nginx进程数相除,但是nginx 分配请求并不是那么均匀,所以最好与ulimit -n 的值保持一致
pid logs/nginx.pid; #进程号存放位置

events {
use epoll; # 指定nginx的工作模式
worker_connections 65535; # 定义每个进程的最大连接数
}


http {
req_status_zone server "$server_addr:$server_port" 10M; # 根据变量值分别统计Tengine的运行状况
include mime.types; # 服务器识别的文件类型
default_type application/octet-stream; # 文件类型未定义时默认识别为二进制流
check_shm_size 20M; #后端检测内存区大小
sendfile on; # 高速传输文件
tcp_nopush on; # 防止网络阻塞
tcp_nodelay on; # 防止网络阻塞
server_tokens off; # 不返回nginx的版本信息
server_info off; #返回错误页面是不返回服务器信息
keepalive_timeout 20s; # 一个keepalive 连接被闲置以后还能保持多久打开状态
keepalive_requests 1000; # 这是一个客户端可以通过一个keepalive连接的请求次数。缺省值是100,但是也可以调得很高,而且这对于测试负载生成工具从哪里使用一个客户端发送这么多请求非常有用

gzip on; # 开启gzip压缩输出
gzip_min_length 1024; # 最小压缩文件大小
gzip_buffers 16 8k; # 压缩缓冲区
gzip_comp_level 6; # 压缩等级
gzip_proxied any; # Nginx作为反向代理的时候启用,根据某些请求和应答来决定是否在对代理请求的应答启用gzip压缩,是否压缩取决于请求头中的“Via”字段启用压缩,这里是如果header头中包含 "Expires" 头信息
gzip_types text/plain text/css application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript; #压缩类型,默认就已经包含text/html,所以下面就不用再写了
# 写上去也不会有问题,但是会有一个warn
gzip_vary on; # 让前端的缓存服务器缓存经过gzip压缩的页面,和http头有关系,加个vary头,给代理服务器用的,有的浏览器支持压缩,有的不支持,所以避免浪费不支持的也压缩,所以根据客户端的HTTP头来判断,是否需要压缩


fastcgi_intercept_errors on; # 这个指令指定是否传递4xx和5xx错误信息到客户端,或者允许nginx使用error_page处理错误信息
fastcgi_connect_timeout 75s; # 指定连接到后端FastCGI的超时时间
fastcgi_send_timeout 300s; # 指定向FastCGI传送请求的超时时间,这个值是已经完成两次握手后向FastCGI传送请求的超时时间。
fastcgi_read_timeout 300s; # 指定接收FastCGI应答的超时时间,这个值是已经完成两次握手后接收FastCGI应答的超时时间。
fastcgi_buffer_size 16k; # 用于指定读取FastCGI应答第一部分需要用多大的缓冲区,这个值表示将使用1个64KB的缓冲区读取应答的第一部分(应答头),可以设置为fastcgi_buffers选项指定的缓冲区大小
fastcgi_buffers 4 16k; # 指定本地需要用多少和多大的缓冲区来缓冲FastCGI的应答请求。如果一个PHP脚本所产生的页面大小为256KB,那么会为其分配4个64KB的缓冲区来缓存,如果页面大小大于256KB,那么大于256K
# B的部分会缓存到
fastcgi_busy_buffers_size 32k; # 繁忙模式下的缓冲区大小,默认值是fastcgi_buffers的两倍

#open_file_cache max=10240 inactive=20s; # 最多缓存多少个文件,缓存多少时间
#open_file_cache_valid 30s; # 多少时间检查一次,如果发现20s内没有用过一次的删除
#open_file_cache_min_uses 1; # 在20S中没有使用到这个配置的次数的话就删除

client_body_timeout 90s; # 设置客户端请求头读取超时的时间
client_max_body_size 20m; # 用来设置允许客户端请求的最大的单个文件字节数
client_body_buffer_size 1m; # 设置缓存区的最大值
client_header_buffer_size 128k; # 用于指定来自客户端请求头的header buffer大小
large_client_header_buffers 256 16k; # 用来指定客户端请求中较大的消息头和缓存最大数量和大小

proxy_buffer_size 16k; # 设置代理服务器(nginx)保存用户头信息的缓冲区大小
proxy_buffers 8 32k; # proxy_buffers缓冲区,网页平均在32k以下的设置
proxy_busy_buffers_size 64k; # 高负荷下缓冲大小(proxy_buffers*2)
proxy_connect_timeout 300s; # nginx跟后端服务器连接超时时间(代理连接超时)
proxy_send_timeout 300s; # 后端服务器数据回传时间(代理发送超时)
proxy_read_timeout 300s; # 连接成功后,后端服务器响应时间(代理接收超时)

#proxy_temp_path /usr/local/nginx/proxy_temp; # 缓存临时目录。后端的响应并不直接返回客户端,而是先写到一个临时文件中,然后被rename一下当做缓存放在 proxy_cache_path
#proxy_cache_path ... : 设置缓存目录,目录里的文件名是 cache_key 的MD5值。
#levels=1:2 keys_zone=cache_one:50m表示采用2级目录结构,Web缓存区名称为cache_one,内存缓存空间大小为100MB,这个缓冲zone可以被多次使用。文件系统上看到的缓存文件名类似于 /usr/local/nginx-1.6/proxy_cache/c/29/b7f54b2df7773722d382f4809d65029c inactive=2d max_size=2g表示2天没有被访问的内容自动清除,硬盘最大缓存空间为2GB,超过这个大学将清除最近最少使用的数据。
#proxy_cache_path /usr/local/nginx/proxy_cache levels=1:2 keys_zone=cache_one:100m inactive=2d max_size=2g;这两句需要搭配location里面的指令使用,默认不开启


map $upstream_addr $short_address {
~^\d+\.\d+\.(.*) '';
}
add_header X-from $short_address$1;

proxy_set_header Host $host;
proxy_set_header X-User-IP $clientRealIp;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass_header User-Agent;
proxy_set_header X-Forwarded-Proto $scheme;


map $http_x_forwarded_for $clientRealIp {
"" $remote_addr;
~^(?P<firstAddr>[0-9\.]+),?.*$ $firstAddr;
}

log_format main '{ "@timestamp": "$time_iso8601", '
'"remote_addr": "$remote_addr", '
'"upstream_addr": "$upstream_addr", '
'"server_addr": "$server_addr", '
'"http_host": "$http_host",'
'"request_time": $request_time, '
'"upstream_response_time": $upstream_response_time, '
'"request_uri": "$request_uri", '
'"status": "$status", '
'"request": "$request", '
'"request_method": "$request_method", '
'"http_referer": "$http_referer", '
'"body_bytes_sent": $body_bytes_sent, '
'"http_x_forwarded_for": "$http_x_forwarded_for", '
'"request_length": $request_length, '
'"http_user_agent": "$http_user_agent", '
'"scheme": "$scheme",'
'"uri": "$uri",'
'"clientRealIp": "$clientRealIp"}';

include /usr/local/nginx/conf.d/*.conf;
}

6.2 状态检测配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#/usr/local/nginx/conf.d/admin.conf
server {
listen 8000;
location ~ ^/(phpfpm_status|ping)$ {
fastcgi_pass 127.0.0.1:9000;
include fastcgi.conf;
}
location = /nginx_status {
stub_status on;
access_log off;
}
location = /nginx_status_detail {
req_status_show;
}
location = /nstatus {
check_status;
access_log off;
#allow IP;
#deny all;
}

}

6.3 tengine常用配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#/usr/local/nginx/conf.d/default.conf(一些常用的配置功能,供参考)
server {
listen 80 ;
listen 443 ssl;
server_name www.test1.com www.test2.com;
server_tag off;
req_status server;

# 开启https的配置,证书存放位置需要规范
# ssl on;
ssl_certificate /usr/local/nginx/certs/test.crt;
ssl_certificate_key /usr/local/nginx/certs/test.key;
ssl_session_timeout 5m;
ssl_protocols SSLv2 SSLv3 TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP;
ssl_prefer_server_ciphers on;
#配置本监听端口下的日志
access_log logs/host.access.log main;

location /example {

root html;
index index.html index.htm;
# 最多 5 个排队, 由于每秒处理 10 个请求 + 5个排队,你一秒最多发送 15 个请求过来,再多就直接返回 503 错误给你了
# limit_req zone=ConnLimitZone burst=5 nodelay;

# 用于获取用户真实IP,传给后端的服务器获取
proxy_set_header Host $host;
proxy_set_header X-real-ip $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

# 开启与后端tomcat长连接需下面两个指令,tomcat也需要配置长连接参数(tomcat在server.xml配置标签 <Connector keepAliveTimeout="20000" maxKeepAliveRequests="3000" />)
proxy_http_version 1.1;
proxy_set_header Connection "";

# 反向代理指令,记得proxy_pass 带uri和不带uri的区别
#proxy_pass http://bakend/ ; #与负载均衡结合使用
proxy_pass http://192.168.31.11:7111/ ;
# 用户访问局部限制指令,匹配上的立马匹配,不继续下面的匹配动作
allow 192.168.31.69;
deny all;
deny 192.168.31.70;
allow all;

# 传输数据限速到20k,为了测试很明显就把此值调的很低
limit_rate 20k;

# 数据合并发送
# 合并js css,需要开发合并文件,暂时使用不了
concat on;
concat_max_files 20;
concat_unique off;
concat_delimiter "\r\n";
concat_ignore_file_error on;

#配置web缓存,与主配置文件配置的缓存目录结合使用。缓存也就是将js、css、image等静态文件从tomcat缓存到nginx指定的缓存目录下,既可以减轻tomcat负担,也可以加快访问速度,
#但这样缓存及时清理成为了一个问题,所以需要 ngx_cache_purge 这个模块来在过期时间未到之前,手动清理缓存。(有篇文章http://quenlang.blog.51cto.com/4813803/1570671,
#对比使用缓存、不使用缓存、使用动静分离三种情况下,高并发性能比较。使用代理缓存功能性能会高出很多倍)
#反向代理到哪台机器
proxy_pass http://192.168.31.11;
#不显示重定向信息
proxy_redirect off;
#设置请求头,获取用户真实IP
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

#引用前面定义的缓存区 cache_one
proxy_cache cache_one;
#增加头部记录缓存命中率
add_header Nginx-Cache $upstream_cache_status;
#proxy_cache_valid : 为不同的响应状态码设置不同的缓存时间,比如200、302等正常结果可以缓存的时间长点,而404、500等缓存时间设置短一些,这个时间到了文件就会过期,而不论是否刚被访问过。
proxy_cache_valid 200 304 301 302 8h;
proxy_cache_valid 404 1m;
proxy_cache_valid any 2d;
#定义cache_key
proxy_cache_key $host$uri$is_args$args;
#返回给客户端的浏览器缓存失效时间,指的是静态资源的缓存
expires 30d;
}

#清除缓存。下面配置的proxy_cache_purge指令用于方便的清除缓存,但必须按装第三方的 ngx_cache_purge 模块才能使用,项目地址:https://github.com/FRiCKLE/ngx_cache_purge/ 。
location ~ /purge(/.*) {
#设置只允许指定的IP或IP段才可以清除URL缓存。
allow 127.0.0.1;
allow 192.168.31.0/24;
deny all;
proxy_cache_purge cache_one $host$1$is_args$args;
error_page 405 =200 /purge$1;
}

# 图片防盗链配置
location ~* \.(gif|jpg|png|bmp)$ {
root html;
valid_referers none blocked *.feidee.com server_names ~\.google\. ~\.baidu\.;
if ($invalid_referer) {
return 403;
#rewrite ^/ http://xxxx/403.jpg;
}
}

location /realip {
#如果是作为代理,下面三句才会把客户端的IP带到真正的服务器上面
proxy_set_header Host $host;
proxy_set_header X-real-ip $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://192.168.31.11/realip/;
}

error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}

7.Tengine 安全防护

7.1 禁止web服务IP直接访问

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#/usr/local/nginx/conf.d/defend.conf(禁止IP直接访问配置,默认开启)
#Nginx配置禁止IP直接访问,如果是直接使用IP访问,直接返回客户端403错误
#注意:对于https,必须指定证书,否则连域名访问也会一起禁止
server
{
listen 80 default;
#server_name _;
return 403;
}

server
{
listen 443 default;
#server_name _;
ssl_certificate /usr/local/nginx/certs/test.crt;
ssl_certificate_key /usr/local/nginx/certs/test.key;
return 403;
}

7.2 连接和请求数限制

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#/usr/local/nginx/conf.d/limit_rate.conf(连接和请求数限制脚本,默认关闭)
# 这里取得原始用户的IP地址
map $http_x_forwarded_for $clientRealIp {
"" $remote_addr;
~^(?P<firstAddr>[0-9\.]+),?.*$ $firstAddr;
}
# 设置白名单
geo $clientRealIp $whiteiplist {
default 1;
192.168.31.241 1;
192.168.31.251 0;
192.168.31.236 0;
192.168.31.0/24 0;
}
map $whiteiplist $limit {
1 $clientRealIp;
0 "";
}
# server 段配置
# if ( $whiteiplist = 0 ){
# return 403;
# }
# if ( $http_user_agent ~ Dalvik.* ){
# return 403;
# }


# 针对原始用户 IP 地址做限制
limit_conn_zone $limit zone=TotalConnLimitZone:20m ;
limit_conn TotalConnLimitZone 50; # 每个IP最大连接数
limit_conn_log_level notice;

# 针对原始用户 IP 地址做限制
limit_req_zone $limit zone=ConnLimitZone:20m rate=20r/s; #每个地址每秒只能请求同一个URL20次
limit_req zone=ConnLimitZone burst=10 nodelay; # 如果开启此条规则,burst=10的限制将会在nginx全局生效 一共有10块令牌,并且每秒钟只新增1块令牌,10块令牌发完后 多出来的那些请求就会返回503.
limit_req_log_level notice;

7.3 访问全站IP黑名单限制

1
2
3
4
5
6
7
#/usr/local/nginx/conf.d/globle_blacklistip.conf(访问全站限制IP)
#配置全局的对网站访问的限制,对特定的url进行访问限制可以在location里面进行配置
#############globle setting ##########
deny 192.168.31.69;
deny 192.168.31.70;
#deny 192.168.31.0/24 ;
allow all;

7.4 下载防盗链配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#/usr/local/nginx/conf.d/secure_link.conf(下载防盗链配置)
nginx 配置如下:
server {
listen 80;
server_name www.testchao.com #本机域名
access_log ../logs/ www.testchao.com.access.log main; #日志
location / {
root html;
#md5_hash[,expiration_time] MD5哈希值和过期时间
secure_link $arg_st,$arg_e;
#md5值对比结果,使用上面提供的uri、密钥、过期时间生成md5哈希值.如果它生成的md5哈希值与用户提交过来的哈希值一致,那么这个变量的值为1,否则为0
secure_link_md5 ttlsa.com$uri$arg_e;

if ($secure_link = "") {
return 403;
}

if ($secure_link = "0") {
return 403;
}
}

#php解析
location ~ \.php$ {
root html;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root/$fastcgi_script_name;
include fastcgi_params;
}
}

#下载页面php如下:
#download.php
<html>
<br>nginx下载页面
<br>
<a href="/test.php" class="btn btn-danger go-link" role="button" target="_blank" rel="nofollow" _hover-ignore="1">下载地址</a>
</html>

#test.php 生成连接页面
<?php
# 作用:生成nginx secure link链接
# 站点:www.qingye.info
# 作者:青叶
# 时间:2020-01-12
$secret = 'qingye'; # 密钥
$path = '/web/nginx-1.4.2.tar.gz.jpg'; # 下载文件
# 下载到期时间,time是当前时间,300表示300秒,也就是说从现在到300秒之内文件不过期
$expire = time()+10;
# 用文件路径、密钥、过期时间生成加密串
$md5 = base64_encode(md5($secret . $path . $expire .$_SERVER['REMOTE_ADDR'], true));
$md5 = strtr($md5, '+/', '-_');
$md5 = str_replace('=', '', $md5);
# 加密后的下载地址
$url = http://www.qingye.info/web/nginx-1.4.2.tar.gz.jpg?st='.$md5.'&e='.$expire;
#echo '<a href=http://www.qingye.info/web/nginx-1.4.2.tar.gz.jpg?st='.$md5.'&e='.$expire.'>nginx-1.4.2</a>';
#echo '<br>http://www.qingye.info/web/nginx-1.4.2.tar.gz.jpg?st='.$md5.'&e='.$expire;
header("Location: $url");
?>

8.Tengine 重要模块

8.1 upstream负载均衡模块

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#upstream模块详细例子
upstream backend {
#负载均衡算法,这个ip_hash根据IP来辨别,有时候因为访问都是从cdn或其他同一个IP过来,导致负载均衡发挥不好
ip_hash;
server 192.168.31.225:8080 weight 2;
server 192.168.31.226:8080 weight=1 max_fails=2 fail_timeout=30s ;
server 192.168.31.227:8080 backup;
}
server {
location / {
proxy_pass http://backend;
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
}

#weight : 轮询权值也是可以用在ip_hash的,默认值为1
#max_fails : 允许请求失败的次数,默认为1。当超过最大次数时,返回proxy_next_upstream 模块定义的错误。
#fail_timeout : 有两层含义,一是在 30s 时间内最多容许 2 次失败;二是在经历了 2 次失败以后,30s时间内不分配请求到这台服务器。
#backup : 预留的备份机器。当其他所有的非backup机器出现故障的时候,才会请求backup机器,因此这台机器的压力最轻。(为什么我的1.6.3版本里配置backup启动nginx时说invalid parameter "backup"?)
#max_conns: 限制同时连接到某台后端服务器的连接数,默认为0即无限制。因为queue指令是commercial,所以还是保持默认吧。
#proxy_next_upstream : 这个指令属于 http_proxy 模块的,指定后端返回什么样的异常响应时,使用另一个realserver

关于nginx使用负载均衡会话跟踪问题(ngx_http_upstream_session_sticky_module 模块,tenginx默认已经安装)

这个模块的作用是通过cookie黏贴的方式将来自同一个客户端(浏览器)的请求发送到同一个后端服务器上处理,这样一定程度上可以解决多个backend servers的session同步的问题 —— 因为不再需要同步,

而RR轮询模式(nginx的默认后端调度模式)必须要运维人员自己考虑session同步的实现。

语法:session_sticky [cookie=name] [domain=your_domain] [path=your_path] [maxage=time] [mode=insert|rewrite|prefix] [option=indirect] [maxidle=time] [maxlife=time] [fallback=on|off] [hash=plain|md5]
默认值:session_sticky cookie=route mode=insert fallback=on
上下文:upstream

说明:

本指令可以打开会话保持的功能,下面是具体的参数:

cookie设置用来记录会话的cookie名称

domain设置cookie作用的域名,默认不设置

path设置cookie作用的URL路径,默认不设置

maxage设置cookie的生存期,默认不设置,即为session cookie,浏览器关闭即失效

mode设置cookie的模式:

insert: 在回复中本模块通过Set-Cookie头直接插入相应名称的cookie。

prefix: 不会生成新的cookie,但会在响应的cookie值前面加上特定的前缀,当浏览器带着这个有特定标识的cookie再次请求时,模块在传给后端服务前先删除加入的前缀,后端服务拿到的还是原来的cookie值,这些动作对后端透明。如:”Cookie: NAME=SRV~VALUE”。

rewrite: 使用服务端标识覆盖后端设置的用于session sticky的cookie。如果后端服务在响应头中没有设置该cookie,则认为该请求不需要进行session sticky,使用这种模式,后端服务可以控制哪些请求需要sesstion sticky,哪些请求不需要。

option 设置用于session sticky的cookie的选项,可设置成indirect或direct。indirect不会将session sticky的cookie传送给后端服务,该cookie对后端应用完全透明。direct则与indirect相反。

maxidle设置session cookie的最长空闲的超时时间

maxlife设置session cookie的最长生存期

fallback设置是否重试其他机器,当sticky的后端机器挂了以后,是否需要尝试其他机器

hash 设置cookie中server标识是用明文还是使用md5值,默认使用md5
maxage是cookie的生存期。不设置时,浏览器或App关闭后就失效。下次启动时,又会随机分配后端服务器。所以如果希望该客户端的请求长期落在同一台后端服务器上,可以设置maxage。

hash不论是明文还是hash值,都有固定的数目。因为hash是server的标识,所以有多少个server,就有等同数量的hash值。

一些例外:

同一客户端的请求,有可能落在不同的后端服务器上## 如果客户端启动时同时发起多个请求。由于这些请求都没带cookie,所以服务器会随机选择后端服务器,返回不同的cookie。当这些请求中的最后一个请求返回时,客户端的cookie才会稳定下来,值以最后返回的cookie为准。

cookie不一定生效## 由于cookie最初由服务器端下发,如果客户端禁用cookie,则cookie不会生效。

客户端可能不带cookie## Android客户端发送请求时,一般不会带上所有的cookie,需要明确指定哪些cookie会带上。如果希望用sticky做负载均衡,请对Android开发说加上cookie。

注意事项:

cookie名称不要和业务使用的cookie重名。Sticky默认的cookie名称是route,可以改成任何值。但切记,不可以与业务中使用的cookie重名。
客户端发的第一个请求是不带cookie的。服务器下发的cookie,在客户端下一次请求时才能生效
另外内置的 ip_hash 也可以实现根据客户端IP来分发请求,但它很容易造成负载不均衡的情况,而如果nginx前面有CDN网络或者来自同一局域网的访问,它接收的客户端IP是一样的,容易造成负载不均衡现象。

这个模块并不合适不支持 Cookie 或手动禁用了cookie的浏览器,此时默认session_sticky就会切换成RR。它不能与ip_hash同时使用。

1
2
3
4
5
6
7
8
9
10
11
12
upstream backend {
check interval=3000 rise=2 fall=5 timeout=1000 type=http;
check_http_send "HEAD / HTTP/1.0\r\n\r\n";
check_http_expect_alive http_2xx http_3xx;
server 192.168.31.226:8080 weight=1;
server 192.168.31.227:8080 weight=1;
session_sticky;
#在insert + indirect模式或者prefix模式下需要配置session_sticky_hide_cookie
#这种模式不会将保持会话使用的cookie传给后端服务,让保持会话的cookie对后端透明
#session_sticky cookie=uid fallback=on mode=insert option=indirect hash=plain;
#配置起来超级简单,一般来说一个session_sticky指令就够了。
}

负载均衡其它调度方案

  • 轮询(默认) : 每个请求按时间顺序逐一分配到不同的后端服务器,如果后端某台服务器宕机,故障系统被自动剔除,使用户访问不受影响。Weight 指定轮询权值,Weight值越大,分配到的访问机率越高,主要用于后端每个服务器性能不均的情况下。

  • ip_hash : 每个请求按访问IP的hash结果分配,这样来自同一个IP的访客固定访问一个后端服务器,有效解决了动态网页存在的session共享问题。当然如果这个节点不可用了,会发到下个节点,而此时没有session同步的话就注销掉了。

  • least_conn : 请求被发送到当前活跃连接最少的realserver上。会考虑weight的值。

  • url_hash : 此方法按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器,可以进一步提高后端缓存服务器的效率。Nginx本身是不支持url_hash的,如果需要使用这种调度算法,必须安装Nginx 的hash软件包 nginx_upstream_hash 。

  • fair : 这是比上面两个更加智能的负载均衡算法。此种算法可以依据页面大小和加载时间长短智能地进行负载均衡,也就是根据后端服务器的响应时间来分配请求,响应时间短的优先分配。
    Nginx本身是不支持fair的,如果需要使用这种调度算法,必须下载Nginx的 upstream_fair 模块

8.2 rewrite重写模块

rewrite模块rewrite功能就是,使用nginx提供的全局变量或自己设置的变量,结合正则表达式和标志位实现url重写以及重定向。rewrite只能放在server{},location{},if{}中,
并且只能对域名后边的除去传递的参数外的字符串起作用,例如 http://seanlook.com/a/we/index.php?id=1&u=str 只对/a/we/index.php重写。语法rewrite regex replacement [flag];

flag标志位

1
2
3
4
last : 相当于Apache的[L]标记,表示完成rewrite
break : 停止执行当前虚拟主机的后续rewrite指令集
redirect : 返回302临时重定向,地址栏会显示跳转后的地址
permanent : 返回301永久重定向,地址栏会显示跳转后的地址

if指令与全局变量,if判断指令:

1
2
3
4
5
6
7
8
语法为if(condition){...},对给定的条件condition进行判断。如果为真,大括号内的rewrite指令将被执行,if条件(conditon)可以是如下任何内容:
当表达式只是一个变量时,如果值为空或任何以0开头的字符串都会当做false
直接比较变量和内容时,使用=或!=
~正则表达式匹配,~*不区分大小写的匹配,!~区分大小写的不匹配
-f和!-f用来判断是否存在文件
-d和!-d用来判断是否存在目录
-e和!-e用来判断是否存在文件或目录
-x和!-x用来判断文件是否可执行
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
if ($http_user_agent ~ MSIE) {
rewrite ^(.*)$ /msie/$1 break;
} //如果UA包含"MSIE",rewrite请求到/msid/目录下
if ($http_cookie ~* "id=([^;]+)(?:;|$)") {
set $id $1;
} //如果cookie匹配正则,设置变量$id等于正则引用部分
if ($request_method = POST) {
return 405;
} //如果提交方法为POST,则返回状态405(Method not allowed)。return不能返回301,302
if ($slow) {
limit_rate 10k;
} //限速,$slow可以通过 set 指令设置
if (!-f $request_filename){
break;
proxy_pass http://127.0.0.1;
} //如果请求的文件名不存在,则反向代理到localhost 。这里的break也是停止rewrite检查
if ($args ~ post=140){
rewrite ^ http://example.com/ permanent;
} //如果query string中包含"post=140",永久重定向到example.com
location ~* \.(gif|jpg|png|swf|flv)$ {
valid_referers none blocked www.jefflei.com www.leizhenfang.com;
if ($invalid_referer) {
return 404;
} //防盗链
}

下面是可以用作if判断的全局变量:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
$args  #这个变量等于请求行中的参数,同$query_string
$content_length 请求头中的Content-length字段。
$content_type 请求头中的Content-Type字段。
$document_root 当前请求在root指令中指定的值。
$host 请求主机头字段,否则为服务器名称。
$http_user_agent 客户端agent信息
$http_cookie 客户端cookie信息
$limit_rate 这个变量可以限制连接速率。
$request_method 客户端请求的动作,通常为GET或POST。
$remote_addr 客户端的IP地址。
$remote_port 客户端的端口。
$remote_user 已经经过Auth Basic Module验证的用户名。
$request_filename 当前请求的文件路径,由root或alias指令与URI请求生成。
$scheme HTTP方法(如http,https)。
$server_protocol 请求使用的协议,通常是HTTP/1.0或HTTP/1.1。
$server_addr 服务器地址,在完成一次系统调用后可以确定这个值。
$server_name 服务器名称。
$server_port 请求到达服务器的端口号。
$request_uri 包含请求参数的原始URI,不包含主机名,如:”/foo/bar.php?arg=baz”。
$uri 不带请求参数的当前URI,$uri不包含主机名,如”/foo/bar.html”。
$document_uri 与$uri相同。

常用正则:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
.  匹配除换行符以外的任意字符
? 重复0次或1次
+ 重复1次或更多次
* 重复0次或更多次
\d :匹配数字
^ 匹配字符串的开始
$ 匹配字符串的介绍
{n} 重复n次
{n,} 重复n次或更多次
[c] 匹配单个字符c
[a-z] 匹配a-z小写字母的任意一个
#小括号()之间匹配的内容,可以在后面通过$1来引用,$2表示的是前面第二个()里的内容。正则里面容易让人困惑的是\转义特殊字符。

break
语法:break
默认值:none
使用字段:server, location, if
完成当前设置的重写规则,停止执行其他的重写规则。

return
语法:return code
默认值:none
使用字段:server, location, if
停止处理并为客户端返回状态码。非标准的444状态码将关闭连接,不发送任何响应头。可以使用的状态码有:204,400,402-406,408,410, 411, 413, 416与500-504。如果状态码附带文字段落,该文本将被放置在响应主体。相反,如果状态码后面是一个URL,该URL将成为location头补值。没有状态码的URL将被视为一个302状态码。

rewrite
语法:rewrite regex replacement flag
默认值:none
使用字段:server, location, if
按照相关的正则表达式与字符串修改URI,指令按照在配置文件中出现的顺序执行。可以在重写指令后面添加标记。
注意:如果替换的字符串以http://开头,请求将被重定向,并且不再执行多余的rewrite指令。
尾部的标记(flag)可以是以下的值:
last - 停止处理重写模块指令,之后搜索location与更改后的URI匹配。
break - 完成重写指令。
redirect - 返回302临时重定向,如果替换字段用http://开头则被使用。
permanent - 返回301永久重定向。
rewrite_log
语法:rewrite_log on | off
默认值:rewrite_log off
使用字段:server, location, if
变量:无
启用时将在error log中记录notice级别的重写日志。

set
语法:set variable value
默认值:none
使用字段:server, location, if
为给定的变量设置一个特定值。
uninitialized_variable_warn
语法:uninitialized_variable_warn on|off
默认值:uninitialized_variable_warn on
使用字段:http, server, location, if
控制是否记录未初始化变量的警告信息。

例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#last和break实现URL重写,浏览器地址栏URL地址不变
location ~ ^/best/ {
rewrite ^/best/(.*) /test/$1 break;
proxy_pass http://www.taob.com
}

#更换域名
server{
server_name www.taob.com;
rewrite ^/(.*)$ http://www.tb.com/$1 permanent;
}
#或者
server {
server_name www.tb.com www.taob.com;
if ($host != 'www.tb.com')
rewrite ^/(.*)$ http://www.tb.com/$1 permanent;
}

9.location 在匹配中的优先级

配置文件示例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
location = / {

# 仅仅匹配请求 /

[ configuration A ]

}

location / {

# 匹配所有以 / 开头的请求。

# 但是如果有更长的同类型的表达式,则选择更长的表达式。

# 如果有正则表达式可以匹配,则优先匹配正则表达式。

[ configuration B ]

}

location /documents/ {

# 匹配所有以 /documents/ 开头的请求。

# 但是如果有更长的同类型的表达式,则选择更长的表达式。

# 如果有正则表达式可以匹配,则优先匹配正则表达式。

[ configuration C ]

}

location ^~ /images/ {

# 匹配所有以 /images/ 开头的表达式,如果匹配成功,则停止匹配查找。

# 所以,即便有符合的正则表达式location,也不会被使用

[ configuration D ]

}

location ~* \.(gif|jpg|jpeg)$ {

# 匹配所有以 gif jpg jpeg结尾的请求。

# 但是 以 /images/开头的请求,将使用 Configuration D

[ configuration E ]

}

匹配结果:

URL 匹配结果 原因
/ configuration A =优先级最高,匹配到结束
/index.html configuration B 路径匹配
/documents/document.html configuration C 第二个匹配到,往后继续匹配,发现第三个匹配最确
/images/1.gif configuration D 同时匹配第二个,第四个,和第五个。但是由于优先级问题
/documents/1.jpg configuration E 同时匹配第二个,第三个,和第五个。第五个是正则表达式

优先级如下:

(location =) > (location 完整路径) > (location ^~ 路径) > (location ,* 正则顺序) > (location 部分起始路径) > (/)

注: ~ 和 ~都是正则匹配 其中 ~ 不区分大小写 ~ 区分大小写

10.Tengine root 和 alias 的区别

nginx配置下有两个指定目录的执行,root和alias

例如有以下配置文件:

1
2
3
location /img/ {
alias /var/www/image/;
}

若按照上述配置的话,则访问/img/目录里面的文件时,ningx会自动去/var/www/image/目录找文件

1
2
3
location /img/ {
root /var/www/image;
}

若按照这种配置的话,则访问/img/目录下的文件时,nginx会去/var/www/image/img/目录下找文件。alias是一个目录别名的定义,root则是最上层目录的定义
还有一个重要的区别是alias后面必须要用“/”结束,否则会找不到文件的。。。而root则可有可无

11.Tengine TCP转发配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#nginx tcp 配置,这一段必须放在http上下文
tcp {
timeout 1d;
proxy_read_timeout 10d;
proxy_send_timeout 10d;
proxy_connect_timeout 30;
upstream api_server {
server 192.168.31.212:389 weight=5 max_fails=1 fail_timeout=10s;
}
server {
listen 1389;
proxy_connect_timeout 1s;
proxy_pass api_server;
}
}

12.Tengine 常用维护脚本或命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#1、查看安装的模块

/usr/local/nginx/sbin/nginx -m

#2、检测配置文件语法

/usr/local/nginx/sbin/nginx -t

#3、启动tenginx

/usr/local/nginx/sbin/nginx

#4、配置文件重新加载

/usr/local/nginx/sbin/nginx -s reload

#5、关闭nginx

/usr/local/nginx/sbin/nginx -s stop

#6、日志备份脚本

# /bin/bash

logs_path="/usr/local/nginx/logs/"

pid_path="/usr/local/nginx/logs/nginx.pid"

cut_path="/usr/local/nginx/logs/bak/"

[ -e $cut_path ] || mkdir -p $cut_path

cd $logs_path
for log_name in `ls *.log`;do
mv ${logs_path}${log_name} ${cut_path}${log_name}_$(date +"%Y-%m-%d").log
done

if [[ -s $pid_path ]]; then
kill -USR1 `cat ${pid_path}`
fi

find ${cut_path} -type f -name "*.log" -mtime +7 | xargs rm -f

13.参考文档

# 推荐文章
  1.docker常用容器管理命令
  2.docker镜像管理
  3.dockerfile指令
  4.深刻理解Docker镜像大小
  5.k8s专题[1.k8s基础概念]

评论


:D 一言句子获取中...