nginx私房笔记

0 用途

Nginx("engine x")是一款是由俄罗斯的程序设计师Igor Sysoev所开发高性能的 [Web] 和 [反向代理] 服务器,也是一个 IMAP/POP3/SMTP 代理服务器。内存少,并发强.
Nginx 是开源、高性能、高可靠的 Web 和反向代理服务器,而且支持热部署,几乎可以做到 7 * 24 小时不间断运行,即使运行几个月也不需要重新启动。

  1. 静态页面服务
  2. 反向代理服务,负载均衡、缓存等

1 安装

采用编译安装,不建议rpm包或yum方式安装。

1.0 准备

操作系统版本:CentOS 7.3
nginx版本:1.14.0
安装编译需要的gcc和gcc-c++
yum install -y gcc gcc-c++
pcre-devel、openssl-devel、zlib-devel
yum install -y pcre pcre-devel openssl openssl-devel zlib zlib-devel
一般以上都不用安装

nginx-1.14.0.tar.gz
openssl-1.1.0h.tar.gz(可选)
pcre-8.42.tar.gz(可选,Nginx 支持 Rewrite 功能)

1.1 configure

nginx-1.14.tar.gz和openssl-1.1.0h.tar.gz包放到到/upgrade

cd /upgrade
tar xzvf nginx-1.14.0.tar.gz
tar xzvf openssl-1.1.0h.tar.gz

cd nginx-1.14

./configure --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module
指定ssl版本编译安装:
./configure --prefix=/usr/local/nginx --with-http_ssl_module --with-openssl=/upgrade/openssl-1.1.0h

--with-openssl=/usr/local/openssl/ 注意是解压目录,不是编译目录

1.2 make

make && make install

1.3 创建nginx专用账户(可选)

groupadd www
useradd -g www www

2 常用命令

查看版本
nginx -V
检查配置文件
nginx -t
指定其他配置文件启动nginx
nginx -c /application/nginx/conf/nginx-tmp.conf
启动nginx
nginx
停止nginx
nginx -s stop
重启nginx
nginx -s reload
参数解释
-s stop 快速停止nginx
-s quit 平滑停止nginx
-s reopen 重新打开日志文件
-s reload 平滑重载所有配置

3 配置文件

nginx.conf结构总览:

main        # 全局块,运行的用户组,pid存放路径,worker process数
├── events  # 配置 Nginx 服务器与用户的网络连接
├── http    # 配置代理,缓存,日志定义等绝大多数功能和第三方模块的配置
│   ├── upstream # 配置后端服务器具体地址,负载均衡用
│   ├── server   # 配置虚拟主机的相关参数,一个 http 块中可以有多个 server
│   ├── server
│   │   ├── location  # 配置请求的路由,用于匹配 uri
│   │   ├── location
│   │   └── ...
│   └── ...
└── ...

nginx.conf文件样例

user  nginx;                        # 运行用户,默认即是nginx,可以不进行设置
worker_processes  8;                # Nginx 进程数,一般设置为和 CPU 核数一样
worker_rlimit_nofile 65535;    #Nginx文件描述符修改
error_log  /var/log/nginx/error.log warn;   # Nginx 的错误日志存放目录级别
pid        /var/run/nginx.pid;      # Nginx 服务启动时的 pid 存放位置

events {
    use epoll;     # 使用epoll的I/O模型(如果你不知道Nginx该使用哪种轮询方法,会自动选择一个最适合你操作系统的)
    worker_connections 1024;   # 每个进程允许最大并发数
}

