Sam's Notes | Sam Blog

梦想还是要有的,万一实现了呢

0%

nginx

主要内容

nginx

更新历史
2019-12-30 增加源码安装的自动日志归档
2020-04-20 add timeout config

安装

yum 安装

yum源

如果系统自带yum源中没有nginx,按如下增加

1
2
3
4
5
6
7
8
# vim /etc/yum.repos.d/nginx.repo
[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true

安装

    # install
    yum -y install nginx
    
    # check
    nginx -v

源码 安装

前提

  • 确保 Development Tools 已经安装

  • 增加nginx 用户

1
useradd nginx -s /sbin/nologin -M

安装

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
wget http://nginx.org/download/nginx-{版本}.tar.gz
tar -xzvf nginx-{版本}.tar.gz -C /usr/src
# 安装依赖
yum install -y zlib-devel.x86_64 pcre-devel.x86_64 openssl-devel
yum install -y gd-devel libxml2 libxml2-dev libxslt-devel perl-devel perl-ExtUtils-Embed GeoIP GeoIP-devel GeoIP-data

cd /usr/src/nginx-{版本}
# 以下是一行。。用于生成makefile。如果需要添加第三方模块,使用--add-module=/path/module1的方法编译
./configure --prefix=/usr/share/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib64/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --http-client-body-temp-path=/var/lib/nginx/tmp/client_body --http-proxy-temp-path=/var/lib/nginx/tmp/proxy --http-fastcgi-temp-path=/var/lib/nginx/tmp/fastcgi --http-uwsgi-temp-path=/var/lib/nginx/tmp/uwsgi --http-scgi-temp-path=/var/lib/nginx/tmp/scgi --pid-path=/run/nginx.pid --lock-path=/run/lock/subsys/nginx --user=nginx --group=nginx --with-file-aio --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_addition_module --with-http_xslt_module=dynamic --with-http_image_filter_module=dynamic --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_random_index_module --with-http_secure_link_module --with-http_degradation_module --with-http_slice_module --with-http_stub_status_module --with-http_perl_module=dynamic --with-http_auth_request_module --with-mail=dynamic --with-mail_ssl_module --with-pcre --with-pcre-jit --with-stream=dynamic --with-stream_ssl_module --with-debug


# make是生成在objs目录中,make install则安装到prefix所示的目录中
make && make install
# 没有错误出现的话,就可以进入nginx安装目录(/etc/nginx)配置。

nginx 服务

在 /usr/lib/systemd/system/目录下面新建一个nginx.service文件。

1
vim /usr/lib/systemd/system/nginx.service

内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
[Service]
Type=forking
PIDFile=/run/nginx.pid
# Nginx will fail to start if /run/nginx.pid already exists but has the wrong
# SELinux context. This might happen when running `nginx -t` from the cmdline.
# https://bugzilla.redhat.com/show_bug.cgi?id=1268621
ExecStartPre=/usr/bin/rm -f /run/nginx.pid
ExecStartPre=/usr/sbin/nginx -t
ExecStart=/usr/sbin/nginx
ExecReload=/bin/kill -s HUP $MAINPID
KillSignal=SIGQUIT
TimeoutStopSec=5
KillMode=mixed
PrivateTmp=true
# system limit open file and processes
LimitCORE=infinity
LimitNOFILE=100000
LimitNPROC=100000

[Install]
WantedBy=multi-user.target

参考 CENTOS/RHEL 7 系统中设置SYSTEMD SERVICE的ULIMIT资源限制

启动服务

1
2
3
4
5
6
mkdir -p /var/lib/nginx/tmp
chown -R nginx:nginx /var/lib/nginx/

chmod +x /usr/lib/systemd/system/nginx.service
systemctl daemon-reload
systemctl start nginx.service

日志

注意 源码安装默认不自动归档日志, 可用logrotate工具实现日志切割归档.

配置文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
╰─# rpm -ql logrotate
/etc/cron.daily/logrotate
/etc/logrotate.conf
/etc/logrotate.d
/etc/rwtab.d/logrotate
/usr/sbin/logrotate
/usr/share/doc/logrotate-3.8.6
/usr/share/doc/logrotate-3.8.6/CHANGES
/usr/share/doc/logrotate-3.8.6/COPYING
/usr/share/man/man5/logrotate.conf.5.gz
/usr/share/man/man8/logrotate.8.gz
/var/lib/logrotate
/var/lib/logrotate/logrotate.status

其中, /etc/logrotate.d/ 是用于存储各种自定义应用的配置文件的目录。该目录里的所有文件都会被主动的读入到 /etc/logrotate.conf中执行。该目录下的应用配置文件继承所有/etc/logrotate.conf 的默认参数。
因此我们可以新建一个针对nginx日志文件的轮循配置的文件,然后将这个文件放在 /etc/logrotate.d/ 目录下, 它就会主动的读入到/etc/logrotate.conf中执行, 以达到按指定频率定时执行的需求。

新建nginx文件, 存放在/etc/logrotate.d/ 文件夹下 /etc/logrotate.d/nginx, 内容如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/var/log/nginx/*log {
create 640 nginx root
daily
rotate 61
missingok
notifempty
compress
delaycompress
sharedscripts
postrotate
/bin/kill -USR1 `cat /run/nginx.pid 2>/dev/null` 2>/dev/null || true
endscript
}

  • /usr/local/nginx/logs 需要轮询日志路径
  • daily: 日志文件分割频度。可选值为 daily,monthly,weekly,yearly
  • rotate 61: 一次将存储61个归档日志。对于第62个归档,时间最久的归档将被删除。
  • missingok: 在日志轮循期间,任何错误将被忽略,例如“文件无法找到”之类的错误。
  • dateext 使用日期作为命名格式
  • compress: 在轮循任务完成后,已轮循的归档将使用gzip进行压缩。
  • nocompress: 如果你不希望对日志文件进行压缩,设置这个参数即可
  • delaycompress: 总是与compress选项一起用,delaycompress选项指示logrotate不要将最近的归档压缩,压缩将在下一次轮循周期进行。这在你或任何软件仍然需要读取最新归档时很有用。
  • notifempty: 如果日志文件为空,轮循不会进行。
  • sharedscripts 表示postrotate脚本在压缩了日志之后只执行一次
  • create 640 www root: 以指定的权限创建全新的日志文件,同时logrotate也会重命名原始日志文件。
  • postrotate/endscript: 最通常的作用是让应用重启,以便切换到新的日志文件, 在所有其它指令完成后,postrotate和endscript里面指定的命令将被执行。在这种情况下,rsyslogd 进程将立即再次读取其配置并继续运行。
logrotate 命令

运行
logrotate /etc/logrotate.d/nginx

测试
logrotate -d /etc/logrotate.d/nginx

强制执行
logrotate -vf /etc/logrotate.d/nginx

配置

主配置文件

主配置文件/etc/nginx/nginx.conf, 增加如下内容

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
worker_processes  auto;
user nginx nginx; # 指定Nginx服务的用户和用户组


# worker_rlimit_nofile 4096; # set open fd limit, 根据服务器具体情况 -- nginx.service 中全局制定


http {
#隐藏nginx版本号
server_tokens off;

types_hash_max_size 2048;

# 413 Request Entity Too Large
client_max_body_size 8m;

#nginx服务器与被代理服务连接超时时间,代理超时
proxy_connect_timeout 360;
proxy_read_timeout 360;
proxy_send_timeout 360;

# header
add_header X-Frame-Options "SAMEORIGIN";
add_header X-XSS-Protection "1; mode=block";
add_header X-Content-Type-Options "nosniff";

include /etc/nginx/conf.d/*/*.conf;
}

