关键词: Nginx
环境与安装
本地安装
下载 nginx 的压缩包文件到根目录,官网下载地址:nginx.org/download /nginx-x.xx.xx.tar.gz
yum update #更新系统软件
cd /
wget nginx.org/download/nginx-1.23.3.tar.gz
# 解压 tar.gz 压缩包文件,进去 nginx-1.23.3.tar.gz
tar -xzvf nginx-1.23.3.tar.gz
cd nginx-1.23.3
# 进入文件夹后进行配置检查
./configure
通过配置检查,发现有报错。检查中发现一些依赖库没有找到,这时候需要先安装 nginx 的一些依赖库
yum -y install pcre* #安装使nginx支持rewrite
yum -y install gcc-c++
yum -y install zlib*
yum -y install openssl openssl-devel
再次进行检查操作 ./configure
没发现报错显示,接下来进行编译并安装的操作.
# 检查模块支持
./configure --prefix=/usr/local/nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_addition_module --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_auth_request_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-mail --with-mail_ssl_module --with-stream --with-stream_ssl_module --with-stream_realip_module --with-stream_ssl_preread_module --with-threads --user=www --group=www
查看默认安装的模块支持。
nginx-x.xx.x/auto/options
这个文件里面保存的就是 nginx 编译过程中的所有选项配置。
ls nginx-1.23.3 # 查看 nginx 的文件列表
cat nginx-1.17.2/auto/options | grep YES # 查看所有选项配置
编译并安装
make && make install
查看 nginx 安装后在的目录,可以看到已经安装到 /usr/local/nginx
目录。
whereis nginx
$nginx: /usr/local/nginx
启动 nginx 服务。
服务启动的时候如果报错:nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
通过命令查看本机网络地址和端口等一些信息,找到被占用的 80 端口 netstat -ntpl
的 tcp 连接,并杀死进程(kill 进程 pid)
cd /usr/local/nginx/sbin/
./nginx
# 如果报错
netstat -ntpl
kill 进程PID
./nginx # 再次启动
在浏览器直接访问 ip 地址,页面出现 Welcome to Nginx! 则安装成功。
服务器安装
需要远程连接工具 putty 或者 xshell 或者 xftp6
大致步骤和本地安装一样
-
远程连接工具连接上服务器
-
环境安装
yum -y install gcc gcc-c++ autoconf pcre-devel make automake
yum -y install wget httpd-tools vim # server and 编辑器
# 如果出现报错,确认是否是网络问题 `ping www.baidu.com`
# 新建文件夹
cd /
ls
cd root
mkdir hk
cd hk
mkdir app/backup/download/logs/work
# 基于Yum的方式安装Nginx,查看一下yum是否已经存在 `yum list | grep nginx`
# 自行配置yum源
vim /etc/yum.repos.d/nginx.repo
# 键盘按 i
[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/centos/7/$basearch/
gpgcheck=0
enabled=1
# 键盘按 esc
:wq
yum install nginx
# y
nginx -v # 版本号 安装成功
常用功能
正向代理
小故事:我(Client)想要买日本万代(Server)发售的手办(data),但是我没有条件(cors)亲自去买,这时候我就拜托经常去日本出差的小刚(proxy),让他帮我带回来.
客户端才能使用正向代理,比如 VPN 就是正向代理。是一个位于客户端和原始服务器(origin server)之间的服务器,为了从原始服务器取得内容,客户端向代理发送一个请求并指定目标(原始服务器),然后代理向原始服务器转交请求并将获得的内容返回给客户端。
resolver 8.8.8.8 # 谷歌的域名解析地址
server {
resolver_timeout 5s; // 设超时时间
location / {
# 当客户端请求我的时候,我会把请求转发给它
# $host 要访问的主机名 $request_uri 请求路径
proxy_pass http://$host$request_uri;
}
}
正向代理的对象是客户端,服务器端看不到真正的客户端。
反向代理
小故事:我(Client)想要买日本万代(server)发售的手办(data),通过日本亚马逊的万代旗舰店(Nginx)下单购买。
主要是通过反向代理解决跨域问题,其实反向代理还可以
- 用来控制缓存(代理缓存 proxy cache),
- 进行访问控制,通过反向代理来实现
- 负载均衡也是通过反向代理来实现的
cd etc/nginx/conf.d
vim 8001.conf
举例: 前端 server 的域名为:fe.server.com,后端服务的域名为:dev.server.com
server {
listen 80;
server_name fe.server.com;
location / {
proxy_pass dev.server.com;
}
}
server {
listen 8080;
# 用户访问 ip:8080/test 下的所有路径代理到 github
location /test {
proxy_pass https://github.com;
}
# 所有 /api 下的接口访问都代理到本地的 8888 端口
# 例如你本地运行的 java 服务的端口是 8888,接口都是以 /api 开头
location /api {
proxy_pass http://127.0.0.1:8888;
}
}
错误页面设置
cd /
cd etc/nginx/conf.d
vim default.conf
# 可以了解到 404 -> 404.html 500 502 -> 50x.html
# 单独错误 404
error_page 500 502 503 504 /50x.html;
error_page 404 /404_error.html;
cd /
cd usr/share/nginx/html
vim 404_error.html
# 进行 html 编辑 -> esc
:wq
# 重启服务
nginx -s quit
nginx
# 将错误页面指定到外部链接
cd /
vim etc/nginx/conf.d/default.conf
error_page 404 https:www.baidu.com;
访问控制/访问权限
vim etc/nginx/conf.d/default.conf
location
中增加
server {
location ~ ^/index.html {
# 匹配 index.html 页面 除了 127.0.0.1 以外都可以访问
deny 192.168.11.50 # ip地址 # 仅不允许
deny 192.168.1.1;
deny 192.168.1.2;
allow all;
# allow 为可以访问
# deny all 都不能反问
# deny 192.168.11.50/200 ip50-200都不能访问
}
}
# 根据目录确定访问 例子:img 文件夹可以访问
location =/img {
allow all;
}
# 正则表达式 ~<rxg> 下面的意思是 以php结尾的都不能访问
location ~\.php${
deny all
}
负载均衡
通过负载均衡充利用服务器资源,nginx 目前支持自带 4 种负载均衡策略,还有 2 种常用的第三方策略。
- 轮询
- 最小连接数
- 最快相应时间
- 客户端 ip 绑定
Upstream 指定后端服务器地址列表
upstream balanceServer {
server 10.1.22.33:12345;
server 10.1.22.34:12345;
server 10.1.22.35:12345;
}
- 在 server 中拦截响应请求,并将请求转发到 Upstream 中配置的服务器列表。
server {
server_name fe.server.com;
listen 80;
location /api {
proxy_pass http://balanceServer;
}
}
上面的配置只是指定了 nginx 需要转发的服务端列表,并没有指定分配策略。
轮询
默认情况下采用的策略,将所有客户端请求轮询分配给服务端。这种策略是可以正常工作的,但是如果其中某一台服务器压力太大,出现延迟,会影响所有分配在这台服务器下的用户。
upstream balanceServer {
server 10.1.22.33:12345;
server 10.1.22.34:12345;
server 10.1.22.35:12345;
}
http {
upstream test.com {
server 192.168.1.12:8887;
server 192.168.1.13:8888;
}
server {
location /api {
proxy_pass http://test.com;
}
}
}
服务器权重
例如要配置:10 次请求中大概 1 次访问到 8888 端口,9 次访问到 8887 端口:
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;
}
}
}
最小连接数
将请求优先分配给压力较小的服务器,它可以平衡每个队列的长度,并避免向压力大的服务器添加更多的请求。
upstream balanceServer {
least_conn;
server 10.1.22.33:12345;
server 10.1.22.34:12345;
server 10.1.22.35:12345;
}
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
,优先分配给响应时间最短的服务器。
upstream balanceServer {
fair;
server 10.1.22.33:12345;
server 10.1.22.34:12345;
server 10.1.22.35:12345;
}
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;
}
}
}
客户端 ip 绑定
来自同一个 ip 的请求永远只分配一台服务器,有效解决了动态网页存在的 session
共享问题。
upstream balanceServer {
ip_hash;
server 10.1.22.33:12345;
server 10.1.22.34:12345;
server 10.1.22.35:12345;
}
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;
}
}
}
gzip 压缩
对于文本文件,gzip 的效果非常明显,开启后传输所需流量大约会降至 1/4 至 1/3。
并不是每个浏览器都支持 gzip。如何知道客户端是否支持 gzip 呢?
请求头中的 Accept-Encoding
来标识对压缩的支持。
vim etc/nginx/nginx.conf
# http 内部
gzip on;
gzip_http_version 1.1; # HTTP/1.1默认支持TCP持久连接
gzip_comp_level 5;
gzip_min_length 1000;
gzip_types text/csv text/xml text/css text/plain text/javascript application/javascript application/x-javascript application/json application/xml;
gzip_http_version 相关问题:为什么 gzip_http_version 设置为 1.1?
Nginx 启用 GZip 的情况下,不会等文件 GZip 完成再返回响应,而是边压缩边响应。这样可以显著提高 TTFB(Time To First Byte,首字节时间,WEB 性能优化重要指标)。
这样唯一的问题是: Nginx 开始返回响应时,它无法知道将要传输的文件最终有多大,也就无法给出 Content-Length
这个响应头部。
HTTP/1.0
可通过显式指定 Connection: keep-alive
来启用持久连接。对于 TCP 持久连接上的 HTTP 报文,客户端需要一种机制来准确判断结束位置,而在 HTTP/1.0
中,这种机制只有Content-Length
。如果启用GZip,是无法获得 Content-Length
的,这导致 HTTP1.0
中开启持久连接和使用 GZip 只能二选一。
在 HTTP/1.1
中新增的 Transfer-Encoding: chunked
所对应的分块传输机制可以完美解决这类问题。
所以在这里 gzip_http_version
默认设置为1.1。
gzip on; # 开启gzip 压缩
# 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]\.";
HTTP 服务器
nginx 本身也是一个静态资源的服务器,当只有静态资源的时候,就可以使用 nginx 来做服务器。
这样如果访问 http://ip 就会默认访问到 /usr/local/app
目录下面的 index.html
,如果一个网站只是静态页面的话,那么就可以通过这种方式来实现部署,比如一个静态官网。
server {
listen 80;
server_name localhost;
location / {
root /usr/local/app;
index index.html;
}
}
动静分离
就是把动态和静态的请求分开。方式主要有两种:
- 一种是纯粹把静态文件独立成单独的域名,放在独立的服务器上,也是目前主流推崇的方案
- 一种方法就是动态跟静态文件混合在一起发布, 通过 nginx 配置来分开
注意设置了 expires,当 nginx 设置了 expires 后,例如设置为:expires 10d;
那么,所在的 location 或 if 的内容,用户在 10 天内请求的时候,都只会访问浏览器中的缓存,而不会去请求 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;
}
请求限制
对于大流量恶意的访问,会造成带宽的浪费,给服务器增加压力。可以通过 nginx 对于同一 IP 的连接数以及并发数进行限制。合理的控制还可以用来防止 DDos 和 CC 攻击。
关于请求限制主要使用 nginx 默认集成的 2 个模块:
limit_conn_module
连接频率限制模块limit_req_module
请求频率限制模块
涉及到的配置主要是:
limit_req_zone
限制请求数limit_conn_zone
限制并发连接数- 通过
limit_req_zone
限制请求数
http{
limit_conn_zone $binary_remote_addrzone=limit:10m; // 设置共享内存空间大
server{
location /{
limit_conn addr 5; # 同一用户地址同一时间只允许有5个连接。
}
}
}
如果共享内存空间被耗尽,服务器将会对后续所有的请求返回 503 (Service Temporarily Unavailable) 错误。
当多个 limit_conn_zone 指令被配置时,所有的连接数限制都会生效。比如,下面配置不仅会限制单一 IP 来源的连接数,同时也会限制单一虚拟服务器的总连接数:
limit_conn_zone $binary_remote_addr zone=perip:10m;
limit_conn_zone $server_name zone=perserver:10m;
server {
limit_conn perip 10; # 限制每个 ip 连接到服务器的数量
limit_conn perserver 2000; # 限制连接到服务器的总数
}
通过 limit_conn_zone 限制并发连接数
limit_req_zone $binary_remote_addr zone=creq:10 mrate=10r/s;
server{
location /{
limit_req zone=creq burst=5;
}
}
限制平均每秒不超过一个请求,同时允许超过频率限制的请求数不多于 5 个。如果不希望超过的请求被延迟,可以用 nodelay 参数,如:
limit_req zone=creq burst=5 nodelay;
适配 PC 和 手机
根据用户设备不同返回不同样式的站点,以前经常使用的是纯前端的自适应布局,但是复杂的网站并不适合响应式,无论是复杂性和易用性上面还是不如分开编写的好,比如淘宝、京东。
根据用户请求的 user-agent
来判断是返回 PC 还是 H5 站点:
/usr/share/nginx/
新建文件夹mkdir pc & mobile
pc/moblie
新建index.htmletc/nginx/conf.d
server{
listen 80;
server_name www.huakang.live;
location / {
root /usr/share/nginx/pc;
if ($http_user_agent ~* '(Android|webOS|iPhone|iPod|BlackBerry)') { # 通过内置变量 $http_user_agent,可以获取到请求客户端的userAgent
root /usr/share/nginx/mobile;
}
index index.html;
}
}
server {
listen 80;
server_name test.com;
location / {
root /usr/local/app/pc; # pc 的 html 路径
if ($http_user_agent ~* '(Android|webOS|iPhone|iPod|BlackBerry)') {
root /usr/local/app/mobile; # mobile 的 html 路径
}
index index.html;
}
}
图片防盗链
server {
listen 80;
server_name *.test;
# 图片防盗链
location ~* \.(gif|jpg|jpeg|png|bmp|swf)$ {
valid_referers none blocked server_names ~\.google\. ~\.baidu\. *.qq.com; # 只允许本机 IP 外链引用,将百度和谷歌也加入白名单有利于 SEO
if ($invalid_referer){
return 403;
}
}
}
设置二级域名
新建一个 server 即可
server {
listen 80;
server_name admin.test.com; // 二级域名
location / {
root /usr/local/app/admin; # 二级域名的 html 路径
index index.html;
}
}
配置 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/
下面的域名目录下。
修改 nginx 配置
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; // 证书绑定的域名
}
配置 HTTP 转 HTTPS
配置选择自己需要的一条即可,不用全部加。
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;
}
单页面项目 history 路由配置
vue-router 官网只有一句话
try_files $uri $uri/ /index.html;
,而上面做了一些重定向处理。
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;
}
}
配置高可用集群(双机热备)
当主 nginx 服务器宕机之后,切换到备份的 nginx 服务器。
首先安装 keepalived
yum install keepalived -y
然后编辑 /etc/keepalived/keepalived.conf
配置文件,并在配置文件中增加 vrrp_script 定义一个外围检测机制,并在 vrrp_instance 中通过定义 track_script 来追踪脚本执行过程,实现节点转移
global_defs{
notification_email {
cchroot@gmail.com
}
notification_email_from test@firewall.loc
smtp_server 127.0.0.1
smtp_connect_timeout 30 // 上面都是邮件配置
router_id LVS_DEVEL // 当前服务器名字,用 hostname 命令来查看
}
vrrp_script chk_maintainace { // 检测机制的脚本名称为chk_maintainace
script "[[ -e/etc/keepalived/down ]] && exit 1 || exit 0" // 可以是脚本路径或脚本命令
// script "/etc/keepalived/nginx_check.sh" // 比如这样的脚本路径
interval 2 // 每隔2秒检测一次
weight -20 // 当脚本执行成立,那么把当前服务器优先级改为-20
}
vrrp_instanceVI_1 { // 每一个vrrp_instance就是定义一个虚拟路由器
state MASTER // 主机为MASTER,备用机为BACKUP
interface eth0 // 网卡名字,可以从ifconfig中查找
virtual_router_id 51 // 虚拟路由的id号,一般小于255,主备机id需要一样
priority 100 // 优先级,master的优先级比backup的大
advert_int 1 // 默认心跳间隔
authentication { // 认证机制
auth_type PASS
auth_pass 1111 // 密码
}
virtual_ipaddress { // 虚拟地址vip
172.16.2.8
}
}
其中检测脚本 nginx_check.sh,这里提供一个:
#!/bin/bash
A=`ps -C nginx --no-header | wc -l`
if [ $A -eq 0 ];then
/usr/sbin/nginx # 尝试重新启动nginx
sleep 2 # 睡眠2秒
if [ `ps -C nginx --no-header | wc -l` -eq 0 ];then
killall keepalived # 启动失败,将keepalived服务杀死。将vip漂移到其它备份节点
fi
fi
复制一份到备份服务器,备份 nginx 的配置要将 state 后改为 BACKUP
,priority 改为比主机小。设置完毕后各自 service keepalived start 启动,经过访问成功之后,可以把 Master 机的 keepalived 停掉,此时 Master 机就不再是主机了 service keepalived stop,看访问虚拟 IP 时是否能够自动切换到备机 ip addr。
再次启动 Master 的 keepalived,此时 vip 又变到了主机上。
代理缓存
nginx 的 http_proxy
模块,提供类似于 Squid 的缓存功能,使用 proxy_cache_path
来配置。
nginx 可以对访问过的内容在 nginx 服务器本地建立副本,这样在一段时间内再次访问该数据,就不需要通过 nginx 服务器再次向后端服务器发出请求,减小数据传输延迟,提高访问速度。
下面配置表示:nginx 提供一块 10 M 的内存用于缓存,名字为 my_cache
, levels 等级为 1:2,缓存存放的路径为 usr/local/cache
。
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 的默认配置
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;
}
错误日志
错误日志放在 main 全局区块中,童鞋们打开 nginx.conf
就可以看见在配置文件中和下面一样的代码了
nginx 错误日志默认配置为: error_log logs/error.log error;
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
静态资源服务器
匹配以 png|gif|jpg|jpeg
为结尾的请求,并将请求转发到本地路径,root中指定的路径即 nginx 本地路径。同时也可以进行一些缓存的设置。
location ~* \.(png|gif|jpg|jpeg)$ {
root /root/static/;
autoindex on;
access_log off;
expires 10h;# 设置过期时间为 10 小时
}
server {
listen 80;
server_name static.bin;
charset utf-8; # 防止中文文件名乱码
location /download {
alias /usr/share/nginx/static; # 静态资源目录
autoindex on; # 开启静态资源列目录,浏览目录权限
autoindex_exact_size off; # on(默认)显示文件的确切大小,单位是byte;off显示文件大概大小,单位KB、MB、GB
autoindex_localtime off; # off(默认)时显示的文件时间为GMT时间;on显示的文件时间为服务器时间
}
}
禁止指定 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;
}
请求过滤
- 状态码过滤
error_page 500 501 502 503 504 506 /50x.html;
location = /50x.html {
# 将跟路径改编为存放 html 的路径。
root /root/static/html;
}
这样实际上是一个内部跳转,当访问出现 502、503 的时候就能返回 50x.html
中的内容,这里需要注意是否可以找到 50x.html
页面,所以加了个 location 保证找到你自定义的 50x 页面。
- 根据 URL 名称过滤,精准匹配 URL,不匹配的 URL 全部重定向到主页。
location / {
rewrite ^.*$ /index.html redirect;
}
if ($host = baidu.com' ) {
#其中 $1是取自regex部分()里的内容,匹配成功后跳转到的URL。
rewrite ^/(.*)$ http://www.baidu.com/$1 permanent;
}
location /test {
// /test 全部重定向到首页
rewrite ^(.*)$ /index.html redirect;
}
- 根据请求类型过滤
if ( $request_method !~ ^(GET|POST|HEAD)$ ) {
return 403;
}
ab 命令
测试前需要安装 httpd-tools:yum install httpd-tools
ab 命令全称为:Apache bench,是 Apache 自带的压力测试工具,也可以测试 Nginx、IIS 等其他 Web 服务器:
- -n 总共的请求数
- -c 并发的请求数
- -t 测试所进行的最大秒数,默认值 为 50000
- -p 包含了需要的 POST 的数据文件
- -T POST 数据所使用的 Content-type 头信息
ab -n 1000 -c 5000 http://127.0.0.1/ # 每次发送1000并发的请求数,请求数总数为5000。
泛域名路径分离
配置一些二级或者三级域名,希望通过 nginx 自动指向对应目录,比如:
- 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;
}
}
【云】设置虚拟主机
- 基于端口号配置虚拟主机
cd /
cd etc/nginx/conf.d
# 新建 8001的conf 文件
server{
listien 8001;# 监听的端口号
server_name localhost; # 服务名称
root /usr/share/nginx/html/html8001;# 文件放置的路径
index index.html # 索引目录
}
:wq
pwd # 查看当前文件路径
cd usr/share/nginx/html/
mkdir html8001
vim index.html
nginx -s quit
nginx
【云】设置域名虚拟机 cd etc/nginx/conf.d
# default.conf
server {
listen 80;
server_name www.huakang.live;
}
# 8001.conf
server{
listen 80;
server_name www.huakang.live;
location / {
root /usr/share/nginx/html/html8001;
index index.html index.htm;
}
}
常见问题
nginx 中怎么设置变量
# set $name "chroot";
server {
listen 80;
server_name test.com;
location / {
set $temp hello;
return "$temp world";
}
}
# 当引用的变量名之后紧跟着变量名的构成字符时(比如后跟字母、数字以及下划线),我们就需要使用特别的记法来消除歧义
server {
listen 80;
server_name test.com;
location / {
set $temp "hello ";
# 直接写作 "$tempworld" 有问题
return "${temp}world";
}
}
# 若是想输出 $ 符号本身
geo $dollar {
default "$";
}
server {
listen 80;
server_name test.com;
location / {
set $temp "hello ";
return "${temp}world: $dollar";
}
}
配置Nginx
找到 nginx 所在目录
# rpm-> linux 包管理 -q 查询 l 返回列表
rpm -ql nginx
vim etc/nginx/nginx.conf
Nginx 基本结构
main # 全局配置,对全局生效
├── events # 配置影响 nginx 服务器或与用户的网络连接
├── http # 配置代理,缓存,日志定义等绝大多数功能和第三方模块的配置
│ ├── upstream # 配置后端服务器具体地址,负载均衡配置不可或缺的部分
│ ├── server # 配置虚拟主机的相关参数,一个 http 块中可以有多个 server 块
│ ├── server
│ │ ├── location # server 块可以包含多个 location 块,location 指令用于匹配 uri
│ │ ├── location
│ │ └── ...
│ └── ...
└── ...
主要配置含义
- main:nginx 的全局配置,对全局生效。
- events:配置影响 nginx 服务器或与用户的网络连接。
- http:可以嵌套多个 server,配置代理,缓存,日志定义等绝大多数功能和第三方模块的配置。
- server:配置虚拟主机的相关参数,一个 http 中可以有多个 server。
- location:配置请求的路由,以及各种页面的处理情况。
- upstream:配置后端服务器具体地址,负载均衡配置不可或缺的部分。
nginx.conf 配置文件的语法规则
- 配置文件由指令与指令块构成
- 每条指令以 “;” 分号结尾,指令与参数间以空格符号分隔
- 指令块以 {} 大括号将多条指令组织在一起
- include 语句允许组合多个配置文件以提升可维护性
- 通过 # 符号添加注释,提高可读性
- 通过 $ 符号使用变量
- 部分指令的参数支持正则表达式,例如常用的 location 指令
修改配置文件
#运行用户,默认即是nginx,可以不进行设置
user nginx;
#Nginx进程,一般设置为和CPU核数一样
worker_processes 1;
#错误日志存放目录
error_log /var/log/nginx/error.log warn;
#进程pid存放位置
pid /var/run/nginx.pid;
events {
worker_connections 1024; # 单个后台进程的最大并发数
}
http {
include /etc/nginx/mime.types; #文件扩展名与类型映射表
default_type application/octet-stream; #默认文件类型
#设置日志模式
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; #减少网络报文段的数量
keepalive_timeout 65; #保持连接的时间,也叫超时时间
#gzip on; #开启gzip压缩
include /etc/nginx/conf.d/*.conf; #包含的子配置项位置和文件
}
修改子配置项
vim conf.d/default.conf
server {
listen 80; #配置监听端口
server_name localhost; //配置域名
#charset koi8-r;
#access_log /var/log/nginx/host.access.log main;
location / {
root /usr/share/nginx/html; #服务默认启动目录
index index.html index.htm; #默认访问文件
}
#error_page 404 /404.html; # 配置404页面
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html; #错误状态码的显示页面,配置后需要重启
location = /50x.html {
root /usr/share/nginx/html;
}
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
# root html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include fastcgi_params;
#}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}
配置 nginx 开机自启
利用 systemctl 命令
如果用 yum install
命令安装的 nginx,yum 命令会自动创建 nginx.service
文件,直接用命令
systemctl enable nginx # 设置开机启动 Nginx
systemctl disable nginx # 关闭开机启动 Nginx
就可以设置开机自启,否则需要在系统服务目录里创建 nginx.service
文件。
创建并打开 nginx.service
文件:
vi /lib/systemd/system/nginx.service
[Unit]
Description=nginx
After=network.target
[Service]
Type=forking
ExecStart=/usr/local/nginx/sbin/nginx
ExecReload=/usr/local/nginx/sbin/nginx -s reload
ExecStop=/usr/local/nginx/sbin/nginx -s quit
PrivateTmp=true
[Install]
WantedBy=multi-user.target
:wq
保存退出,运行 systemctl daemon-reload
使文件生效。
这样便可以通过以下命令操作 nginx 了
systemctl start nginx.service # 启动nginx服务
systemctl enable nginx.service # 设置开机启动
systemctl disable nginx.service # 停止开机自启动
systemctl status nginx.service # 查看服务当前状态
systemctl restart nginx.service # 重新启动服务
systemctl is-enabled nginx.service #查询服务是否开机启动
通过开机启动命令脚本实现开机自启
创建开机启动命令脚本文件:vi /etc/init.d/nginx
在这个 nginx 文件中插入一下启动脚本代码,启动脚本代码来源网络复制,实测有效:
#! /bin/bash
# chkconfig: - 85 15
PATH=/usr/local/nginx
DESC="nginx daemon"
NAME=nginx
DAEMON=$PATH/sbin/$NAME
CONFIGFILE=$PATH/conf/$NAME.conf
PIDFILE=$PATH/logs/$NAME.pid
scriptNAME=/etc/init.d/$NAME
set -e
[ -x "$DAEMON" ] || exit 0
do_start() {
$DAEMON -c $CONFIGFILE || echo -n "nginx already running"
}
do_stop() {
$DAEMON -s stop || echo -n "nginx not running"
}
do_reload() {
$DAEMON -s reload || echo -n "nginx can't reload"
}
case "$1" in
start)
echo -n "Starting $DESC: $NAME"
do_start
echo "."
;;
stop)
echo -n "Stopping $DESC: $NAME"
do_stop
echo "."
;;
reload|graceful)
echo -n "Reloading $DESC configuration..."
do_reload
echo "."
;;
restart)
echo -n "Restarting $DESC: $NAME"
do_stop
do_start
echo "."
;;
*)
echo "Usage: $scriptNAME {start|stop|reload|restart}" >&2
exit 3
;;
esac
exit 0
设置所有人都有对这个启动脚本 nginx 文件的执行权限:chmod a+x /etc/init.d/nginx
。
把 nginx 加入系统服务中:chkconfig --add nginx
。
把服务设置为开机启动:chkconfig nginx on
。
reboot 重启系统生效,可以使用上面 systemctl 方法相同的命令。
如果服务启动的时候出现 Restarting nginx daemon: nginxnginx: [error] open() "/usr/local/nginx/logs/nginx.pid" failed (2: No such file or directory) nginx not running
的错误,通过 nginx -c
参数指定配置文件即可解决。/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf
如果服务启动中出现 nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
的错误,可以先通过 service nginx stop
停止服务,再启动就好。
配置 nginx 全局可用
全局使用 nginx 命令,每次改了 nginx.conf
配置文件的内容都需要重新到 nginx
启动目录去执行命令,或者通过 -p
参数指向特定目录,会不会感觉很麻烦?
例如:直接执行 nginx -s reload
会报错 -bash: nginx: command not found
,需要到 /usr/local/nginx/sbin
目录下面去执行,并且是执行 ./nginx -s reload
。
这里有两种方式可以解决,一种是通过脚本对 nginx 命令包装,这里介绍另外一种比较简单:通过把 nginx 配置到环境变量里,用 nginx 执行指令即可。
- 编辑 /etc/profile
vi /etc/profile
- 在最后一行添加配置,
:wq
保存export PATH=$PATH:/usr/local/nginx/sbin
- 使配置立即生效
source /etc/profile
常用命令
nginx -h # 查看命令
nginx # 启动
nginx -s reload # 向主进程发送信号,重新加载配置文件,热重启
nginx -s reopen # 重启 Nginx
nginx -s stop # 快速关闭
nginx -s quit # 等待工作进程处理完成后关闭
nginx -T # 查看当前 Nginx 最终的配置
nginx -t -c <配置路径> # 检查配置是否有问题,如果已经在配置目录,则不需要 -c
killall nginx # 强制关闭
netstat -tlnp # 查看端口号
# Linux 系统应用管理工具 systemd 关于 nginx 的常用命令
systemctl start nginx # 启动 Nginx
systemctl stop nginx # 停止 Nginx
systemctl restart nginx # 重启 Nginx
systemctl reload nginx # 重新加载 Nginx,用于修改配置后
systemctl enable nginx # 设置开机启动 Nginx
systemctl disable nginx # 关闭开机启动 Nginx
systemctl status nginx # 查看 Nginx 运行状态
常用内置变量
TCP | UDP |
---|---|
$host | 请求信息中的HOST,如果请求中没有 Host 行,则等于设置的服务器名 |
$request_method | 客户端请求类型,如GET/POST |
$remote_addr | 客户端IP地址 |
$args | 请求中的参数 |
$content_length | 请求头中的 Content-length字段 |
$http_user_agent | 客户端agent信息 |
$http_cookie | 客户端cookie信息 |
$remote_port | 客户端的端口 |
$server_protocol | 请求使用的协议,如HTTP/1.1 |
$server_addr | 服务器地址 |
$server_name | 服务器名称 |
$server_port | 服务器端口号 |
附 nginx 内置预定义变量
按字母顺序,变量名与对应定义:
- $arg_PARAMETER #GET 请求中变量名 PARAMETER 参数的值
- $args #这个变量等于 GET 请求中的参数,例如,foo=123&bar=blahblah;这个变量可以被修改
- $binary_remote_addr #二进制码形式的客户端地址
- $body_bytes_sent #传送页面的字节数
- $content_length #请求头中的 Content-length 字段
- $content_type #请求头中的 Content-Type 字段
- $cookie_COOKIE #cookie COOKIE 的值
- $document_root #当前请求在 root 指令中指定的值
- document_uri #与 uri 相同
- $host #请求中的主机头(Host)字段,如果请求中的主机头不可用或者空,则为处理请求的 server 名称(处理请求的 server 的 server_name 指令的值)。值为小写,不包含端口
- $hostname #机器名使用 gethostname 系统调用的值
- http_HEADER #HTTP 请求头中的内容,HEADER 为 HTTP 请求中的内容转为小写,-变为_(破折号变为下划线),例如:http_user_agent(Uaer-Agent 的值)
- sent_http_HEADER #HTTP 响应头中的内容,HEADER 为 HTTP 响应中的内容转为小写,-变为_(破折号变为下划线),例如:sent_http_cache_control、$sent_http_content_type…
- is_args #如果 args 设置,值为"?",否则为""
- $limit_rate #这个变量可以限制连接速率
- $nginx_version #当前运行的 nginx 版本号
- query_string #与 args 相同
- $remote_addr #客户端的 IP 地址
- $remote_port #客户端的端口
- $remote_port #已经经过 Auth Basic Module 验证的用户名
- $request_filename #当前连接请求的文件路径,由 root 或 alias 指令与 URI 请求生成
- $request_body #这个变量(0.7.58+)包含请求的主要信息。在使用 proxy_pass 或 fastcgi_pass 指令的 location 中比较有意义
- $request_body_file #客户端请求主体信息的临时文件名
- $request_completion #如果请求成功,设为"OK";如果请求未完成或者不是一系列请求中最后一部分则设为空
- $request_method #这个变量是客户端请求的动作,通常为 GET 或 POST。包括 0.8.20 及之前的版本中,这个变量总为 main request 中的动作,如果当前请求是一个子请求,并不使用这个当前请求的动作
- request_uri #这个变量等于包含一些客户端请求参数的原始 URI,它无法修改,请查看 uri 更改或重写 URI
- scheme #所用的协议,例如 http 或者是 https,例如 rewrite ^(.+)$$scheme://example.com1 redirect
- $server_addr #服务器地址,在完成一次系统调用后可以确定这个值,如果要绕开系统调用,则必须在 listen 中指定地址并且使用 bind 参数
- $server_name #服务器名称
- $server_port #请求到达服务器的端口号
- $server_protocol #请求使用的协议,通常是 HTTP/1.0、HTTP/1.1 或 HTTP/2
- $uri #请求中的当前 URI(不带请求参数,参数位于 args ) , 不 同 于 浏 览 器 传 递 的 args),不同于浏览器传递的 args),不同于浏览器传递的 request_uri 的值,它可以通过内部重定向,或者使用 index 指令进行修改。不包括协议和主机名,例如 /foo/bar.html