NGINX

举报
小源博客 发表于 2023/04/11 11:50:21 2023/04/11
【摘要】 IO模型同步/异步:关注的是消息通信机制,既调用者在等待一件事情的处理结果时,被调用者是否提供完成状态的通知同步:synchronous 事情做完了或没做完,都不会主动通知消息,需要调用着主动询问事情是否处理完成异步:asynchronous 事情做完了或没做完,都会主动通知消息,不需要调用着主动询问事情是否处理完成阻塞/非阻塞:关注调用者在等待结果返回之前所处的状态阻塞:blocking,...

IO模型

  • 同步/异步:关注的是消息通信机制,既调用者在等待一件事情的处理结果时,被调用者是否提供完成状态的通知

    • 同步:synchronous 事情做完了或没做完,都不会主动通知消息,需要调用着主动询问事情是否处理完成

    • 异步:asynchronous 事情做完了或没做完,都会主动通知消息,不需要调用着主动询问事情是否处理完成

  • 阻塞/非阻塞:关注调用者在等待结果返回之前所处的状态

    • 阻塞:blocking,IO操作需要彻底完成后才返回到用户空间,调用返回结果之前,调用者被挂起,干不了别的事情

    • 非阻塞:nonblocking,IO操作被调用后立即返回给用户一个状态值,而无需等到IO操作彻底完成,在最终的调用结果返回之前,调用者不会被挂起,可以去做别的事情

    • 内核空间 ---> 用户空间

  • nginx支持的事件驱动

    • select(apache默认的)、poll、epoll

网络I/O模型

  • 阻塞型、非阻塞型、复用型、型号驱动型、异步

  • 查看最大并发连接数

# 连接并发数和内存有关
cat /proc/sys/fs/file-max
  • 零拷贝技术

  • 尽量避免拷贝操作来缓解cpu的压力。零拷贝并没有真正做到“0”拷贝,它更多是一种思想,很多的零拷贝技术都是基于这个思想去做的优化

  • MMAP(Menory Mapping)


  • SENDFILE


  • DMA 辅助的 SENDFILE(nginx不支持,需要硬件)


nginx编译安装和全局配置

# yum安装
dnf install nginx -y
​
nginx --help
-V     # 显示编译过程
  • 指定worker_process工作个数(如果配置文件中有worker配置得先注释)

nginx -g "worker_processes 6;"
​
nginx -s start
​
# 查看进程数
pstree -p | grep nginx
  • nginx编译安装

yum install -y gcc pcre-devel zlib-devel openssl-devel make
​
./configure --prefix=/apps/nginx-1.20.2  --with-http_stub_status_module  --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_stub_status_module --with-pcre --with-stream_ssl_module --with-stream_realip_module  --with-stream --with-file-aio
​
useradd -r -s /sbin/nologin nginx
​
chown -R nginx.nginx /apps/nginx
​
# 创建 Nginx 自启动文件
# 复制同一版本的nginx的yum安装生成的service文件
vim /usr/lib/systemd/system/nginx.service
[Unit]
Description=The nginx HTTP and reverse proxy server
After=network.target remote-fs.target nss-lookup.target
​
[Service]
Type=forking
PIDFile=/apps/nginx/run/nginx.pid
ExecStart=/apps/nginx/sbin/nginx -c /apps/nginx/conf/nginx.conf
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s TERM $MAINPID
​
[Install]
WantedBy=multi-user.target
​
​
​
​
​
# 配置 Nginx 自带的nginx.pid路径
vim /apps/nginx/conf/nginx.conf
pid /apps/nginx/run/nginx.pid
​
# 创建 pid 目录
mkdir /apps/nginx/run/
  • 验证 Nginx 自启动文件

systemctl daemon-reload
systemctl enable --now nginx
  • nginx子配置文件