自定义conf 文件都可放入 /etc/nginx/conf.d

1
mkdir /etc/nginx/conf.d

子配置

子配置文件目录/etc/nginx/conf.d, 文件名*.conf, api.xxxx.conf 为例

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
server
{
listen 80;
server_name api.xxxx; #和tomcat的host name 或 alias name 一致。

index index.html;
# root ;
charset utf-8;

location /
{
proxy_pass http://localhost:8080; # tomcat 端口
proxy_redirect off;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $http_host;
}

location /status
{
stub_status on;
access_log off;
}

}

SSL HTTPS 转发

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
server
{
server_name api.xxxx.com ;
#if ($host = '*.xxxx.com') {
# rewrite ^/(.*)$ http://api.xxxx.com/$1 permanent;
#}


# if ($http_referer ~* "bb01.win") {
# rewrite ^/(.*)$ http://api.xxxx.com/$1 permanent;
# }

charset utf-8;
location /
{

proxy_pass http://127.0.0.1:8080;

proxy_redirect http:// https://;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host:$server_port;

}

client_max_body_size 50M;

error_page 404 /404.html;
location = /404.html {
root /usr/share/nginx/html;
internal;
}


listen 443 ssl;
ssl_certificate certificate.pem;
ssl_certificate_key privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

}

超时配置

