安装
自动安装
# CentOS
sudo yum install nginx
# Ubuntu
sudo apt-get install nginx
安装后nginx路径为/usr/sbin/nginx
,配置文件为/etc/nginx/nginx.conf
手动安装
- 下载&解压
wget http://nginx.org/download/nginx-1.17.10.tar.gz
tar zxvf nginx-1.17.10.tar.gz
cd nginx-1.17.10
- 调整配置
./configure --without-http_rewrite_module
./configure --prefix=/usr/local/nginx --with-http_ssl_module # 安装SSL模块
如果有的依赖库没有,需要先安装
# centos
yum -y install pcre* #安装使nginx支持rewrite
yum -y install gcc-c++
yum -y install zlib*
yum -y install openssl openssl-devel
# ubuntu
apt-get install openssl
apt-get install libssl-dev
# 安装完后再次检查配置
./configure
查看默认安装的模块
cat nginx-1.17.2/auto/options | grep YES
- 编译&安装
make
sudo make install
- 修改配置
cd /usr/local/nginx/
vi conf/nginx.conf
# 参看当前 Nginx 最终的配置
sbin/nginx -T
# 检查配置是否有问题
nginx -t -c <配置路径>
- 启动Nginx
cd /usr/local/nginx
# 启动
sbin/nginx
# 停止/退出/重启/重载配置
sbin/nginx -s stop/quit/reopen/reload
- 配置 nginx 开机自启
参考:https://www.nginx.com/resources/wiki/start/topics/examples/systemd/
将以下内容写入文件/lib/systemd/system/nginx.service
[Unit]
Description=The NGINX HTTP and reverse proxy server
After=syslog.target network-online.target remote-fs.target nss-lookup.target
Wants=network-online.target
[Service]
Type=forking
PIDFile=/run/nginx.pid
ExecStartPre=/usr/local/nginx/sbin/nginx -t
ExecStart=/usr/local/nginx/sbin/nginx
ExecReload=/usr/local/nginx/sbin/nginx -s reload
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true
[Install]
WantedBy=multi-user.target
ubuntu版本
[Unit]
Description=A high performance web server and a reverse proxy server
Documentation=man:nginx(8)
After=network.target
[Service]
Type=forking
PIDFile=/run/nginx.pid
ExecStartPre=/usr/local/nginx/sbin/nginx -t -q -g 'daemon on; master_process on;'
ExecStart=/usr/local/nginx/sbin/nginx -g 'daemon on; master_process on;'
ExecReload=/usr/local/nginx/sbin/nginx -g 'daemon on; master_process on;' -s reload
ExecStop=-/sbin/start-stop-daemon --quiet --stop --retry QUIT/5 --pidfile /run/nginx.pid
TimeoutStopSec=5
KillMode=mixed
[Install]
WantedBy=multi-user.target
启动
systemctl enable nginx # 设置开机启动 Nginx
systemctl disable nginx # 关闭开机启动 Nginx
配置详解
基本结构
main # 全局配置,对全局生效
├── events # 配置影响 nginx 服务器或与用户的网络连接
├── http # 配置代理,缓存,日志定义等绝大多数功能和第三方模块的配置
│ ├── upstream # 配置后端服务器具体地址,负载均衡配置不可或缺的部分
│ ├── server # 配置虚拟主机的相关参数,一个 http 块中可以有多个 server 块
│ ├── server
│ │ ├── location # server 块可以包含多个 location 块,location 指令用于匹配 uri
│ │ ├── location
│ │ └── ...
│ └── ...
└── ...
配置文件的语法规则
- 配置文件由指令与指令块构成
- 每条指令以 “;” 分号结尾,指令与参数间以空格符号分隔
- 指令块以 {} 大括号将多条指令组织在一起
- include 语句允许组合多个配置文件以提升可维护性
- 通过 # 符号添加注释,提高可读性
- 通过 $ 符号使用变量
- 部分指令的参数支持正则表达式,例如常用的 location 指令
内置变量
变量 | 含义 |
---|---|
$host | 请求的host |
$request_method | 请求类型:GET,POST等 |
$remote_addr | 客户端IP地址 |
$remote_port | 客户端端口 |
$args | 请求中的参数 |
$content_length | Header中的Content-length |
$http_user_agent | 客户端agent |
$http_cookie | 客户端cookie |
$server_protocol | 请求的协议,如HTTP/1.1 |
$server_name | 服务器名称 |
$server_addr | 服务器地址 |
$server_port | 服务器端口 |
设置变量
设置变量$temp
,返回字符串 “hello world”
server {
listen 80;
server_name test.com;
location / {
set $temp hello;
return "$temp world";
}
}
日志配置
# 错误日志放在 main 全局区块中对全局生效
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
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 logs/access.log main;
# 关闭日志
access_log off;
}
Nginx常用功能
HTTP服务器
这样如果访问 http://ip 就会默认访问到 /usr/local/app 目录下面的 index.html,如果一个网站只是静态页面的话,那么就可以通过这种方式来实现部署,比如一个静态官网。
server {
listen 80;
server_name localhost;
location / {
root /usr/local/app;
index index.html;
}
}
动静分离
就是把动态和静态的请求分开。方式主要有两种:
- 一种是纯粹把静态文件独立成单独的域名,放在独立的服务器上,也是目前主流推崇的方案
- 一种方法就是动态跟静态文件混合在一起发布, 通过 nginx 配置来分开
# 所有静态请求都由nginx处理,存放目录为 html
location ~ \.(gif|jpg|jpeg|png|bmp|swf|css|js)$ {
root /usr/local/resource;
expires 10h; # 设置过期时间为10小时
}
# 所有动态请求都转发给 tomcat 处理
location ~ \.(jsp|do)$ {
proxy_pass 127.0.0.1:8888;
}
反向代理
server {
listen 8080;
server_name localhost;
# 用户访问 ip:8080/test 下的所有路径代理到 github
location /test {
proxy_pass https://github.com;
}
# 所有 /api 下的接口访问都代理到本地的 8888 端口
location /api {
proxy_pass http://127.0.0.1:8888;
}
}
正向代理
正向代理的对象是客户端,服务器端看不到真正的客户端。
resolver 8.8.8.8 # 谷歌的域名解析地址
server {
resolver_timeout 5s; // 设超时时间
location / {
# 当客户端请求我的时候,我会把请求转发给它
# $host 要访问的主机名 $request_uri 请求路径
proxy_pass http://$host$request_uri;
}
}
访问控制
server {
location ~ ^/index.html {
# index.html 页面访问控制
# 禁止 192.168.1.1 和 192.168.1.2 两个 ip 访问,其它全部允许
# 从上到下的顺序,匹配到了便跳出
deny 192.168.1.1;
deny 192.168.1.2;
allow all;
}
}
负载均衡
轮询策略(默认)
每个请求按时间顺序逐一分配到不同的后端服务器,如果有后端服务器挂掉,能自动剔除。但是如果其中某一台服务器压力太大,出现延迟,会影响所有分配在这台服务器下的用户。
http {
upstream test.com {
server 192.168.1.12:8887;
server 192.168.1.13:8888;
}
server {
location /api {
proxy_pass http://test.com;
}
}
}
根据服务器权重
http {
upstream test.com {
server 192.168.1.12:8887 weight=9;
server 192.168.1.13:8888 weight=1;
}
server {
location /api {
proxy_pass http://test.com;
}
}
}
客户端 ip 绑定(ip_hash)
来自同一个 ip 的请求永远只分配一台服务器,有效解决了动态网页存在的 session 共享问题。
http {
upstream test.com {
ip_hash;
server 192.168.1.12:8887;
server 192.168.1.13:8888;
}
server {
location /api {
proxy_pass http://test.com;
}
}
}
最小连接数策略
将请求优先分配给压力较小的服务器,它可以平衡每个队列的长度,并避免向压力大的服务器添加更多的请求。
http {
upstream test.com {
least_conn;
server 192.168.1.12:8887;
server 192.168.1.13:8888;
}
server {
location /api {
proxy_pass http://test.com;
}
}
}
最快响应时间策略(依赖于第三方 NGINX Plus)
http {
upstream test.com {
fair;
server 192.168.1.12:8887;
server 192.168.1.13:8888;
}
server {
location /api {
proxy_pass http://test.com;
}
}
}
按访问 url 的 hash 结果(第三方)
按访问 url 的 hash 结果来分配请求,使每个 url 定向到同一个后端服务器,后端服务器为缓存时比较有效。
http {
upstream test.com {
hash $request_uri;
hash_method crc32;
server 192.168.1.12:8887;
server 192.168.1.13:8888;
}
server {
location /api {
proxy_pass http://test.com;
}
}
}
gzip 压缩
开启 gzip 压缩可以大幅减少 http 传输过程中文件的大小,可以极大的提高网站的访问速度,基本是必不可少的优化操作
# 开启gzip 压缩
gzip on;
# gzip_types
# gzip_static on;
# gzip_proxied expired no-cache no-store private auth;
# gzip_buffers 16 8k;
gzip_min_length 1k;
gzip_comp_level 4;
gzip_http_version 1.0;
gzip_vary off;
gzip_disable "MSIE [1-6]\.";
请求限制
通过 limit_req_zone 限制请求数
http{
# 设置共享内存空间
# 如果共享内存空间被耗尽,服务器将会对后续所有的请求返回 503 (Service Temporarily Unavailable) 错误。
limit_conn_zone $binary_remote_addrzone=limit:10m;
server{
location /{
# 同一用户地址同一时间只允许有5个连接
limit_conn addr 5;
}
}
}
通过 limit_conn_zone 限制并发连接数
# 限制平均每秒不超过一个请求,同时允许超过频率限制的请求数不多于5个。
limit_req_zone $binary_remote_addr zone=creq:10 mrate=10r/s;
server{
location /{
limit_req zone=creq burst=5;
}
}
请求过滤
根据请求类型过滤
# 非指定请求全返回 403
if ( $request_method !~ ^(GET|POST|HEAD)$ ) {
return 403;
}
根据状态码过滤
error_page 502 503 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
根据 URL 名称过滤
if ($host = zy.com' ) {
#其中 $1是取自regex部分()里的内容,匹配成功后跳转到的URL。
rewrite ^/(.*)$ http://www.zy.com/$1 permanent;
}
location /test {
// /test 全部重定向到首页
rewrite ^(.*)$ /index.html redirect;
}
禁止指定 user_agent
# http_user_agent 为浏览器标识
# 禁止 user_agent 为baidu、360和sohu,~*表示不区分大小写匹配
if ($http_user_agent ~* 'baidu|360|sohu') {
return 404;
}
# 禁止 Scrapy 等工具的抓取
if ($http_user_agent ~* (Scrapy|Curl|HttpClient)) {
return 403;
代理缓存
nginx 可以对访问过的内容在 nginx 服务器本地建立副本,这样在一段时间内再次访问该数据,就不需要通过 nginx 服务器再次向后端服务器发出请求,减小数据传输延迟,提高访问速度:
proxy_cache_path usr/local/cache levels=1:2 keys_zone=my_cache:10m;
server {
listen 80;
server_name test.com;
location / {
proxy_cache my_cache;
proxy_pass http://127.0.0.1:8888;
proxy_set_header Host $host;
}
}
上面的配置表示:nginx 提供一块 10 M 的内存用于缓存,名字为 my_cache, levels 等级为 1:2,缓存存放的路径为 usr/local/cache
。
路径分离与路径转发
- test1.doc.test.club 自动指向 /usr/local/html/doc/test1 服务器地址;
- test2.doc.test.club 自动指向 /usr/local/html/doc/test2 服务器地址;
server {
listen 80;
server_name ~^([\w-]+)\.doc\.test\.club$;
root /usr/local/html/doc/$1;
}
- test1.serv.test.club/api?name=a 自动转发到 127.0.0.1:8080/test1/api?name=a
- test2.serv.test.club/api?name=a 自动转发到 127.0.0.1:8080/test2/api?name=a
server {
listen 80;
server_name ~^([\w-]+)\.serv\.test\.club$;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_pass http://127.0.0.1:8080/$1$request_uri;
}
}
单页面项目 history 路由配置
server {
listen 80;
server_name fe.sherlocked93.club;
location / {
root /usr/local/app/dist; # vue 打包后的文件夹
index index.html index.htm;
try_files $uri $uri/ /index.html @rewrites; # 默认目录下的 index.html,如果都不存在则重定向
expires -1; # 首页一般没有强制缓存
add_header Cache-Control no-cache;
}
location @rewrites { // 重定向设置
rewrite ^(.+)$ /index.html break;
}
}
配置 HTTPS
证书申请
# 安装 certbot
wget https://dl.eff.org/certbot-auto
chmod a+x certbot-auto
# 申请证书(注意:需要把要申请证书的域名先解析到这台服务器上,才能申请):
sudo ./certbot-auto certonly --standalone --email admin@abc.com -d test.com -d www.test.com
执行上面指令,按提示操作。
Certbot 会启动一个临时服务器来完成验证(会占用 80 端口或 443 端口,因此需要暂时关闭 Web 服务器),然后 Certbot 会把证书以文件的形式保存,包括完整的证书链文件和私钥文件。
文件保存在 /etc/letsencrypt/live/ 下面的域名目录下。
配置HTTPS
server{
listen 443 ssl http2; // 这里还启用了 http/2.0
ssl_certificate /etc/letsencrypt/live/test.com/fullchain.pem; # 证书文件地址
ssl_certificate_key /etc/letsencrypt/live/test.com/privkey.pem; # 私钥文件地址
server_name test.com www.test.com; # 证书绑定的域名
}
server {
listen 80;
server_name test.com www.test.com;
# 单域名重定向
if ($host = 'www.sherlocked93.club'){
return 301 https://www.sherlocked93.club$request_uri;
}
# 全局非 https 协议时重定向
if ($scheme != 'https') {
return 301 https://$server_name$request_uri;
}
# 或者全部重定向
return 301 https://$server_name$request_uri;
}
Nginx模块
模块分类
- 核心模块:nginx 最基本最核心的服务,如进程管理、权限控制、日志记录;
- 标准 HTTP 模块:nginx 服务器的标准 HTTP 功能;
- 可选 HTTP 模块:处理特殊的 HTTP 请求
- 邮件服务模块:邮件服务
- 第三方模块:作为扩展,完成特殊功能
核心模块
- ngx_core
- ngx_errlog
- ngx_conf
- ngx_events
- ngx_event_core
- ngx_epll
- ngx_regex
标准HTTP模块
- ngx_http
- ngx_http_core #配置端口,URI 分析,服务器相应错误处理,别名控制 (alias) 等
- ngx_http_log #自定义 access 日志
- ngx_http_upstream #定义一组服务器,可以接受来自 proxy, Fastcgi,Memcache 的重定向;主要用作负载均衡
- ngx_http_static
- ngx_http_autoindex #自动生成目录列表
- ngx_http_index #处理以/结尾的请求,如果没有找到 index 页,则看是否开启了 random_index;如开启,则用之,否则用 autoindex
- ngx_http_auth_basic #基于 http 的身份认证 (auth_basic)
- ngx_http_access #基于 IP 地址的访问控制 (deny,allow)
- ngx_http_limit_conn #限制来自客户端的连接的响应和处理速率
- ngx_http_limit_req #限制来自客户端的请求的响应和处理速率
- ngx_http_geo
- ngx_http_map #创建任意的键值对变量
- ngx_http_split_clients
- ngx_http_referer #过滤 HTTP 头中 Referer 为空的对象
- ngx_http_rewrite #通过正则表达式重定向请求
- ngx_http_proxy
- ngx_http_fastcgi #支持 fastcgi
- ngx_http_uwsgi
- ngx_http_scgi
- ngx_http_memcached
- ngx_http_empty_gif #从内存创建一个 1×1 的透明 gif 图片,可以快速调用
- ngx_http_browser #解析 http 请求头部的 User-Agent 值
- ngx_http_charset #指定网页编码
- ngx_http_upstream_ip_hash
- ngx_http_upstream_least_conn
- ngx_http_upstream_keepalive
- ngx_http_write_filter
- ngx_http_header_filter
- ngx_http_chunked_filter
- ngx_http_range_header
- ngx_http_gzip_filter
- ngx_http_postpone_filter
- ngx_http_ssi_filter
- ngx_http_charset_filter
- ngx_http_userid_filter
- ngx_http_headers_filter #设置 http 响应头
- ngx_http_copy_filter
- ngx_http_range_body_filter
- ngx_http_not_modified_filter
可选HTTP模块
- ngx_http_addition:在响应请求的页面开始或者结尾添加文本信息
- ngx_http_degradation:在低内存的情况下允许服务器返回 444 或者 204 错误
- ngx_http_perl
- ngx_http_flv:支持将 Flash 多媒体信息按照流文件传输,可以根据客户端指定的开始位置返回 Flash
- ngx_http_geoip:支持解析基于 GeoIP 数据库的客户端请求
- ngx_google_perftools
- ngx_http_gzip:gzip 压缩请求的响应
- ngx_http_gzip_static:搜索并使用预压缩的以.gz 为后缀的文件代替一般文件响应客户端请求
- ngx_http_image_filter:支持改变 png,jpeg,gif 图片的尺寸和旋转方向
- ngx_http_mp4:支持.mp4,.m4v,.m4a 等多媒体信息按照流文件传输,常与 ngx_http_flv 一起使用
- ngx_http_random_index:当收到 / 结尾的请求时,在指定目录下随机选择一个文件作为 index
- ngx_http_secure_link:支持对请求链接的有效性检查
- ngx_http_ssl:支持 https
- ngx_http_stub_status
- ngx_http_sub_module:使用指定的字符串替换响应中的信息
- ngx_http_dav:支持 HTTP 和 WebDAV 协议中的 PUT/DELETE/MKCOL/COPY/MOVE 方法
- ngx_http_xslt:将 XML 响应信息使用 XSLT 进行转换
邮件服务模块
- ngx_mail_core
- ngx_mail_pop3
- ngx_mail_imap
- ngx_mail_smtp
- ngx_mail_auth_http
- ngx_mail_proxy
- ngx_mail_ssl
第三方模块
- echo-nginx-module:支持在 nginx 配置文件中使用 echo/sleep/time/exec 等类 Shell 命令
- memc-nginx-module
- rds-json-nginx-module:使 nginx 支持 json 数据的处理
- lua-nginx-module
直播模块
HTTPS server示例
server {
listen 443 ssl;
server_name devcloud;
ssl_certificate /usr/local/ssl/mycert.pem;
ssl_certificate_key /usr/local/ssl/mykey.key;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
location / {
root html;
index index.html index.htm;
}
location /jupyter {
proxy_pass http://127.0.0.1:8888;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_redirect off;
}
location /prometheus/ {
proxy_pass http://127.0.0.1:9090/;
}
location /grafana/ {
proxy_pass http://127.0.0.1:3000/;
}
location /kibana/ {
proxy_pass http://127.0.0.1:5601/kibana/;
}
}