http {   # 配置使用最频繁的部分,代理、缓存、日志定义等绝大多数功能和第三方模块的配置都在这里设置
    # 设置日志模式
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;   # Nginx访问日志存放位置

    sendfile            on;   # 开启高效传输模式
    tcp_nopush          on;   # 减少网络报文段的数量
    tcp_nodelay         on;
    keepalive_timeout   65;   # 保持连接的时间,也叫超时时间,单位秒
    types_hash_max_size 2048;

    include             /etc/nginx/mime.types;      # 文件扩展名与类型映射表
    default_type        application/octet-stream;   # 默认文件类型

    include /etc/nginx/conf.d/*.conf;   # 加载子配置项
    
    server {
        listen       80;       # 配置监听的端口
        server_name  localhost;    # 配置的域名
        
        location / {
            root   /usr/share/nginx/html;  # 网站根目录
            index  index.html index.htm;   # 默认首页文件
            deny 172.168.22.11;   # 禁止访问的ip地址,可以为all
            allow 172.168.33.44;# 允许访问的ip地址,可以为all
        }
        
        error_page 500 502 503 504 /50x.html;  # 默认50x对应的访问页面
        error_page 400 404 error.html;   # 同上
    }
}

3.1 工作线程数配置优化

worker_processes 8;
一般配置成和cpu核数一致。(阻塞式的调用的话数量可以适当提高)
worker_connections 每个worker进程处理的并发连接数,默认512,一般调节为1024或65535。

Nginx支持以下I/O复用方法处理连接:select、 poll、 kqueue、 epoll、 rtsig、 /dev/poll、 eventport。它们分别适用于不同的操作系统,其中 epoll是Linux系统上面效率最高的: use epoll

3.2 日志的配置

  • log_format : 定义记录日志的格式
  • access_log : 指定日志文件路径及日志文件格式。默认access_log logs/access.log main;
    access_log /var/logs/nginx-access.log buffer=64k gzip flush=1m记录日志的I/O开销较高,缓存功能降低写日志的频率,从而提高性能。
  • error_log 级别 debug, info, notice, warn, error, crit 。
    默认为crit,error_log logs/error.log crit;
    log_format  main  '$remote_addr - $remote_user [$time_local] $request_time $upstream_response_time "$request" $upstream_addr'
                               '$status $body_bytes_sent "$http_referer" '
                               '"$http_user_agent" "$http_x_forwarded_for"';
image.png

$remote_addr #记录访问网站的客户端地址
$remote_user #远程客户端用户名
$time_local #记录访问时间与时区
$request_time 毛响应时间
$upstream_response_time 净响应时间
$request #用户的http请求起始行信息
$upstream_addr #真正提供服务的主机IP
$status #http状态码,记录请求返回的状态码,例如:200、301、404等
$body_bytes_sent #服务器发送给客户端的响应body字节数
$http_referer #记录此次请求是从哪个连接访问过来的,可以根据该参数进行防盗链设置。
$http_user_agent #记录客户端访问信息,例如:浏览器、手机客户端等
$http_x_forwarded_for #当前端有代理服务器时,设置web节点记录客户端地址的配置,此参数生效的前提是代理服务器也要进行相关的x_forwarded_for设置

3.3 location番外篇

location [ = | ~ | ~* | ^~] uri {
    ...
}
  • = 精确匹配。用于不含正则的 uri 前,如匹配成功,不再进行后续的查找;
  • ~ 表示用该符号后面的正则去匹配路径,区分大小写;
  • ^~ 用于不含正则表达式的 uri 前,表示如果该符号后面的字符是最佳匹配,采用该规则,不再进行后续的查找;
  • ~* 表示用该符号后面的正则去匹配路径,不区分大小写。跟 ~ 优先级都比较低,如有多个location的正则能匹配的话,则使用正则表达式最长的那个;

3.4 正向代理&反向代理

正向代理:浏览器无法直接访问facebook,可以通过一个代理服务器来访问facebook,这个服务器就叫正向代理。
反向代理:隐藏了真实的服务器,为服务器收发请求,使真实服务器对客户端不可见。客户——饭点店小二——各个大厨
例如:把访问 http://127.0.0.1:9001/csc 的请求转发到 http://127.0.0.1:8001

server {
  listen 9001;
  server_name *.sherlocked93.club;
  location ~ /csc/ {
    proxy_pass http://127.0.0.1:8001;
  } 
}
  • proxy_set_header:在将客户端请求发送给后端服务器之前,更改来自客户端的请求头信息;
  • proxy_connect_timeout:配置 Nginx 与后端代理服务器尝试建立连接的超时时间;
  • proxy_read_timeout:配置 Nginx 向后端服务器组发出 read 请求后,等待相应的超时时间;
  • proxy_send_timeout:配置 Nginx 向后端服务器组发出 write 请求后,等待相应的超时时间;
  • proxy_redirect:用于修改后端服务器返回的响应头中的 Location 和 Refresh。

3.5 负载均衡

数据流:
客户端——http请求——Nginx——tcp请求——后端服务器(jboss、tomcat、java服务等)

后端负载方式:

  • 1 RR轮询(万能油)
upstream iserver{
    server 192.168.10.1:80;
    server 192.168.10.2:80;
 }
  • 2 加权轮询(根据后端硬件条件分配流量)
upstream iserver{
    server 192.168.10.1:80 weight=1;
    server 192.168.10.2:80 weight=2;
}
  • 3 Ip hash(可以解决session不共享的问题)
upstream iserver{
    ip_hash;
    server 192.168.10.1:80 ;
    server 192.168.10.2:80 ;
}
  • 4 fair(响应时间短的优先分配)
upstream iserver{
    server 192.168.10.1:80 ;
    server 192.168.10.2:80 ;
    fair;
}
  • 5 url_hash(后端服务器为缓存)
upstream iserver{
    server 192.168.10.1:80 ;
    server 192.168.10.2:80 ;
    hash $request_uri; 
    hash_method crc32; 
}

3.6 SSL监听的配置

server

    {
        listen 80;
        #http
        rewrite ^(.*)$ https://${server_name}$1 permanent;    }
server
    {
        listen 443 ssl ;
        #https
        ...
        ssl on;
        ssl_certificate /usr/local/ssl/csc.crt;
        ssl_certificate_key /usr/local/ssl/csc.key;
        ...
}

3.7 非公开页面添加用户认证

  • 安装账号密码工具
    yum install httpd-tools
  • 生成一个账号密码文件
    htpasswd -bc 生成账号密码文件路径 账号名 密码
    htpasswd -bc /tmp/my.db admin 123456
  • 在nginx配置启用密码认证
location /iELK/ {
     root  html;
     index  index.html index.htm;
     auth_basic "input password";   # 登录界面提示信息
     auth_basic_user_file /tmp/my.db; # 密码工具生成的文件路径
}
  • 重新加载配置文件
    nginx -s reload
    image.png

3.8 连接优化

长连接的优势就是在一个 tcp 连接上可以传输多个 HTTP 请求, 减少建立连接和关闭连接的消耗和延迟。

3.81 client & nginx

http {                                                                  
    keepalive_timeout  120s;   #为 0 时禁用长连接                                  
    keepalive_requests 10000 ;   #  默认为 100
}

keepalive_timeout默认65s,一般情况下无需修改,对于一些请求比较大且后台服务处理能力强的场景,适当加大为120s。
keepalive_requests用于设置一个keep-alive连接上可以服务的请求的最大数量,当最大请求数量达到时,连接被关闭。高并发下,如果后台的处理能力很强,这个参数需要适当提高,否则不断的创建断开连接会消耗大量的资源,造成很多TIME_WAIT。

3.82 nginx & upstream

upstream http_backend {
        keepalive 512;
        server 127.0.0.1:8080;
}

server {
    ...
    location /http/ {
        proxy_pass http://iBackend;
        proxy_http_version 1.1; #设置http版本为1.1
        proxy_set_header Connection ""; #设置http头默认为长连接,不关闭
    }
}

默认nginx访问后端upstream是用的短连接(HTTP1.0),一个请求Nginx 新开一个端口和后端建立连接,后端执行完毕后主动关闭该链接。
Nginx从 1.1.4 开始,实现了对后端机器的长连接支持,这意味着 Nginx 与后端机器的通信效率更高,后端机器的负担更低。

注:keepalive指定的数值是Nginx每个worker连接后端的最大长连接数,而不是整个Nginx的。 修正:“最大空闲长连接数量”
The connections parameter sets the maximum number of idle keepalive connections to upstream servers that are preserved in the cache of each worker process. When this number is exceeded, the least recently used connections are closed.

目标QPS为6000,Web服务响应时间约为200ms,因此需要约1200个长连接。

查看本机连接情况:
netstat -n | grep ESTAB
netstat -n | grep TIME_WAIT
netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'

3.9 获取F5中真实IP

nginx取的 $remote_addr 并非真实ip,事实上$http_X_Forwarded_For 才是用户真实ip,$remote_addr只是f5映射后的内网地址。

在 http 模块添加如下语句:10.17.0.1为F5映射的

    set_real_ip_from 10.17.0.1;
    real_ip_header X-Forwarded-For;
    real_ip_recursive on;

set_real_ip_from是告诉nginx反代服务器地址,不是真实的用户IP。
real_ip_header是告诉nginx真实的用户IP取自X-Forwarded-For请求头(X-Forwarded-For自行百度)。

server {
  listen 8080;
  server_name  localhost;
  location / {
    index index.html index.htm;
    proxy_pass http://iweb;
    proxy_redirect http://iweb http://$host:$server_port;
    proxy_set_header Host $http_host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forward-For $proxy_add_x_forwarded_for;
    }

重新加载nginx配置之后,就可以看到nginx日志里记录的IP就是真实IP了。

启动nginx报:

nginx: [emerg] unknown directive "set_real_ip_from" in **

需要添加realip模块,重新编译nginx

./configure --prefix=/usr/local/nginx   --with-http_ssl_module \
--with-openssl=/upgrade/openssl-1.1.0h  \
--with-http_stub_status_module \
--with-http_realip_module

make !!!注意不要make install
备份原nginx执行文件,替换最新编译的nginx。

# cp /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx.bak
# cp ./objs/nginx /usr/local/nginx/sbin/

3.10 跨域请求

当前访问的网站向另一个网站发送请求获取数据的过程就是跨域请求。
跨域是浏览器的同源策略决定的,是一个重要的浏览器安全策略,用于限制一个 origin 的文档或者它加载的脚本与另一个源的资源进行交互,它能够帮助阻隔恶意文档。

  • 协议不同
  • host不同
  • 端口不同

4 nginx守护脚本&日志切割脚本

nginxmonitor.sh

#! /bin/bash

ipid=/usr/local/nginx/logs/nginx.pid

iNginxBin=/usr/local/nginx/sbin/nginx

iConfFile=/usr/local/nginx/conf/nginx.conf

if [ ! -f $iPid ]; then

     $iNginxBin -c $iConfFile

fi

nginxLogRotate.sh
日志切割脚本添加到crontab中。(通过linux自带的logrotate也可以实现,自行百度)

#!/bin/bash
#Rotate the Nginx logs to prevent a single logfile 
#from consuming too much disk space.
LOGS_PATH=./logs
YESTERDAY=$(date -d "yesterday" +%Y-%m-%d)
mv ${LOGS_PATH}/access.log ${LOGS_PATH}/access_${YESTERDAY}.log
mv ${LOGS_PATH}/error.log ${LOGS_PATH}/error_${YESTERDAY}.log
kill -USR1 $(cat ${LOGS_PATH}/nginx.pid)

5 linux系统参数优化

对于系统层面的调优,通常我们修改文件描述符限制、缓冲区队列长度以及临时端口数量就可以了。
个TCP连接都要占用一个文件描述符,一旦文件描述符耗尽,新的连接到来就会返回“Too many open files”这样的错误。vi /etc/sysctl.conf添加以下内容:

#系统级文件描述符限制
 fs.file-max =10000000
 fs.nr_open =10000000

# The length of the syn quene
 net.ipv4.tcp_max_syn_backlog =65535
# The length of the tcp accept queue
net.core.somaxconn =65535

#临时端口
net.ipv4.ip_local_port_range =102465535
#用于指定保留端口
net.ipv4.ip_local_reserved_ports =8080,8081,9000-9010

用户层级的限制vi /etc/security/limits.conf,添加以下内容:

*      soft      noproc  65535
*      hard    noproc  65535
*      hard   nofile      65535
*      soft   nofile      65535

保证用户层级限制不大于系统层级限制,否则可能会出现无法通过SSH登录系统的问题。修改完执行sysctl -p,然后查看ulimit -a是否修改成功。

[参考]

https://www.runoob.com/w3cnote/nginx-setup-intro.html
https://zhuanlan.zhihu.com/p/138791994
https://www.cnblogs.com/chopper-poet/p/10744214.html
https://mp.weixin.qq.com/s/mrS7kZX6MgLzaKP8Jv1ypg

演示点:

  • 页面服务器443
  • 日志格式修改
  • 负载均衡配置 api调用
  • 后端长链接测试

你可能感兴趣的:(nginx私房笔记)