vim /apps/nginx/conf/nginx.conf
http {
'''
 include /etc/nginx/conf.d/*.conf;      # 配置以后可以在定义的目录下写 .conf nginx配置文件了
}


全局配置


  • Nginx中,master是由root管理,也是默认的,而worker是非root管理

  • master管理worker进程。worker只负责处理用户的请求,而master的复制端口与转发等,所以需要root

  • Main全局配置段常见的配置指令分类

  • 正常运行必备的配置

  • 优化性能相关的配置

  • 用于调式及定位问题相关的配置

  • 事件驱动相关的配置

# 全局配置说明
vim /apps/nginx/conf/nginx.conf
user nginx nginx;      # 启动Nginx工作进程的用户和组
worker_process [number | auto];       # 启动Nginx工作进程的数量,一般设为CPU核心数相同.number自己规定worker进程数,auto根据CPU数量自动创建worker数
worker_cpu_affinity 00000001 00000010 00000100 00001000   # 将Nginx工作进程绑定到指定的CPU核心,默认Nginx是不进行进程绑定的,绑定并不是意味着当前nginx进程独占一核心CPU,但是可以保证此进程不会运行在其它核心上,这就极大减少了nginx的工作进程在不同的CPU核心上的来回跳转,减少了CPU对进程的资源分配与回收以及内存管理等,因此可以有效的提升nginx服务器的性能.
​
# 规律
CPU MASK: 00000001;    0号CPU
          00000010;    1号CPU
          10000000;    7号CPU
          
# 示例
worker_cpu_affinity 0001 0010 0100 1000;     # 第0号 ~ 第3号CPU。有几颗CPU就写几个0,比如有8颗CPU,格式就是:00000000
  • 监控判断看效果

vim /apps/nginx/conf/nginx.conf
user nginx nginx;
worker_process 4;
worker_cpu_affinity 00000010 00001000 00100000 10000000;    分别绑定到 2,4,6,8号CPU上。记住,cpu是从 0 开始算的,所以 2 就是 1
​
systemctl restart nginx
​
​
watch -n.5 'ps axo pid,cmd,psr | grep nginx'
​
dnf install -y httpd-tools
​
ab -c 1000 -n 2000 http://10.0.0.18/
  • 定义工作进程优先级,-20~19。官方是 -20到20,但是测试结果不对,最高 19

vim /apps/nginx/conf/nginx.conf
worker_priority -20;       # 工作进程优先级.-20优先级最高
worker_rlimit_nofile 65536;     # 所有worker进程能打开的文件数量上限,包括:Nginx的所有连接(例如与服务器的连接等),而不仅仅是与客户端的连接,另一个考虑因素是实际的并发连接数不能超过系统级别的最大打开文件数限制,最好与 ulimit -n 的值保持一致。 并发数*进程数 等于或接近于这个数
​
​
# 配置优化如下内核限制
cat /etc/security/limits.conf
* soft    core    unlimited
* hard    core    unlimited
* soft    nproc    1000000        # 系统最大进程数
* hard    nproc    1000000
* soft    nofile    1000000       # 系统最大打开文件个数
* hard    nofile    1000000
* soft    memlock    32000        # 最大锁的数量
* hard    memlock    32000
* soft    msgqueue    8192000      # 消息队列长度
* hard    msgqueue    8192000
​
# 重启服务器查看
reboot
ulimit -a      # 查看所有
ulimit -n      # 查看最大打开文件数限制
​
# 配置完成监控优先级查看效果
watch -n.5 'ps axo pid,cmd,psr,ni | grep nginx'
​
daemon off;     # 前台运行nginx服务,用于测试、docker等环境。
master_process off|on;      # 是否开启nginx的master-worker工作模式,仅用于开发调试场景,默认on
​
events {
    worker_connections 65536;      # 设置单个工作进程的最大并发连接数
    use epoll;      # 使用epoll事件驱动,Nginx支持众多的事件驱动,比如:select、poll、epoll,只能在events模块中设置
    accept_mutex on;    # on为同一时刻一个请求轮流由work进程处理,防止同时唤醒所有的worker,避免多个睡眠进程被唤醒的设置。默认为off,请求会唤醒所有worker进程,此过程也称为"惊群",因此nginx刚安装完以后要进行适当的优化。建议设置为on
    multi_accept on;    # on时Nginx服务器的每个工作进程可以同时接受多个新的网络连接。此指令默认为off,即默认为一个工作进程,即默认认为一个工作进程只能接受一个新的网络连接,打开后几个同时接受多个,建议设置为on
}

面试题(nginx优化手段)

1.调整使用cpu个数,根据cpu个数调整worker进程
​
2.对worker进行cpu绑定
​
3.worker进程能打开的文件数量上限
​
4.调整单个工作进程的最大并发连接数
​
5.事件驱动就不用设置了,默认就是epoll
​
6.同一时刻轮流由worker进程处理,让每个cpu都醒着,避免出现“惊群”现象
​
7.设置每个工作进程同时接受多个新的网络连接,因为默认是一个

范例:实现nginx的高并发配置

ulimit -n 102400       # 临时修改进程最大打开文件数
​
while true;do ab -c 5000 -n 10000 http://10.0.0.8/;sleep 0.5;done
​
# 默认配置不支持高并发,会出现错误日志
tail /apps/nginx/logs/error.log
...... Too many open files     # 文件太多了打不开
​
# 修改配置
vim /etc/security/limits.conf
worker_rlimit_nofile 100000;
​
systemctl restart nginx



http模块

http协议相关的配置结构

vim /apps/nginx/conf/nginx.conf
http {
​
'''
​
'''    # 各server的公共配置
​
server {       # 每个server用于定义一个虚拟主机,第一个server为默认虚拟服务器
​
    '''
​
}
​
server {
​
    '''
​
    server_name # 虚拟主机名
​
    root    # 主目录
​
    alias   # 路径别名
​
    location URI {
​
        '''
​
        if condition {
​
            '''
​
        }
​
    }
​
}
​
}

http协议配置说明

vim /apps/nginx/conf/nginx.conf
http {
include       mime.types;     # 导入支持的文件类型,是相对于/apps/nginx/conf目录
default_type  application/octet-stream;   # 除mime.types中文件类型外,设置其它文件默认类型,访问其它类型时会提升下载不匹配的类型文件。
​
​
# 日志部分
#log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
#                  '$status $body_bytes_sent "$http_referer" '
#                  '"$http_user_agent" "$http_x_forwarded_for"';
​
''''
}


MIME(媒体类型)

vim /apps/nginx/conf/nginx.conf
http {
include       mime.types;
default_type  application/octet-stream;    # 除mime.types中文件类型外,指定其它文件默认MIME类型,浏览器一般提示下载
types {
text/html html;
image/gif git;
image/jpeg jpg;
}
​
# MIME参考文档
https://developer.mozilla.org/zh-CN/docs/web/HTTP/Basics_of_HTTP/MIME_Types
  • 范例

# 先取出类型配置信息
cat /apps/nginx/conf/mime.types | grep text
​
vim /apps/nginx/conf/nginx.conf
default_type  text/plain;     # 改了即可
​
systemctl restart nginx
​
# 测试
curl 10.0.0.18/info.php -I


指定响应报文server首部

# 是否在响应报文中的Content-Type显示指定的字符集,默认off不显示
charset charset | off;
  • 示例

charset utf-8;
  • 是否在响应报文的Server首部显示nginx版本

server_tokens on | off | build | string;
  • 范例:修改server字段

如果想自定义响应报文的nginx版本信息,需要修改源码文件,重新编译
如果server_tokens on,修改 src/core/nginx.h    修改第13-14行,如下示例
vim src/core/nginx.h
define NGINX_VERSION      "1.68.9"
define NGINX_VER          "xier/"    NGINX_VERSION
​
# 如果 server_tokens off 关闭了显示版本信息,那么就只会显示网站应用程序(nginx)
vim src/http/ngx_http_header_filter_module.c
第49行,如下:
static char ngx_http_server_string[] = "Server: nginx" CRLF;
把其中 nginx 改为自己想要的文字即可,如:xier


核心配置示例

基于不同的IP、不同的端口以及不用得域名实现不同的虚拟主机,依赖于核心模块 ngx_http_core_module 实现

新建一个PC web站点(电脑端)

# 定义子配置文件路径
mkdir /apps/nginx/conf/conf.d
vim /apps/nginx/conf/conf.d/nginx.conf
http {
'''''
include /apps/nginx/conf/conf.d/*.conf;    # 在配置文件的最后添加。如果在server前面写入,那么首页就是在conf.d目录下了,优先级是文件名的首字母 a,b,c,d 排序
}
  • 创建PC网站配置

cat /apps/nginx/conf/conf.d/pc.conf
server {
   listen 80;
   server_name www.xier.org;
   root /data/nginx/html/pc;
}
​
mkdir -p /data/nginx/html/pc
echo "PC web" > /data/nginx/html/pc/index.html
​
systemctl reload nginx

新建一个Mobile web站点(手机端)

  • 创建m网站配置

cat /apps/nginx/conf/conf.d/pc.conf
server {
   listen 80;
   server_name www.xier.org;
   root /data/nginx/html/mobile;
}
​
mkdir -p /data/nginx/html/mobile
echo "Mobile web" > /data/nginx/html/mobile/index.html
​
systemctl reload nginx


root与alias

  • root: 指定web的家目录。在定义location的时候,文件的绝对路径等于 root+location

  • 范例

server {
   listen 80;
   server_name www.xier.org;
   location / {
       root /data/nginx/html/pc;
   }
​
   location /about {
       root /opt/html/about;       # 必须要在html目录中创建一个about目录才可以访问,否则报错。访问的url要跟上about
   }
}
​
mkdir /opt/html/about -pv
echo "about" > /opt/html/about/index.html
​
# 访问: localhost/about
​
nginx -s reload
  • alias: 定义路径别名,会把访问的路径重新定义到其指定的路径,文档映射的另一种机制,仅能用于location上下文,使用较少

  • 范例

server {
   listen 80;
   server_name www.xier.org;
   location / {
       root /data/nginx/html/pc;
   }
​
   location /about {
       alias /opt/html/about;       # 不需要在about目录中再创建about目录了,直接定位,访问about的时候,会显示alias定义的/opt/html/about里面的内容
   }


location的详细使用

  • 在一个server中location配置可存在多个,用于实现从uri到文件系统的路径映射;nginx会根据用户请求的URL来检查定义的所有location,按一定的优化级找出一个最佳匹配,而后应用其配置

  • 在没有使用正则表达式的时候,nginx会先在server中的多个location选取匹配度最高的一个uri,uri是用户请求的字符串,即域后面的web文件路径,然后使用该location模块中的正则url和字符串,如果匹配成功就结束搜索,并使用此location处理请求

  • location官方帮助文档:https://nginx.org/en/docs/http/ngx_http_core_module.html#location

# 语法规则
location [ = | ~ | ~* | ^~ ] uri { ... }
​
=       # 用于标准url前,需要请求字串与url精准匹配,大小敏感,如果匹配成功就停止向下匹配并立即处理请求
​
^~      # 用于标准url前,表示包含正则表达式,并且匹配以指定的正则表达式开头,对url的最左边部分匹配检查,不区分字符大小写
​
~       # 用于标准url前,表示包含正则表达式,并且区分大小写
​
~*      # 用于标准url前,表示包含正则表达式,并且不区分大小写
​
不带符号    # 匹配起始于此url的所有的url
​
\       # 用于标准url前,表示包含正则表达式并且转义字符。可以将 . * ?等转义为普通符号
​
# 匹配优先级从高到底
=,^~,~/~*(谁在前面谁先),不带符号
  • 官方示例

location = / {
  [ configuration A ]
}
​
location / {
  [ configuration B ]
}
​
location /documents/ {
  [ configuration C ]
}
​
location ^~ /images/ {
  [ configuration D ]
}
​
location ~* \.(gif|jpg|jpeg)$ {
  [ configuration E ]
}

生产使用案例

# 直接匹配网站根会加速Nginx访问处理
location = /index.html {
'''''';
}
​
location /index.html {
'''''';
}
  • 静态资源方法1

location ^~ /static/ {
   '''''';
}
  • 静态资源偶尔在方法1,应用较多

location ~* \.(gif|jpg|jpeg|png|css|js|ico)$ {
   '''''';
}
  • 多应用配置

location ~* /app1 {
   '''''';
}
​
location ~* /app2 {
   '''''';
}



Nginx四层访问控制

  • 访问控制基于模块 ngx_http_access_module 实现,可以通过匹配客户端源IP地址进行限制

  • 注意:如果能在防火墙设备控制,最好就不要在nginx上配置,可以更好的节约资源

  • 官方帮助:https://nginx.org/en/docs/http/ngx_http_access_module.html

  • 范例

location = /login/ {
  root /data/nginx/html/pc;
  allow 10.0.0.0/24;      # allow 允许访问
  deny all;               # deny 拒绝访问
}
​
location = /about {
  alias /data/nginx/html/pc;
  index index.html;
  deny 192.168.1.1;
  allow 192.168.1.0/24;
  allow 10.1.1.0/16;
  allow 2001:0db8::/32;
  deny all;    # 按先小范围,在大部分排序
}


Nginx认证功能

# Centos安装包
yum install -y httpd-tools
​
# Ubuntu安装包
apt install -y apache2-utils
​
# 创建用户
# c覆盖  b非交互式创建
htpasswd -cb /apps/nginx/conf.d/.htpasswd user1 123456
​
htpasswd -b /apps/nginx/conf.d/.htpasswd user2 123456
​
vim /apps/nginx/conf/conf.d/pc.conf
location = /login/ {
  root /data/nginx/html/pc;
  index index.html;
  auth_basic "login password";      # 登录提示
  auth_basic_user_file /apps/nginx/conf/.htpasswd;
}
​
# 访问
curl http://user1:123456@www.xier.org/admin/
​
curl -u user2:123456 http://www.xier.org/admin/


自定义错误页面

  • 定义错误页,以指定的响应状态码进行响应,可用位置:htto,server,location,if in location

error_page code ... [=[response]] url;
  • 范例

server {
  listen 80;
  server_name www.xier.com;
  error_page 500 502 503 504 /error.html;
  location = /error.html {
      root /data/nginx/html;
  }
}
  • 范例:防止浏览器“截胡”

  • 使用360浏览器访问基于IP的不存在页面时会自动用广告页面代替错误页面。属于流氓行为,将自己的错误页面设置为他自己的

# 404转为302
error_page 404 =302 /index.html;    #相对于 /data/nginx/html 下的index.html,如果没有index.htmln
error_page 500 502 503 504 /50x.html;
root /data/nginx/html;
  location = /50x.html {
      root /data/nginx/html;
  }


自定义错误日志

  • 范例

server {
  listen 80;
  server_name www.xier.com;
  error_page 500 502 503 504 /error.html;
  access_log /apps/nginx/logs/xier-com_access.log;
  error_log  /apps/nginx/logs/xier-com_error.log error;       # 定义错误日志
  location = /error.html {
      root /data/nginx/html;
  }
}


检查文件是否存在

  • 范例

location / {
   root /data/nginx/html/pc;
   index index.html;
   try_files $uri $uri.html $uri/index.html /about/default.html;   # 如果都找不着,就到/about/default.html找,否则500
   # try_files $uri $uri.html = 489;   自定义的状态码,如果是 404 ,那么配置了这段就会变成 489
}


长连接配置

keepalive_timeout timeout [header_timeout];      # 设定保持连接时长,0表示禁止长连接,默认为75s,通常配置在http字段作为站点全配置
​
keepalive_requests number;   # 在一次长连接上允许请求的资源最大数量,默认为100次,建议适当调大,比如500
  • 范例

keepalive_requests 3;     # 请求达到3次断开
keepalive_timeout 65 60;    # 保持连接65秒。60是假的,作为返回值看。真正起作用的是65,65秒后断开
  • 测试

curl -I www.xier.com


作为下载服务器

autoindex on | off;    # 自动文件索引功能,默认off
​
autoindex_exact_size on | off;    # 计算文件确切大小(单位bytes),off显示大概大小(单位K、M),默认on
​
autoindex_localtime on | off;     # 显示本机时间而非GMT(格林威治)时间,默认off
​
autoindex_format html | xml | json | jsonp;   # 显示索引的页面文件风格,默认html
​
limit_rate rate;    # 限制响应客户传输速率(单位B/s)。默认0,表示无限制
  • 范例

# 注意:download不需要index.html文件
​
mkdir -p /data/nginx/download
​
vim /apps/nginx/conf.d/pc.conf
location /download {
   autoindex on;     # 自动索引功能
   autoindex_exact_size on;    # 计算文件确切大小(单位bytes),此为默认值,off只显示大概大小(单位kb,mb,gb)
   autoindex_localtime on;     # on表示显示本机时间,而非GMT时间,默认为off
   limit_rate 1024k;
   root /data/nginx/;
}
​
# 重启nginx并访问


作为上传服务器

  • 以下指令控制上传数据

client_max_body_size 1m;     # 设置允许客户端上传单个文件的最大值,默认为1m,上传文件超过此值会出413错误
​
client_body_buffer_size size;   # 用于接收每个客户端请求的body部分缓冲区大小,默认16k,超出范围暂存到磁盘上由下面client_body_temp_path指令所定义的位置
​
client_body_temp_path path [leve]1 [leve]2 [leve]3;    # 设定存储客户端请求报文的body部分的临时存储路径及子目录结构和数量,目录名为16进制
  • 配置示例

client_max_body_size 100m;     # 如果太大,上传时会出现下图413错误,注意:如果php上传,还需要修改php.ini的相关配置
​
client_body_buffer_size 1024k;
​
client_body_temp_path /apps/nginx/client_body_temp/ 1 2 2;   # 上传时,nginx会自动创建相关目录


其它配置

  • 对那种浏览器禁用长连接

keepalive_disable none | browser ...;
  • 限制客户端使用除了指定的请求方法之外的其它方法

method: GET, HEAD, POST, PUT, DELETE, MKCOL, COPY, MOVE
limit_except GET {
    allow 192.168.0.0/24;
    allow 10.0.0.1;
    deny all;
}
  • 范例

location /upload {
  root /data/nginx/html/pc;
  index index.html;
  limit_except GET {
      allow 10.0.0.7;
      deny all;
  }
}
  • 是否启用异步(需要模块 --with-file-aio )

aio on | off      # 是否启用asynchronous file I/O(AIO)功能,需要编译开启 --with-file-aio
  • 文件写入到磁盘

  • 操作完全与aio相反,aio是读取文件而direction是写文件到磁盘,启用直接I/O,默认为关闭,当文件大于等于给定大小时,例如:directio 4m,同步(直接)写磁盘,而非缓存

direction size | off;
  • 缓存设置

  • nginx可以缓存三种信息

    • 文件元数据:文件描述符、文件大小和最近一次的修改时间

    • 打开目录结构

    • 没有找到的或者没有权限访问的文件相关信息

open_file_cache off;    # 是否缓存打开过的文件信息
open_file_cache max=N [inactive=time];
​
​
open_file_cache_valid time;    # 多少时间检查一下缓存,过期清理,没过期缓存,默认值为60s
open_file_cache_errors on | off;     # 是否缓存查找时发送错误的文件一类信息,默认值为off
open_file_cache_min_uses number;    # 至少访问几次才被缓存,如果是3,那么必须使用次数超过三次才能被缓存,达不到三次就会被内存清理掉,默认值为1
  • 范例

open_file_cache max=10000 inactive=60s;      # 最大缓存10000个文件,非活动数据超时时长60s
​
open_file_cache_valid 60s;      # 每隔60s检查一下缓存数据有效性
​
open_file_cache_min_uses  5;    # 60秒内至少访问5次才被缓存,没达到则被清理
​
open_file_cache_errors on;     # 缓存错误信息



Nginx高级配置

Nginx状态页

​
​
# 状态页用于输出nginx的基本状态信息
Active connections: 291
server accepts handled requests
16630948 16630948 31070465
上面三个数字对应accepts handled requests三个值
Reading: 6 Writing: 179 Waiting: 106
​
Active connections:当前处于活动的客户端连接数
accepts:统计总值,Nginx自启动后接收客户端的请求总数
handled:统计总值,Nginx自启动后已处理完成的客户端请求总数
requests: 统计总值,Nginx自启动后客户端发来的总的请求数
reading:当前状态,正在读取客户端请求报文首部的连接的连接数,数值越大,说名排队现象严重,性能不足
Writing: 当前状态,正在向客户端发送响应报文过程中的连接数,数值越大,说明访问量很大
Waiting:当前状态,正在等待客户端发出请求的空闲连接数,开启keep-alive的情况下,这个值等于 active - (reading+Writing)
  • 文本分析网站当前访问量

curl http://www.xier.com/nginx_status 2>/dev/null | awk '/Reading/{print $2,$4,$6}'
0 1 1

Nginx第三方模块

  • 第三模块是对nginx的功能扩展,第三方模块需要在编译安装nginx的时候使用参数 --add-module=PATH指定路径添加。

  • 如开源的echo模块:https://github.com/openresty/echo-nginx-module

  • 编译模块并加入到nginx中

mkdir /usr/local/src/
​
cd /usr/local/src/
​
git clone https://github.com/openresty/echo-nginx-module.git
​
cd /apps/nginx
​
# 原来的配置信息不会消失
./configure --prefix=/apps/nginx  --module=/usr/local/src/echo-nginx-module   # 指定模块源码路径
​
make && make install
  • 配置echo使用示例

location /main {
   index index.html;
   default_type text/html;
   echo "hello world,main-->";
   echo $remote_addr;     # 显示客户端ip地址
   echo $request;         # 显示请求信息
}
​
systemctl restart nginx
​
curl %IP/main

Nginx变量使用

内置变量

# 存放了客户端的地址,注意是客户端的公网IP
$remote_addr;
​
# 此变量表示将客户端IP追加请求报文中X-Forwarded-For首部字段,多个IP之间用逗号分隔。如果没有X-Forwarded-For则用$remote_addr'
$proxy_add_x_forwarded_for
​
# 返回请求报文中的参数,如(http:///www.xier.org/main/index.do?id=2312412&partner=search),返回的是id=2312412&partner=search
$args;
​
# 返回存放网页的路径
$document_root;
​
# 返回存放网页的目录
$document_uri;
​
# 返回请求的host名称
$host;
​
# 返回客户端的端口
$remote_port;
​
# 已经经过Auth Basic Module验证的用户名
$remote_user;
​
# 做反向代理时发给后端服务器的本地资源名称
$request_body_file;
​
# 返回请求资源方法
$request_method;
​
# 当前请求的资源文件的磁盘路径
$request_filename;
​
# 返回完整的url地址
$request_uri;
​
# 返回请求的协议
$scheme;
​
# 返回客户端请求协议版本,如:HTTP/1.0,HTTP/1.1等
$server_protocol;
​
# 保存了服务器IP地址
$server_addr;
​
# 请求服务器的主机名
$server_name;
​
# 请求服务器的端口号
$server_port;
​
# name为任意请求报文首部字段,表示记录请求报文的首部字段。用 curl -I查看头部信息
$http_<name>
​
# 客户端浏览器的详细信息
$http_user_agent;
​
# 客户端cookie信息
$http_cookie;
​
# name为任意请求报文首部字部cookie的key名。curl -b 携带cookie
$cookie_<name>

自定义变量

  • 假如需要自定义变量名称和值,使用指令set $variable value;

  • 语法格式

Syntax: set $variable value;
Default: -
Context: server, location, if
  • 范例

set $name xier;
echo $name;
set $my_port $server_port;
echo $my_port;
echo "$server_name:$server_port"


Nginx自定义访问日志

Syntax: access_log path [format [buffer=size] [gzip[=level]] [flush=time] [if=condition]];
access_log off;
Default:    
access_log logs/access.log combined;
Context:    http, server, location, if in location, limit_except

自定义默认格式日志

  • 如果是要保留日志的源格式,只是添加相应的日志内容,配置如下

http {
log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                 '$status $body_bytes_sent "$http_referer" '
                 '"$http_user_agent" "$http_x_forwarded_for"' '$server_name:$server_port';
}
​
access_log logs/nginx-access.log main;

自定义json格式日志

  • Nginx的默认访问日志记录相对比较单一,默认格式也不方便做日志统计分析,生产环境中通常将nginx日志转换为json日志,配合ELK做日志收集分析

   log_format access_json '{"@timestamp":"$time_iso8601",'
       '"host":"$server_addr",'
       '"clientip":"$remote_addr",'
       '"size":$body_bytes_sent,'
       '"responsetime":$request_time,'    # 总的处理时间
       '"upstreamtime":"$upstream_response_time",'
       '"upstreamhost":"$upstream_addr",'   # 后端应用服务器处理时间
       '"http_host":"$host",'
       '"uri":"$uri",'
       '"user_port":"$remote_port",'
       '"method":"$request_method",'
       '"xff":"$http_x_forwarded_for",'
       '"referer":"$http_referer",'
       '"tcp_xff":"$proxy_protocol_addr",'
       '"http_user_agent":"$http_user_agent",'
       '"status":"$status"}';
   access_log  logs/access.log  access_json;
  • 转换python2语法到python3

pip3 install 2to3
2to3 -w log.py


Nginx压缩功能

# 启用或禁用gzip压缩,默认关闭
gzip on | off;
​
# 压缩比由高到低从1到9,默认为1
gzip_comp_level level;
​
# 禁用IE gzip功能
gzip_disable "MSIE [1-6]\.";
​
# gzip压缩的最小文件,小于设置的文件将不会压缩
gzip_http_version 1.0 | 1.1;
​
# 指定Nginx服务需要向服务器申请的缓存空间的个数和大小,平台不同,默认:32 4k或者16 6k;
gzip_buffers number size;
​
# 指明仅对哪些类型的资源执行压缩操作;默认为gzip_types text/html,不用显示指定,否则出错
gzip_types mime-type ...;
​
# 如果启用压缩,是否在响应报文首部插入"Vary: Accept-Encoding",一般建议打开
gzip_vary on | off;
  • 范例

   #gzip setting
   gzip  off;
   gzip_comp_level 3;
   gzip_disable "MSIE [1-6]\.";
   gzip_min_length 1k;
   gzip_http_version 1.1;
   gzip_buffers 64 16k;
   gzip_types text/plain application/javascript application/x-javascript text/cssapplication/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png; 
   gzip_vary on;


https功能

https配置参数

mkdir /apps/nginx/certs
​
cd /apps/nginx/certs
​
# 自签名CA证书,生成私钥(ca.key)和公钥(ca.crt)
openssl req -newkey rsa:4096 -nodes -sha256 -keyout ca.key -x509 -days 3650 -out ca.crt
# 交互输入以下内容
CN        # 国家代码,https://country-code.cl/
guizhou    # 省份
zunyi      # 城市名称
shanzhi    # 公司名称
yunwei     # 部门
xier       # 通用名称
360120854@qq.com    # 邮箱
​
# 自制key和csr文件
openssl req -newkey rsa:4096 -nodes -sha256 -keyout www.xier.net.key -out www.xier.net.csr
CN       # 国家代码
guizhou    # 省份
zunyi      # 城市名称
shanzhi    # 公司名称
yunwei     # 部门
www.xier.net       # 必须要写自己证书对应的域名
360120854@qq.com    # 邮箱
设置密码(不设置)
可选名称(不设置)
​
# 签发证书
openssl x509 -req -days 3650 -in www.xier.net.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out www.xier.net.crt
​
# 验证签发内容
openssl x509 -in www.xier.net.crt -noout -text


  • 需要证书,先写证书脚本生成(脚本方式)

cd /apps/nginx/conf.d/
​
vim certificate.sh
#!/bin/bash
CA_SUBJECT="/O=magedu/CN=ca.magedu.org"
SUBJECT="/C=CN/ST=zunyi/L=zhengan/O=wanshan/CN=www.xier.org"
SERIAL=34
EXPIRE=20211224
FILE=xier.org
​
openssl req -x509 -netkey rsa:2048 -subj $CA_SUBJECT -keyout ca.key -nodes -days 202111 -out ca.crt
​
openssl req -newkey rsa:2048 -nodes -keyout ${FILE}.key -subj $SUBJECT -out ${FILE}.csr
​
openssl x509 -req -in $FILE.csr -CA ca.crt -CAkey ca.key -set_serial $SERIAL -days $EXPIRE -out ${FILE}.crt
​
chmod 600 ${FILE}.key ca.key
​
# 执行
bash certificate.sh
​
# nginx需要一个cr证书,需要将两个合并。网站的证书在前,ca证书在后
cat xier.org.crt ca.crt > xier.crt
  • 配置参数如下

# 启用ssl功能
listen 443 ssl;
​
# 当前虚拟主机使用的公钥文件,一般是crt文件
ssl_certificate /apps/nginx/conf.d/xier.crt;
​
# 当前虚拟主机使用的私钥文件,一般是key文件
ssl_certificate_key /apps/nginx/conf.d/xier.key;
​
# 支持ssl协议版本,早期为ssl,现在是TLS,默认为后三个。一般保持默认
ssl_protocols [SSLv2] [SSLv3] [TLSv1] [TLSv1.1] [TLSv1.2];
​
# 配置ssl缓存
ssl_session_cache off | none | [builtin[:size] [shared:name:size];
    off: 关闭缓存
    none: 通知客户端支持ssl session cache,但实际不支持
    builtin[:size]: 使用OpenSSL内建缓存,每个worker一个缓存
    [shared:name:size]: 在各worker之间使用一个共享的缓存,需要定义一个缓存名称空间大小,一兆可以存储4000个会话信息,多个虚拟主机可以使用相同的缓存名称
​
# 客户端连接可以复用ssl session cache中缓存的有效时长,默认5m
ssl_session_timeout time;
  • nginx证书配置

vim /apps/nginx/conf/nginx.conf
server {
  listen 80;
  listen 443 ssl;
  server_name www.xier.net;      # 必须要和证书签发的一致(hostname)
  ssl_certificate /apps/nginx/certs/www.xier.net.crt;     # 公钥
  ssl_certificate_key /apps/nginx/crets/www.xier.net.key;   # 私钥
  ssl_session_cache shared:sslcache:20m;
  ssl_session_timeout 10m;
  root /data/nginx/html;
}


实现多域名HTTPS

  • Nginx支持基于单个IP实现多域名功能,并还支持单IP多域名的基础之上实现HTTPS,其实是基于Nginx的SNI(Server Name indication)功能实现,SNL是为了解决一个Nginx服务器内使用一个IP绑定多个域名和证书的功能,其具体功能是客户端在连接到服务器建立SSL链接之前先发送要访问站点的域名(Hostname),这样服务器再根据这个域名返回给客户端一个合适的证书

  • 制作key和csr文件

# 自制移动端私钥公钥
openssl req -newkey rsa:4096 -nodes -sha256 -keyout m.xier.net.key -out m.xier.net.csr
CN        # 国家代码,https://country-code.cl/
guizhou    # 省份
zunyi      # 城市名称
shanzhi    # 公司名称
yunwei     # 部门
m.xier.net       # 通用名称
360120854@qq.com    # 邮箱
设置密码(不设置)
可选名称(不设置)
​
# 利用生成好的ca证书签发证书
openssl x509 -req -days 3650 -in m.xier.net.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out m.xier.net.crt
  • nginx证书设置

vim /apps/nginx/conf.d/m.conf
server {
   listen 80;                   # 80和443必须是同一个页面
   server_name m.xier.net;
   location / {
      root /data/nginx/html/mobile;
      index index.html index.htm;
   } 
}
​
server {
  listen 443;
  server_name m.xier.net;     # 必须和证书设置(hostname)的一致
  ssl_certificate /apps/nginx/certs/m.xier.net.crt;     # 公钥
  ssl_certificate_key /apps/nginx/crets/m.xier.net.key;   # 私钥
  ssl_session_cache shared:sslcache:20m;
  ssl_session_timeout 10m;
  location / {
      root /data/nginx/html/mobile;
      index index.html index.htm;
  }
}


关于favicon.ico

  • favicon.ico文件是浏览器收藏网址时显示的图标,当客户端使用浏览器问页面时,浏览器会自己主动发起请求获取页面的favicon.ico文件,当时当浏览器请求的favicon.ico不存在时,服务器会级联404日志,而且浏览器也会报404错误

  • 解决办法

# 一:服务器不记录访问日志
location = /favicon.ico {
   log_not_found off;
   access_log off;
}
​
# 二:将图标保存到指定目录访问
#location ~ ^/favicon\.ico$
location = /favicon.ico {
   root /data/nginx/html/pc/images;
   expires 90d;    # 设置文件过期时间
}


升级OpenSSL版本

  • 心脏出血(英语:Heartbleed),也简称为心血漏洞,是一个出现在加密程序库OpenSSL的安全漏洞,该程序库广泛用于实现互联网的传输层安全(TLS)协议。只要使用是存在的OpenSSL实例,无论是服务器还是客户端,都可能因此受到攻击。此问题的原因是在实现TLS的心跳扩展时没有对输入进行适当验证(缺少边界检查),因此漏洞的名称来源于"心跳"。改程序错误属于缓冲区过读,即可以读取的数据比应该允许读取的还多

  • 下载地址:https://www.openssl.org/source/openssl-1.1.1l.tar.gz

准备OpenSSL源码包:
pwd
# /usr/local/src
​
tar xvf openssl-1.1.1d
​
编译安装Nginx并制定新版本OpenSSL路径
cd /usr/local/src/nginx-1.20.0/
​
./configure --prefix=/apps/nginx-1.20.2 --with-http_stub_status_module --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_stub_status_module --with-pcre --with-stream_ssl_module --with-stream_realip_module --with-stream --with-file-aio --add-module=/usr/local/src/echo-nginx-module-master --add-module=/usr/local/src/openssl-1.1.1l
​
make && make install
​
# 验证启动nginx
nginx -t
​
nginx


Nginx Rewrite相关功能


if指令与条件表达式

  • 用于条件匹配判断,并根据条件判断结果选择不同的Nginx配置,可以配置在server或location块中进行配置,Nginx的if语法仅能使用if做单词判断,不支持使用if else或者if elif这样的多重判断,用法如下

if (条件匹配) {
   action;
}
  • 使用正则表达式对变量进行匹配,匹配成功时if指令认为条件为true,否则认为false,变量与表达式之间使用以下符号链接

=     比较变量和字符串是否相等,相等true,不相等为false

!=    比较变量和字符是否不相等,相等false,不相等为true

~     表示在匹配过程中区分大小写字符,(可以通过正则表达式匹配),满足true,不满足为false

~*    表示在匹配过程中不区分大小写字符,(可以通过正则表达式匹配),满足true,不满足为false

!~    表示在匹配过程中不区分大小写字符,满足true,不满足为false

!~*   表示在匹配过程中区分大小写字符,满足true,不满足为false

-f 和 ! -f     判断请求文件是否存在和是否不存在

-d 和 ! -d     判断请求目录是否存在和是否不存在

-x 和 ! -x     判断文件是否可执行和是否不可执行

-e 和 ! -e     判断请求文件或目录是否存在和是否不存在(包括文件,目录,软链接)
  • 范例

location /main {
   index index.html;
   default_type text/html;
   if ( $scheme = http ){        # 判断请求类型
       echo "if-----> $scheme";
   }
   if ( $scheme = https ){
       echo "if----=> $scheme";
   }

   if (-f $request_filename) {		# 判断访问路径有没有文件,有则返回,无则404。一般用 -e
       echo "file is exist";
   }
   if (!-f $request_filename) {	# 判断访问路径有没有文件,没有则返回,无则返回默认页
       echo "file not is exist"; 
   }
}

set指令

  • 指定key并给其定义一个变量,变量可以调用Nginx内置变量复制给key,另外定义格式为set $key $value,及无论是key还是value都要加$符号

location /set {
    default_type text/html;
    set $name xier;
    echo $name;
    set $ws $scheme;
    echo $ws;
    set $my_port $server_port;
    echo $my_port;
}

break指令

  • 用于 中断 当前相同作用域(location)中的其它Nginx配置,与改指令处于同一作用域的Nginx配置中,位于它前面的配置生效,位于后面的指令配置就不再生效了,Nginx服务器在根据配置处理请求的过程中遇到该指令的时候,回到上一层作用域继续向下读取配置,该指令可以在server块和location块以及if块中使用,使用语法如下:

location /break {
   default_type text/html;
   set $name xier;
   echo $name;
   set $ws $scheme;
   echo $ws;
   break;
   set $my_port $server_port;
   echo $my_port;
}

return指令

  • 从nginx版本0.8.42开始支持。处于此指令后的所有配置都将不被执行,一般用于重定向(301临时重定向 302永久重定向),return可以在server、if、location块进行配置,用法如下

return code;
return code (text);
return code URL;
  • 示例

location /main {
   root /data/nginx/html/pc;
   default_type text/html;
   index index.html;
   if ( $scheme = http ){
       #return 666;
       #return 666 "not allow http";
       return 500 "service error";
       return 302 https://www.bilibili.com/
       echo "if ---> $scheme";
   }
}

rewrite_log指令

  • 设置是否开启记录 ngx_http_rewrite_module 模块日志记录到error_log日志文件当中,可以配置在http、server、location或if当中,需要日志级别为notice

error_log /var/log/nginx/error.log notice;
location /main {
   root /data/nginx/html/pc;
   default_type text/html;
   index index.html;
   set $name xier;
   echo $name;
   rewrite_log on;      # 开启日志,默认是 off
   break;
}

rewrite指令

  • 通过表达式的匹配来改变URL,可以同时存在一个或多个指令,按照顺序依次对URI进行匹配,rewrite主要是针对用户请求的URL或者是URI做具体处理,以下是URL和URI的具体介绍

  • URI(universal resource identifier): 通过资源标识符,标识一个资源的路径,可以不带协议

  • URL(uniform resource location): 统一资源定位符,是用于在Internet中描述资源的字符串,是URI的子集。格式一般为:http://www.xier.com:8080/path/file/index.html

  • 每一个URL都是URI,但是URI不都是URL

  • 例如

http://example.org:8080/path/to/resource.txt     # URI/URL

ftp://example.org/resource.txt     # URI/URL

/absolute/path/to/resource.txt     # URI
rewrite regex replacement [flag];

rewrite flag使用

  • 利用nginx的rewrite的指令,可以实现url的重新跳转,rewrite有四种不同的flag:

  • 分别是redirect(临时重定向,状态码302)、permanent(永久重定向,状态码301)、break和last

    • 其中前两种是跳转型flag

      • redirect临时重定向302

      • permanent永久重定向301

    • 后两种是代理型和跳转型,是指有客户端浏览器重新对新地址进行请求,代理型是在WEB服务器内部实现跳转

      • break:匹配location成功或不成功遇到break后直接停止,也不再进行重写检查。最后返回给用户

      • last:匹配location成功停止,不成功还会重新匹配location进行重写,都不匹配停止。(有很多location情况下不建议使用)。最后返回给用户

  • 临时重定向和永久重定向的区别

  • 临时重定向:域名的临时调整,后期可能会变,之前的域名或者URL可能还用、或者跳转的目的域名和URL还会跳转,这种情况浏览器不会缓存跳转结果

  • 永久重定向:域名永久型调整,即域名永远跳转至另外一个新的域名,之前的域名再也不使用,跳转记录也可以缓存到客户端浏览器

rewrite案例-域名永久与临时重定向

  • 要求:因业务需要,将访问源域名 www.xier.net 的请求永久重定向到 www.bilibili.com

  • 临时重定向不会缓存域名解析记录(A记录),但是永久重定向会缓存

location {
   root /data/nginx/html/pc;
   index index.html
   rewrite / http://www.bilibli.com permanent;     # 永久重定向
   #rewrite / http://www.bilibli.com redirect;     临时重定向
}

重启nginx并访问 www.xier.net 进行测试

rewrite案例--break与last

  • 测试:访问break的请求被rewrite至test1,而访问test1传递请求再次被rewrite发至test2,以此测试last和break分别有什么区别

break案例

  • break案例:当客户端访问break时,测试通过rewrite将URL重写为test1,然后再通过rewrite将test1重写为test2测试两条write规则最终哪一条生效,并测试重写后URL会不会到其它location重新匹配

location /break {
   root /data/nginx;
   index index.html;
   rewrite ^/break/(.*) /test1/$1 break;    # break匹配成功后不再向下匹配
   rewrite ^/test1/(.*) /test2/$1 break;
}

location = /test1 {
   return 999 "new test1";
}

location = /test2 {
   return 666 "new test2";
}
  • 创建资源

mkdir /data/nginx/break;

mkdir /data/nginx/test1

mkdir /data/nginx/test2

cat /data/nginx/break/index.html
break

cat /data/nginx/test1/index.html
test1

cat /data/nginx/test2/index.html
test2
  • 观察结果:到 rewrite ^/break/(.*) /test1/$1 break; 就直接停止了,不会继续往下重写

last案例

  • last: 对某个location的URL匹配成功后会停止当前location的后续rewrite规则,并结束当前location,然后将匹配生成的新URL跳转至其它location继续匹配,直到匹配完为止

location /last {
   root /data/nginx;
   index index.html;
   rewrite ^/last/(.*) /test1/$1 last;
   rewrite ^/last/(.*) /test2/$1 last;
}

location = /test1 {
   return 999 "new test1";
}

location = /test2 {
   return 666 "new test2";
}
  • 结果:会显示 location = /test1 里面的资源,主要遇到 rewrite 就会停止,那怕下面还有 rewrite,根据第一个 rewrite 重写的url进行匹配下面的 location匹配,匹配成功后结束。最多10次,超过直接500


rewrite案例-自动跳转https

  • 要求:基于通信安全考虑公司网站要求全栈https,因此要求将在不影响用户请求的情况下将http请求全部自动跳转至https,另外也可以实现部分location跳转

vim /apps/nginx/conf/nginx.conf
server {
 listen 80;
 listen 443 ssl;
 server_name www.xier.net;
 ssl_certificate /apps/nginx/certs/www.xier.net.crt;
 ssl_certificate_key /apps/nginx/crets/www.xier.net.key;
 ssl_session_cache shared:sslcache:20m;
 ssl_session_timeout 10m;
 location / {
     root /data/nginx/html;
     index index.html;
     if ($scheme = http) {    #如果不加条件。那么会一直循环重定向,当重定向达到10次,就会报错
         rewrite / https://$host permanent;
     }
 }
}


rewrite案例-判断文件是否存在

  • 要求:当访问到公司网站时输入了一个错误的URL,可以将用户重定向至官网首页

location / {
   root /data/nginx/html/pc;
   index index.html;
   if (!-f $request_filename) {
       # return 404 "xier";
       rewrite (.*) http://www.xier.net/index.html;
   }
}

# 重启nginx并测试


更换目录访问方式

  • 要求:/20211128/static ---> /static?id=20210106

rewrite ^/(\d+)/(.+)/ /$2?id=$1 last;


多级目录访问方式

if ($host ~* (.*)\.xier\.com) {
   rewrite ^/(.*)\/(\d+)\/(.*)$ /index.do?name=$1&dir=$2&file=&3 last;
}


Nginx防盗链

  • 防盗链基于客户端携带的Referer: https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Referer 实现。referer是记录打开一个页面之前记录是从哪个页面跳转过来的标记信息,如果别人只链接了自己网站图片或某个单独的资源,而不是打开了网站的整个页面,这就是盗链,referer就是之前的那个网站域名。

  • 正常的referer信息有一下几种

  • none:请求报文首部没有referer首部,比如用户直接在浏览器输入域名访问web网站,就没有referer信息

  • blocked:请求报文有referer首部,但无有效值,比如为空

  • server_names:referer首部中包含本机名及nginx,监听的server_name

  • arbitrary_string:自定义指定字符串,但可使用 * 做通配符

  • regular expression:被指定的正则表达式模式匹配到的字符串,要使用 ~ 开头,例如:~.*\xier\com

  • 防止别人盗用自己网站的视频,图片,音乐等资源。总的来说就是:找到对方网站上的资源,复制资源 url 直接挂到自己的网站上。导致自己带宽、速度都受到了打击。这种情况就需要使用 Nginx 的防盗链来防止别人 "盗链"

  • 准备新的虚拟机 web2

在web1把nginx文件全部拷贝过来
scp -r /apps/nginx/* web2:/apps

nginx -V   # 得到编译参数,进行编译安装

# web2
编译nginx

mkdir /apps/nginx/conf/http

vim /apps/nginx/nginx.conf
'''
include /apps/nginx/conf/http/*.conf;
}

# 创建web目录
mdkir -p /data/nginx/html

vim /apps/nginx/conf/http/www.ws.net.conf
http {
   log_format access_json '{"@timestamp":"$time_iso8601",'
   '"host":"$server_addr",'
   '"clientip":"$remote_addr",'
   '"size":$body_bytes_sent,'
   '"responsetime":$request_time,'    # 总的处理时间
   '"upstreamtime":"$upstream_response_time",'
   '"upstreamhost":"$upstream_addr",'   # 后端应用服务器处理时间
   '"http_host":"$host",'
   '"uri":"$uri",'
   '"user_port":"$remote_port",'
   '"method":"$request_method",'
   '"xff":"$http_x_forwarded_for",'
   '"referer":"$http_referer",'
   '"tcp_xff":"$proxy_protocol_addr",'
   '"http_user_agent":"$http_user_agent",'
   '"status":"$status"}';

   server {
       listen 80;
       server_name www.ws.net;

       location / {
           index index.html;
           root /data/nginx/html;
           access_log /apps/nginx/logs/www.ws.net.log access_json;
       }
   }
}


# 创建html盗链网站
vim /data/nginx/html/index.html
<!doctype html>
<html lang="zh-CN">
<head>
   <meta charset="utf-8">
   <meta http-equiv="X-UA-Compatible" content="IE=edge">
   <meta name="viewport" content="width=device-width, initial-scale=1">
</head>

<body>
<a href="https://www.xier.net/">测试盗链</a>
<img src="http://www.xier.net/images/1.jpg">
</body>
</html>

# 启动nginx访问查看盗链效果
vim /apps/nginx/conf/conf.d/pc.conf
location / {
   root /data/nginx/html/pc;
   index index.html;
   valid_referers none blocked server_names *.example.com example.* www.example.org/galleries/ ~\.google\.;

   if ($invalid_referer) {
       return 403;
   }
}


扩展




Nginx反向代理

  • 反向代理:也叫reverse proxy.指的是代理外网用户的请求到内部的指定web服务器,并将数据返回给用户的一种方式。

  • 常用反向代理模块

  • ngx_http_proxy_module:将客户端的请求以http协议转发至指定服务器进行处理

  • ngx_stream_proxy_module:将客户端的请求以tcp协议转发至指定服务器处理

  • ngx_http_fastcgi_module:将客户端对php的请求以fastcgi协议转发至指定服务器助理

  • ngx_http_uwsgi_module:将客户端对python的请求以uwsgi协议转发至指定服务器处理


实现http反向代理

192.168.7.102      Nginx代理服务器

192.168.7.103      后端web A,Apache部署

192.168.7.104	   后端web B,Apache部署

反向代理配置参数

  • proxy_pass:用来设置将客户端请求转发给的后端服务器的主机,可以是主机名,IP地址:端口的方式,也可以代理到预先设置的主机群组。

  • 需要模块:ngx_http_upstream_module 支持

upstream apache {
   server 192.168.7.103:80;
   server 192.168.7.104:80;
}

location /web {
  index index.html;
  proxy_pass http://192.168.7.103:80;
  # 不带斜线访问的 /web,等于访问后端服务器 http://192.168.7.103:80/web/index.html

  proxy_pass http://192.168.7.104:80/;
  # 到斜线,等于访问后端服务器 http://192.168.7.103:80/index.html
}


# 重启Nginx测试访问效果
curl -L http://www.xier.net/web/index.html
  • proxy_hide_header field:用于nginx作为反向代理的时候,在返回给客户端http响应的时候,隐藏后端服务版本响应头部信息,可以设置在http/server或location块

location /web {
  index index.html;
  proxy_pass http://192.168.7.103:80;
  proxy_hide_header ETag;    # Etag在浏览器中被隐藏了,调试查不到
}
  • proxy_pass_header field:默认nginx在响应报文中不传递后端服务器的首部字段Date、Server、X-Pad、X-Accel等参数,需要传递则使用proxy_pass_header声明将后端服务器返回给客户端

location /web {
  index index.html;
  proxy_pass http://192.168.7.103:80;
  proxy_hide_header ETag;
  proxy_pass_header Server;
}
  • proxy_pass_request_body on | off是否向后端服务器发送HTTP包体(客户端响应信息),默认是开启,可以设置在http/server或location块

location /web {
  index index.html;
  proxy_pass http://192.168.7.103:80;
  proxy_hide_header ETag;
  proxy_pass_header Server;
  proxy_pass_request_body on;
}
  • proxy_pass_request_headers on | off是否将客户端的请求头部转发给后端服务器,默认是开启,可以设置在http/server或location块

location /web {
  index index.html;
  proxy_pass http://192.168.7.103:80;
  proxy_hide_header ETag;
  proxy_pass_header Server;
  proxy_pass_request_body on;
  proxy_pass_request_headers on;
}
  • proxy_set_header修改客户端请求头部内容转发至后端服务器

location /web {
  index index.html;
  proxy_pass http://192.168.7.103:80;
  proxy_hide_header ETag;
  proxy_pass_header Server;
  proxy_pass_request_body on;
  proxy_pass_request_headers on;
  proxy_set_header X-Forwarded-For $remote_addr;
}
  • proxy_connect_timeout time配置nginx服务器与后端服务器尝试建立连接的超时时间。默认60s

location /web {
  index index.html;
  proxy_pass http://192.168.7.103:80;
  proxy_hide_header ETag;
  proxy_pass_header Server;
  proxy_pass_request_body on;
  proxy_pass_request_headers on;
  proxy_set_header X-Forwarded-For $remote_addr;
  proxy_connect_timeout 60s;
}
  • proxy_read_timeout time配置nginx服务器向后端服务器或后端服务器组发起read请求后,等待超时时间,默认60s

location /web {
  index index.html;
  proxy_pass http://192.168.7.103:80;
  proxy_hide_header ETag;
  proxy_pass_header Server;
  proxy_pass_request_body on;
  proxy_pass_request_headers on;
  proxy_set_header X-Forwarded-For $remote_addr;
  proxy_connect_timeout 60s;
  proxy_read_timeout 60s;
}
  • proxy_send_timeout time配置nginx服务器向后端服务器或后端服务器组发起write请求后,等待超时时间,默认60s

location /web {
  index index.html;
  proxy_pass http://192.168.7.103:80;
  proxy_hide_header ETag;
  proxy_pass_header Server;
  proxy_pass_request_body on;
  proxy_pass_request_headers on;
  proxy_set_header X-Forwarded-For $remote_addr;
  proxy_connect_timeout 60s;
  proxy_read_timeout 60s;
  proxy_send_timeout 60s;
}
  • proxy_http_version用于设置nginx提供服务的HTTP协议版本,默认 http 1.0

location /web {
  index index.html;
  proxy_pass http://192.168.7.103:80;
  proxy_hide_header ETag;
  proxy_pass_header Server;
  proxy_pass_request_body on;
  proxy_pass_request_headers on;
  proxy_set_header X-Forwarded-For $remote_addr;
  proxy_connect_timeout 60s;
  proxy_read_timeout 60s;
  proxy_send_timeout 60s;
  proxy_http_version 1.0;
}
  • proxy_ignore_client_abort off:当客户端网络请求中断时,nginx服务器中断其后端服务器的请求,即如果此项设置为on开启,则服务器会忽略客户端中断并一直等着代理服务器执行返回,如果设置为off,则客户端中断后Nginx也会中断客户端请求并立即记录499日志,默认为off

location /web {
  index index.html;
  proxy_pass http://192.168.7.103:80;
  proxy_hide_header ETag;
  proxy_pass_header Server;
  proxy_pass_request_body on;
  proxy_pass_request_headers on;
  proxy_set_header X-Forwarded-For $remote_addr;
  proxy_connect_timeout 60s;
  proxy_read_timeout 60s;
  proxy_send_timeout 60s;
  proxy_http_version 1.0;
  proxy_ignore_client_abort off;
}
  • proxy_headers_hash_bucket_size:当配置了 proxy_hide_header和proxy_set_header的时候,用于设置nginx保存HTTP报文头的hash表的上限

location /web {
'''
  proxy_headers_hash_bucket_size 128;
}
  • proxy_headers_hash_max_size: 设置proxy_hash_bucket_size的最大可用空间

location /web {
'''
  proxy_headers_hash_max_size 512;
}
  • proxy_names_bash_bucket_size:server_name hash表申请空间大小

location /web {
'''
 proxy_names_bash_bucket_size 512;
}
  • proxy_names_hash_max_size:设置服务器名称hash表的上限大小

location /web {
'''
  proxy_names_hash_max_size 512;
}


反向代理缓存功能

  • 缓存功能默认关闭
proxy_cache zone | off;      默认off

指明调用的缓存,或关闭缓存机制:Context:http,server,location
proxy_cache_key string;

缓存中用于 "键" 的内容,默认值:proxy_cache_key $scheme$proxy_host$request_uri;
proxy_cache_valid [code] time;

定义对特定响应码的响应内容的缓存时长,定义在http{...}中
示例:
proxy_cache_valid 200 302 10m;
proxy_cache_valid 404 1m;
  • 在http配置定义缓存信息
proxy_cache_path /var/cache/nginx/proxy_cache    定义缓存保存路径,proxy_cache会自动创建
levels=1:2:2     定义缓存目录结构层次,1:2:2可用生成 2^4x2^8x2^8=1048567个目录
keys_zone=proxycache:20m     指内存中缓存的大小,主要用于存放key和metadata(如:使用次数)
inactive=120s     缓存有效时间
max_size=1g       最大磁盘占用空间,磁盘存入文件内容的缓存空间最大值

# 调用缓存功能,需要定义在相应的配置段,如server{...};或者location等
proxy_cache proxycache;
proxy_cache_key $request_uri
proxy_cache_valid 200 302 10m;
proxy_cache_valid any 1m;
  • 对哪些客户端请求方法对应的相应进行缓存,GET和HEAD方法总是被缓存
proxy_cache_methods GET | HEAD | POST ...;
  • 示例配置缓存
vim /apps/nginx/nginx.conf
http {
   ''''
   # cache setting
   proxy_cache_path /apps/nginx/proxycache levels=2:2:2 keys_zone=xiercache:128m inactive=180s max_size=5g;
}

# 配置引用
vim /apps/nginx/conf.d/pc.conf
location /web {
   '''
   proxy_cache xiercache;     # 注意要和上面配置的一致
   proxy_cache_key $request_uri;
   proxy_cache_valid 200 302 301 1h;
   proxy_cache_valid any 3m;    # 其它
}

# 重启nginx测试速度
ab -n2000 -c200 http://www.xier.net/web/cache.log


添加头部报文信息

# 缓存过期时间
expires    24h;

vim /apps/nginx/conf.d/pc.conf
location /web {
   '''
   proxy_cache xiercache;
   proxy_cache_key $request_uri;
   proxy_cache_valid 200 302 301 1h;
   proxy_cache_valid any 3m;

   add_header X-Via $server_addr;
   add_header X-Cache $upstream_cache_status;
   add_header X-Accel $server_name;
}




Nginx http反向代理高级应用(负载均衡)

  • 在上面 nginx 可以将客户端请求转发至单台后端服务器,但是无法转发至特定的一组服务器。但是Nginx可以基于 ngx_http_upstream_module 模块提供服务器分组转发、权重分配、状态监测、调度算法等高级应用功能,官方文档:https://nginx.org/en/docs/http/ngx_http_upstream_module.html

http upstream配置参数

  • 自定义一组服务器,配置在http内

upstream name {

}
配置一个后端web服务器,配置在upstream内,至少要有一个server服务器配置
server address [parameters];

# server支持的parameters如下:
weight=number		设置权重,默认为1

max_conns=number	给当前server设置最大活动链接数,默认为0表示没有限制

fail_timeout=time	对后端服务器的单次检测超时时间,默认为10秒

max_fails=number	在fail_timeout时间对后端服务器连续监测失败多少次就标记为不可用

proxy_next_upstream=error timeout    指定在哪种检测状态下将请求转发器到其它服务器(error timeout是默认值)

backup				设置为备份服务器

down				标记为down状态

resolve				当server定义的是主机名的时候,当A记录发生变化会自动应用新IP而不用重启Nginx
hash KEY consistent		基于指定key做hash计算,使用consistent参数,将使用ketama一致性hash算法,适用于后端是cache服务器(如varnish)时使用,consistent定义使用一致性hash运算,一致性hash基于取模运算

hash $request_uri consistent;    基于用户请求的uri做hash
  • nginx的默认调度算法是轮询
  • 源地址hash调度算法,基于客户端的remote_addr(源地址)做hash计算,以实现会话保持
ip_hash;
  • 最少连接调度算法,优先将客户端请求调度到当前最少的后端服务器
least_conn


反向代理示例--多台web服务器

upstream webserver {
    # hash $request_uri consistent;
    # ip_hash;
    # least_conn;
    server 192.168.7.103:80 weight=1 fail_timeout=15s max_fails=3;    后端服务器状态监测
    server 192.168.7.104:80 weight=1 fail_timeout=15s max_fails=3;
    server 192.168.7.101:80 weight=1 fail_timeout=15s max_fails=3 backup;
    hash $request_uri consistent;     # 一般用户会话保存
}

server {
    listen 80;
    server_name www.xier.net;
    location / {
        index index.html index.php;
        root /data/nginx/html/pc;
    }
    
    location /web {
        inndex index.html;
        proxy_pass http://webserver/;
    }
}
  • 更改http的日志格式
格式参照nginx服务器配置中的 proxy_set_header X-Forwarded-For $remote_addr;

vim /etc/httpd/conf/httpd.conf
'''''
 LogFormat "\"%{X-Forwarded-For}i\" %h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined


实现Nginx tcp负载均衡

  • Nginx在1.9.0版本开始支持tcp模式的负载均衡,在1.9.13版本开始支持udp协议的负载,udp主要用于DNS的域名解析,其配置方式和指令和http代理类似,其基于 ngx_stream_proxy_module 模块实现tcp负载,另外基于模块 ngx_stream_upstream_module 实现后端服务器分组转发、权重分配、状态监测】调度算法等高级功能。

  • 编译时添加参数:--with-stream --with_stream_proxy_module --with_stream_upstream_module

  • 范例

stream {     # 定义stream
   upstream backend {    # 定义后端服务器
       hash $remote_addr consistent;    # 定义调度算法

       server backend1.example.com:12345 weight=5;     # 定义具体server
       server 127.0.0.1:12345            max_fails=3 fail_timeout=30s;
       server unix:/tmp/backend3;
   }

   upstream dns {    # 定义后端服务器
      server 192.168.0.1:53535;    # 定义具体server
      server dns.example.com:53;
   }

   server {    # 定义server
       listen 12345;    # 监听IP:PORT
       proxy_connect_timeout 1s;    # 连接超时时间
       proxy_timeout 3s;    # 连接保持会话时长
       proxy_pass backend;  # 转发到具体服务器组
   }

   server {
       listen 127.0.0.1:53 udp reuseport;
       proxy_timeout 20s;
       proxy_pass dns;
   }

   server {
       listen [::1]:12345;
       proxy_pass unix:/tmp/stream.socket;
   }
}
  • redis案例
# redis服务器
yum install redis -y

vim /etc/redis/redis.conf
''''''
bind 0.0.0.0


# mysql服务器
mysql

grant all on *.* to xier@'%' identified by '123456';

flush privileges;


# nginx服务器
mkdir /apps/nginx/conf/tcp/ -p

vim /apps/nginx/tcp/redis_mysql.conf
stream {
   upstream redis-server {
       server 192.168.7.102:6379 max_fails=3 fail_timeout=30s;
   }
   upstream mysql-server {
       server 192.168.7.103:3306 max_fails=3 fail_timeout=30s;
   }

   server {
       listen 192.168.7.101:6379;
       proxy_connect_timeout 3s;   # 与后端服务器连接超时时间
       proxy_timeout 3s;    # 连接保持会话时长
       proxy_pass redis-server;
   }
   server {
       listen 192.168.7.101:3306;
       proxy_connect_timeout 3s;
       proxy_timeout 3s;
       proxy_pass mysql-server;
   }
}

# nginx主配置文件配置识别tcp目录配置文件
由于是tcp代理,所有放在http块中会报错,单独放在外面即可
vim /apps/nginx/nginx.conf
'''
include /apps/nginx/conf/tcp/*.conf;

动静分离

  • 动静分离就是将css、js、html、图片、视频、音乐等静态资源与 app、后端代码,利用location进行隔离在不同的url实现。

  • nginx对动态的不是很完美,一般都是直接代理后端动态资源,自生不进行动态处理,只处理静态资源





FastCGI配置指令(PHP)

  • Nginx基于模块 ngx_http_fastcgi_module实现通过fastcgi协议指定的客户端请求转发至 php-fpm 处理,其配置指令如下:
  • 转发请求到后端服务器,address为后端的fastcgi server的地址,可用位置:location,if in location
fastcgi_pass address:port;
  • fastcgi默认的主页资源,示例:fastcgi_index index.php;

fastcgi_index name


lnmp案例

  • 安装配置服务

yum install -y php-fpm php-mysqlnd php-json

vim /etc/php-fpm.d/www.conf
'''
user=nginx
group=nginx
listen=127.0.0.1:9000
pm.status_path = /status    # 开启状态页
ping.path = /ping

systemctl restart php-fpm 

vim /apps/nginx/conf/php/php.conf
server {
   listen 80;
   server_name www.xier.net;
   error_log /apps/nginx/logs/www_error.log error;
   access_log /apps/nginx/logs/www_access.log nginx_format1;
   root /data/nginx/php;     # 静态资源
   index index.php;
   location ~ \.php$|statu|ping {
        root           /data/nginx/php;
        fastcgi_pass   127.0.0.1:9000;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;   # $document_root一旦用了这个变量,那么root需指定站点目录
        include        fastcgi_params;
   }
}

mkdir /data/nginx/php

vim /data/nginx/php/index.php
<?php
phpinfo();
?>

重启nginx访问




Nginx二次开发版本

Tengine介绍

继承Nginx-1.18.0的所有特性,兼容Nginx的配置;
支持HTTP的CONNECT方法,可用于正向代理场景;
支持异步OpenSSL,可使用硬件如:QAT进行HTTPS的加速与卸载;
增强相关运维、监控能力,比如异步打印日志及回滚,本地DNS缓存,内存监控等;
Stream模块支持server_name指令;
更加强大的负载均衡能力,包括一致性hash模块、会话保持模块,还可以对后端的服务器进行主动健康检查,根据服务器状态自动上线下线,以及动态解析upstream中出现的域名;
输入过滤器机制支持。通过使用这种机制Web应用防火墙的编写更为方便;
支持设置proxy、memcached、fastcgi、scgi、uwsgi在后端失败时的重试次数;
动态脚本语言Lua支持。扩展功能非常高效简单;
支持按指定关键字(域名,url等)收集Tengine运行状态;
组合多个CSS、JavaScript文件的访问请求变成一个请求;
自动去除空白字符和注释从而减小页面的体积
自动根据CPU数目设置进程个数和绑定CPU亲缘性;
监控系统的负载和资源占用从而对系统进行保护;
显示对运维人员更友好的出错信息,便于定位出错机器;;
更强大的防攻击(访问速度限制)模块;
更方便的命令行参数,如列出编译的模块列表、支持的指令等;
支持Dubbo协议;
可以根据访问文件类型设置过期时间;


动态模块

worker_processes  1;

dso {
   load ngx_http_lua_module.so;
   load ngx_http_memcached_module.so;
}

events {
   worker_connections  1024;
}


编译安装 tengine

  • 安装编译环境依赖包(与nginx类似)

yum install -y gcc pcre-devel openssl-devel lua-devel

useradd -r -s /sbin/nologin nginx

cd /usr/local/src

# 下载文件
wget http://tengine.taobao.org/download/tengine-2.3.3.tar.gz

wget https://github.com/openresty/luajit2/archive/v2.1-20200102.tar.gz

tar xf v2.1-20200102.tar.gz

export LUAJIT_LIB=/opt/modules/luajit/lib
export LUAJIT_INC=/opt/modules/luajit/include/luajit-2.0

cd /application/luajit2-2.1-20200102

make install PREFIX=/apps/luajit

cat /etc/profile.d/luajit.sh
#!/bin/bash
export LUAJIT_LIB=/apps/luajit/lib
export LUAJIT_INC=/apps/luajit/include/luajit-2.1

source /etc/profile.d/luajit.sh

tar xvf tengine-2.3.3.tar.gz

cd tengine-2.3.3


./configure --prefix=/apps/tengine --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre --with-stream --with-stream_ssl_module --with-stream_realip_module --with-http_lua_module
# 这个shared是指编译在模块目录中,不写就直接写着二进制文件中,配置文件直接用即可,也不需要导入配置

# 执行两遍
make -j4; make install

cp /apps/luajit/lib/libluajit-5.1.so.2 /usr/local/lib/

echo "/usr/local/lib" >> /etc/ld.so.conf

ldconfig 

/apps/tengine/sbin/nginx
  • 加载lua模块

dso {
  load ngx_http_fastcgi_module.so;
  load ngx_http_rewrite_module.so;
  load ngx_http_lua_module.so;
}

编译安装2.3.2

# 下载
http://tengine.taobao.org/download.html

tar xf tengine-2.3.2.tar.gz

cd tengine-2.3.2

./configure --prefix=/application/tengine --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module  --with-http_realip_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre  --with-stream --with-stream_ssl_module --with-stream_realip_module

make && make install

concat模块(目前版本已没有)

重新编译
./configure --prefix=/application/tengine --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module  --with-http_realip_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre  --with-stream --with-stream_ssl_module --with-stream_realip_module --with-http_concat_module





OpenResty

dnf -yq install gcc prce-devel openssl-devel

useradd -r -s /sbin/nologin nginx

cd /usr/local/src

wget https://openresty.org/download/openresty-1.17.8.2.tar.gz

tar xf openresty-1.17.8.2.tar.gz

cd openresty-1.17.8.2

./configure --prefix=/application/tengine --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module  --with-http_realip_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre  --with-stream --with-stream_ssl_module --with-stream_realip_module

make && make install

ln -sf /application/openresty/nginx/sbin/nginx /application/openresty/bin/openresty


系统参数优化

  • 默认的Linux内核参数考虑是通用场景,不符合用于支持高并发访问的Web服务器定义,根据业务特点来进行调整。此处优化针对最通用的、使Nginx支持更多并发请求的TCP网络参数做简单的配置


优化内核参数

  • 修改:/etc/sysctl.conf

# 表示单个进程较大可以打开的句柄数
fs.file-max = 1000000

# 参数设置为1,表示允许将TIME_WAIT状态的socket重新用于新的TCP链接,这对于服务器来说意义重大,因为总有大量TIME_WAIT状态的链接存在
net.ipv4.tcp_tw_reuse = 1

# 当 keepalive 启动时,TCP发送keepalive消息的频度;默认是2小时,将其设置为10分钟,可更快的清理无效链接
net.ipv4.tcp_keepalive_time = 600

# 当服务器主动关闭链接时,socket保持在FIN_WAIT_2状态的较大时间
net.ipv4.tcp_fin_timeout = 30

# 表示操作系统允许TIME_WAIT套接数量的较大值,如超此值,TIME_WAIT套接字将立即被清除并打印警告信息,默认为8000,过多的TIME_WAIT套接字会使Web服务器变慢
net.ipv4.tcp_max_tw_buckets = 5000

# 定义UDP和TCP链接的本地端口的取值范围
net.ipv4.ip_local_port_range = 1024 65000

# 定义了TCP接受缓存的最小值、默认值、较大值
net.ipv4.tcp_rmem = 10240 87380 12582912

# 当网卡接收数据包的速度大于内核处理速度时,会有一个队列保存这些数据包。这个参数表示改列队的较大值
net.core.netdev_max_backlog = 8096

# 表示内核嵌套字接受缓存区默认大小
net.core.rmem_default = 6291456

# 表示内核嵌套接字发送缓存区默认大小
net.core.wmem_default = 6291456

# 表示内核套接字接受缓存区较大大小
net.core.wmem_max = 12582912
注意:以上的四个参数,需要根据业务逻辑和实际的硬件成本来综合考虑

# 与性能无关。用于解决TCO的SYN攻击
net.ipv4.tcp_syncookies = 1

# 这个参数表示TCO三次握手建立阶段接受SYN请求队列的较大长度,默认1024,将其设置的大一些可使出现Nginx繁忙来不及accept新连接时,Linux不至于丢失客户端发起的链接请求
net.ipv4.tcp_max_syn_backlog = 8192

# 这个参数用于设置启动timewait快速回放.如果找不到设置为 net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1

# 选项默认值是128,这个参数用于调节系统同时发起的TCP连接数,在高并发的请求中,默认的值可能会导致链接超时或重传,因此需要结合高并发请求数来调节此值
net.core.somaxconn = 262114

# 选项用于设定系统中最多有多少个TCP套接字不被关联到任何一个用户文件句柄上。如果超过这个数字,孤立链接将立即被复位并输出信息警告。这个限制指示为了防止简单的DOS攻击,不用过分依靠这个限制,更多情况是增加这个值
net.ipv4.tcp_max_orphans = 262114


cat /etc/sysctl.conf 
fs.file-max = 1000000
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_keepalive_time = 600
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_max_tw_buckets = 5000
net.ipv4.ip_local_port_range = 1024 65000
net.ipv4.tcp_rmem = 10240 87380 12582912
net.core.netdev_max_backlog = 8096
net.core.rmem_default = 6291456
net.core.wmem_default = 6291456
net.core.wmem_max = 12582912
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_max_syn_backlog = 8192
net.ipv4.tcp_tw_reuse = 1
net.core.somaxconn = 262114
net.ipv4.tcp_max_orphans = 262114


PAM资源限制优化

在/etc/security/limits.conf  最后增加:
* soft nofile 65535
* head nofile 65535
* soft nproc 65535
* head nproc 65535





LNMP实战项目

部署数据库

1.MySQL 企业版本选择GA	---稳定发布的版本 绿色版本
Linux - Generic

2.部署MySQL
1)卸载原有的数据库(mariadb)  rpm -qa | grep mariadb
yum -y remove mariadb-libs-5.5.65-1.el7.x86_64

2)创建虚拟用户 useradd -s /sbin/nologin mysql

3)设置环境变量、
vim  /etc/profile
export PATH=/application/mysql/bin:$PATH
source  /etc/profile

4)利用UUID进行挂载
blkid    ---查看磁盘UUID
vim  /etc/fstab
UUID=bb85c355-9c32-4402-ba8c-9eee4770be25 /data xfs     defaults        0 0
mount -a

5)对mysql进行相应的用户授权
[root@dba ~]# chown -R mysql.mysql /application/mysql/*
[root@dba ~]# chown -R mysql.mysql /data/

6)初始化数据  MySQL(创建系统数据)
mkdir -p /data/mysql/data
chown -R mysql.mysql /data/*
方案一:	---使用方案二
--initialize
[root@dba ~]# mysqld --initialize --user=mysql --basedir=/application/mysql --datadir=/data/mysql/data     如果报错【指没有[Note]的一行,其余报错无视】,因为需要依赖个软件包
[root@dba ~]# yum -y install libaio-devel libncurses*	---初始化所需要的包
2020-08-26T14:31:47.643104Z 1 [Note] A temporary password is generated for root@localhost: lg.Rdkdws9Ni	---如有此条则成功
补充: ---initialize 参数:
         a 对于密码复杂度进行定制:12为  , 4种
         b 密码过期时间:默认180天
         c 给root用户设置临时密码
方案二:	推荐使用
--initialize-insecure  参数:
无限制,无临时密码
rm -rf /data/mysql/data/*		--删除原有的数据库信息进行重启创建
mysqld --initialize-insecure  --user=mysql --basedir=/application/mysql --datadir=/data/mysql/data 

7)配置文件  
	 vim  my.cnf 
	[mysqld]
	user=mysql
	basedir=/application/mysql
	datadir=/data/mysql/data
	socket=/tmp/mysql.sock
	server_id=6
	port=3306
	[mysql]
	socket=/tmp/mysql.sock

3.启动数据库
1)sys-v
[root@dba etc]# cp /application/mysql/support-files/mysql.server /etc/init.d/mysqld
[root@dba etc]# service mysqld restart

[root@dba etc]# /etc/init.d/mysqld restart

2)vim /etc/systemd/system  	--前提是需要上面的配置文件,路径配对
[Unit]
Description=MySQL Server
Documentation=man:mysqld(8)
Documentation=http://dev.mysql.com/doc/refman/en/using-systemd.html
After=network.target
After=syslog.target
[install]
WantedBy=multi-user.target
[Service]
User=mysql
Group=mysql
ExecStart=/application/mysql/bin/mysqld --defaults-file=/etc/my.cnf		---这里换成配置文件的路径
LimitNOFILE = 5000

4.如何分析处理MySQL数据库无法启动
1)数据库目录下的文件权限属性不对,"利用数据库日志进行查看 【dba.err】,找到error的行就行排错"
2) /application/mysql/bin/mysqld  --defaults-file=/etc/my.cnf    当数据库日志不能使用时,使用将日志打印到屏幕上进行排查
3)可能情况配置文件是否有错

5.设置密码
mysqladmin -uroot -p password 000000

6.管理员数据库密码忘记了?????
mysqld_safe --skip-grant-tables --skip-networking &
--skip-grant-table		跳过授权表
--skip-networking		跳过远程登陆 
1)/etc/init.d/mysqld stop  需要先停止数据库
2)进入到数据库的维护模式
mysqld_safe --skip-grant-tables --skip-networking &
3)查看密码情况
mysql> select user,host,authentication_string from mysql.user;
4)加载授权表
mysql> flush privileges;
5)重新设置密码
mysql> grant all on *.* to root@'localhost' identified by '1';
关闭数据库,正常启动验证

7.MySQL体系结构与管理
1)MySQL  C/S结构介绍
TCP: mysql  -uroot  -pwanshan  -h  192.168.20.20 -p3306
Socket:mysql  -uroot  -pwanshan  -S  /tmp/mysql.sock


编译安装PHP

  • 目前php8起不来wordpress,安装php7

yum install -y gcc openssl-devel libxml2-devel bzip2-devel libmcrypt-devel sqlite-devel oniguruma-devel

cd /usr/local/src

wget https://www.php.net/distributions/php-8.1.0.tar.xz

./configure --prefix=/apps/php81 --enable-mysqlnd --with-mysqli=mysqlnd --with-pdo-mysql=mysqlnd --with-openssl --with-zlib --with-config-file-path=/etc --with-config-file-scan-dir=/etc/php.d --enable-mbstring --enable-xml --enable-sockets --enable-fpm --enable-zts  --disable-fileinfo

# 使用8颗cpu,增加编译速度
make -j 8 && make install
  • 生成配置文件

cp /usr/local/src/php-8.1.0/php.ini-production /etc/php.ini

cd /opt/php81/etc

cp php-fpm.conf.default php-fpm.conf

cd /opt/php81/etc/php-fpm.d/

cp www.conf.default www.conf

vim www.conf
user = nginx
group = nginx

useradd -r -s /sbin/nologin nginx
  • 启动并验证php-fpm服务

/opt/php81/sbin/php-fpm -t

cp /usr/local/src/php-8.1.0/sapi/fpm/php-fpm.service /usr/lib/systemd/system/

# 修改php最大文件上传限制
vim /etc/php.ini
'''''
post_max_size = 80M
upload_max_filesize = 20M

systemctl daemon-reload

systemctl enable --now php-fpm


编译安装nginx

  • 安装完成后

  • 配置文件上传限制

vim /apps/nginx/conf/nginx.conf
'''
server {
   '''''
   client_max_body_size 10m;
}

vim /apps/nginx/html/index.php
<?php
phpinfo{};
?>


安全加固

  • 隐藏nginx版本信息

server {
''''
   server_tokens off;
}

location ~ \.php$ {
   '''''
   fastcgi_hide_header X-Powered-By;
}


PHP访问加速opcache

  • 开启opcache

vim /etc/php.ini
''''
zend_extension=opcache.so    # 需要手动写入
opcache.enable = 1




PHP扩展session模块支持redis

cd /usr/local/src

wget http://pecl.php.net/get/redis-5.3.4.tgz

tar xf redis-5.3.4.tgz

cd redis-5.3.4

yum install -y autoconf

# 生成php的编译环境
/opt/php81/bin/phpize

./configure --with-php-config=/opt/php81/bin/php-config --enable-redis

make && make install
  • 加载redis模块

vim /etc/php.ini
extension = /apps/php71/lib/php/extensions/no-debug-non-zts-20160303/redis.so   # 最后一行写入
  • 安装redis查看可用性

yum install -y redis

vim /etc/redis.conf
'''
bind 0.0.0.0
requirepass 123456

systemctl restart redis

redis_cli -a 123456
  • php配置redis

vim /etc/php.ini
[Session]
''''
session.save_handler = redis
session.save_path = "tcp://10.0.0.17:6379?auth=123456"

systemctl restart php-fpm


  • 编写php代码访问redis

vim /data/nginx/wordpress/session.php
<?php
session_start();
// redis用session_id作为key并且是以string的形式存储
$rediskey = 'PHPREDIS_SESSION:' . session_id();
​
// SESSION 赋值测试
$_SESSION['message'] = "Hello, I'm in redis";
$_SESSION['arr'] = [1,2,3,4,5,6];
​
echo $_SESSION["message"], "<br/>";
echo "Redis key = " . $rediskey . "<br/>";
​
echo "以下是从Redis获取的数据", "<br/>";
​
echo "以下是从Redis获取的数据", "<br/>";
// 取数据
$redis = new Redis();
$redis->connect('10.0.0.13', 6379);
$redis->auth('123456');
​
echo $redis->get($rediskey);
​
?>
【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。