以下都是默认值

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
http{
#读取http头部的超时时间,单位秒,连接建立后,服务端接收http头部,规定时间内没收到,则超时,返回给客服端408(request time out)
client_header_timeout 60;

#读取http body的超时时间,单位秒,连接建立后,服务端接收body,规定时间内没收到,则超时,返回给客服端408(request time out)
client_body_timeout 60;

#发送响应超时时间,单位秒,服务端向客户端发送数据包,规定时间内客户端没收到,则超时
send_timeout 60;

#保持闲置连接的超时时间,单位秒,超过后服务器和浏览器都会关闭连接
keepalive_timeout 75;

#域名解析超时时间,单位秒
resolve_timeout 30;

#nginx服务器与被代理服务连接超时时间,代理超时
proxy_connect_timeout 60;

#nginx服务器发送数据给被代理服务器超时时间,单位秒,规定时间内nginx服务器没发送数据,则超时
proxy_send_timeout 60;

#nginx服务器接收被代理服务器数据超时时间,单位秒,规定时间内nginx服务器没收到数据,则超时
proxy_read_timeout 60;
}

隐藏nginx 版本和服务器信息

语法: proxy_hide_header field;
默认值: —
上下文: http, server, location
nginx默认不会将“Date”、“Server”、“X-Pad”,和“X-Accel-…”响应头发送给客户端。proxy_hide_header指令则可以设置额外的响应头,这些响应头也不会发送给客户端。

proxy_pass_header: 和proxy_hide_header相反,如果希望允许传递某些响应头给客户端,可以使用proxy_pass_header指令。
为隐藏 nginx , 可以使用, 并在后端服务器处理不返回 服务器类型

1
2
3
location / {
proxy_pass_header Server;
}

异常页面配置

  • 异常页面存放
    默认存放在 /usr/share/nginx/html 目录下。

  • nginx配置文件

配置完类似下面的内容

1
2
3
4
5
6
7
8
9
10
11
12
server {
listen 80 default_server;
listen [::]:80 default_server ipv6only=on;

. . .

error_page 404 /40x.html;
location = /40x.html {
root /usr/share/nginx/html;
internal;
}
}

注意 : 如果配置多个 server, 需要在对应的server中配置 error_page 。

负载均衡

在子配置文件中

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
upstream xxxxServer {
# 策略, 默认轮循
# ip_hash;
# least_conn;



server 127.0.0.1:8080 ;
# server 127.0.0.1:8000 weight=3;;
# server 127.0.0.1:8080 down;

server 127.0.0.2:8080 fail_timeout=600s ;
# server 127.0.0.2:8080 fail_timeout=600s down;
}

server
{
listen 80;
server_name center.xxx.com ;
#if ($host = '*.xxxx.com') {
# rewrite ^/(.*)$ http://m.xxxx.com/$1 permanent;
#}


# if ($http_referer ~* "bb01.win") {
# rewrite ^/(.*)$ http://m.xxxx.com/$1 permanent;
# }


charset utf-8;

location /
{
proxy_pass http://xxxxServer;
proxy_redirect off;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $http_host;

}

# nginx 监控
location /status
{
stub_status on;
access_log off;
}


client_max_body_size 50M;

error_page 404 /404.html;
location = /404.html {
root /usr/share/nginx/html;
internal;
}


location ~ .mp4 {
mp4;
root /data/xxxx;
}


location ~ .apk {
root /data/xxxx;
}
}


nginx 的 upstream目前支持 4 种方式的分配

  • 轮询(默认)
    每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down掉,能自动剔除。
  • weight
    指定轮询几率,weight和访问比率成正比,用于后端服务器性能不均的情况。
  • ip_hash
    每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务器,可以解决session的问题。
  • least_conn
    最少连接。当某些请求需要更长时间来完成时,最少连接可以更公平的控制应用实例上的负载。

upstream 每个设备的状态:

  • down 表示单前的server暂时不参与负载
  • weight 默认为1.weight越大,负载的权重就越大。
  • max_fails :允许请求失败的次数默认为1.当超过最大次数时,返回proxy_next_upstream 模块定义的错误
  • fail_timeout:max_fails 次失败后,暂停的时间。
  • backup: 其它所有的非backup机器down或者忙的时候,请求backup机器。所以这台机器压力会最轻。

HTTPS

  • 非80/443端口
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
server
{
server_name test.domain.com ;

listen 8888 ssl;
ssl_certificate domain.pem;
ssl_certificate_key domain.key;
ssl_session_timeout 5m;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;

error_page 497 301 https://$http_host$request_uri;

proxy_intercept_errors on;
charset utf-8;

location /
{
proxy_pass http://xxxxxxxServer;
proxy_redirect off;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $http_host;

}
}

重点是 error_page 497 301 https://$http_host$request_uri;, 可以解决 The plain HTTP request was sent to HTTPS port 问题

497 HTTP Request Sent to HTTPS Port
An expansion of the 400 Bad Request response code, used when the client has made a HTTP request to a port listening for HTTPS requests.