Nginx进阶知识(理论篇)

369 阅读2分钟

反向代理

代理是什么?

简单来说,我找一个中间人,代替我去做一件事情,只要他给我结果就可以。 代理一般分为两种:正向代理、反向代理

正向代理&反向代理

1234321.PNG

  • 区别
    • 从用途上来讲:
      • 正向代理-为局域网客户端向外访问Internet服务。可以使用缓冲特性减少网络使用率。
      • 反向代理-为局域网服务器向外提供Internet服务。可以使用负载平衡提高客户访问量。还可以基于高级URL策略和管理技术对服务进行高质量管控。
    • 从安全性来讲:
      • 正向代理-必须采取安全措施确保内网客户端通过它访问外部网站。隐藏客户端的身份
      • 反向代理-对外提供服务是透明的,客户端并不知道自己访问的是一个代理。隐藏服务端的身份

nginx 代理模块

  • 官方介绍
  • 官方代码示例
location / {
    : proxy_pass http://localhost:8000; # 设定请求跳转后的地址,可以使用 hostname 或 IP:Port 形式
    : proxy_set_header X-Real-IP $remote_addr; # 后端请求携带原始请求的真实 IP 地址
}

属性详解: proxy_pass 指令设置被代理服务器的地址和被映射的URI,地址可以使用主机名或IP加端口号的形式

proxy_pass关键点

proxy_pass后面的路径最后的/作用很重要!!!

  • 示例代码:
location /html/ {
     1 proxy_pass http://proxy.com; 
     2 proxy_pass http://proxy.com/;
}
  • 假设我们访问的url是 domain.com/html/test.j…
    • 对于 1 来说 proxy.com 后面没有"/",表示"/html/" 请求(包括自己)后续的路径及其参数等关键字都由 http://a.com/ 来处理,代理后的样式如下:
    http://proxy.com/html/test.js 
    
    • 对于 2 来所 proxy.com 后面有"/",表示"/html/" 请求后续的路径及其参数等关键字都由 http://a.com/ 来处理,代理后的样式如下:
    http://proxy.com/test.js 
    

nginx代理实践

  • 代理的配置文件
~# vim /etc/nginx/conf.d/proxy.conf 
server {
     listen 192.168.8.14:80;
     server_name www.sswang.com;
     location / {
     proxy_pass http://192.168.8.14:9999/hello/;
 } }
  • 后端服务配置文件
~# vim /etc/nginx/conf.d/hello.conf 
server {
     listen 192.168.8.14:9999;
     location /hello/ {
     alias /var/www/html/hello/;
     try_files $uri $uri/ =404;
 } 
}
  • 准备后端服务文件
mkdir -p /var/www/html/hello/
echo '<h1>proxy_backend</h1>' > /var/www/html/hello/index.html
  • 检查nginx配置后重载服务
/usr/sbin/nginx -t
systemctl reload nginx
netstat -tnulp | grep nginx
  • 查看效果 12341234.PNG

负载均衡

负载均衡是什么?

我们之前使用proxy_pass的方式实现了nginx代理请求到后端的效果,随着我们的网站访问量越来越多,一个后端 就不现实了,那么接下来我们应该如果在访问量日渐增大的情况下,满足线上业务的稳定呢?

  • 解决方法就是:负载均衡
    • 负载均衡简单说来人多力量大,打群架。
  • 在nginx中的负载均衡主要有两种:四层负载(IP:Port)、七层负载(http://xxx)

nginx upstream模块

  • 官方介绍
  • 官方代码示例
upstream backend {
     server backend1.example.com weight=5;
     server backend2.example.com:8080;
     server unix:/tmp/backend3;
}
server {
     location / {
     proxy_pass http://backend;
 } }
  • 属性详解:
    • upstream 主要是定义一个后端服务地址的集合列表,每个后端服务使用一个server命令表示
    • upstream {} 和 Server {} 两部分内容属于平级关系
  • 后端服务状态
    • 在upstream模块中,可以使用server命令指定后端服务器的地址,同时还可以设置后端服务器在负载均衡调度中的状态,常用的状态有以下几种:
    • down: 表示当前server主机暂时不参与负载均衡
    • backup后备主机,当所有非backup机器出现故障或者繁忙的时候,才会请求backup机器
    • max_fails允许请求的最大失败数,默认为1,配合fail_timeout一起使用
    • fail_timeout经历max_fails次失败后,暂停服务的时间,默认为10s

nginx负载均衡实践

  • 负载均衡配置文件
~# vim /etc/nginx/conf.d/upstream.conf
upstream backends {
     server 192.168.8.14:10086;
     server 192.168.8.14:10087;
     server 192.168.8.14:10088;
}
server {
     listen 80;
     server_name localhost;
     location / {
     proxy_pass http://backends;
 } }
  • 后端代理配置文件
~# vim /etc/nginx/conf.d/backend.conf
server {
     listen 192.168.8.14:10086;
     location / {
     root /var/www/html/hello/;
     try_files $uri $uri/ =404;
 } }
server {
     listen 192.168.8.14:10087;
     location / {
      root /var/www/html/nihao/;
     try_files $uri $uri/ =404;
 } }
server {
     listen 192.168.8.14:10088;
     location / {
     root /var/www/html/huanying/;
     try_files $uri $uri/ =404;
 } }
  • 准备后端服务文件
mkdir -p /var/www/html/hello/
echo '<h1>backend_hello</h1>' > /var/www/html/hello/index.html
mkdir -p /var/www/html/nihao/
echo '<h1>backend_nihao</h1>' > /var/www/html/nihao/index.html
mkdir -p /var/www/html/huanying/
echo '<h1>backend_huanying</h1>' > /var/www/html/huanying/index.html
  • 检查nginx配置后重载服务
/usr/sbin/nginx -t
systemctl reload nginx
netstat -tnulp | grep nginx

注意: 因为课堂演示配置文件过多,而且重载次数过多,所以推荐每次进行新实践的时候,pkill nginx后再来启动 ,使用新的内存环境。

  • 查看效果
~# for i in {1..100};do curl http://192.168.8.14;done
<h1>backend_hello</h1>
<h1>backend_nihao</h1>
<h1>backend_huanying</h1>
...
<h1>backend_hello</h1>
<h1>backend_nihao</h1>
<h1>backend_huanying</h1>

负载均衡调度算法

官方资料:nginx.org/en/docs/htt… Nginx提供的负载均衡策略有两种:

  • 内置策略:nginx自带的算法
    • 雨露均沾型:轮训、加权轮训、哈希
    • 定向服务型:ip_hash、least_conn、cookie、route、lean、
    • 商业类型:ntlm、least_time、queue、stick
  • 扩展策略:各种结合业务场景自定义的算法或者第三方算法
    • 自定义算法
    • 第三方算法:fair、url_hash 常用算法简介:

轮询(默认):请求按顺序逐一分配到不同的后端服务器

weight:指定轮询权重,值越大,分配到的几率就越高,适用于后端服务器性能不均衡情况

ip_hash:按访问 IP 的哈希结果分配请求,分配后访客访问固定后端服务器,有效的解决动态网页会话共享问题。

fair:基于后端服务器的响应时间来分配请求,响应时间短的优先分配

url_hash:按访问 URL 的哈希结果分配请求,使同 URL 定向到同一台后端服务器,可提高后端缓存服务器的效率。

加权轮训实践

  • 修改负载均衡配置文件
~# vim /etc/nginx/conf.d/upstream.conf
upstream backends {
     server 192.168.8.14:10086 backup;
     server 192.168.8.14:10087 weight=1;
     server 192.168.8.14:10088 weight=2;
}
...
  • 检查nginx配置后重载服务
/usr/sbin/nginx -t
systemctl reload nginx
netstat -tnulp | grep nginx
  • 查看效果
~# for i in {1..100};do curl http://192.168.8.14;done
<h1>backend_nihao</h1>
<h1>backend_huanying</h1>
<h1>backend_huanying</h1>
...
<h1>backend_nihao</h1>
<h1>backend_huanying</h1>
<h1>backend_huanying</h1>

ip_hash实践

  • 修改负载均衡配置文件
~# vim /etc/nginx/conf.d/upstream.conf
upstream backends {
     ip_hash;
     server 192.168.8.14:10086 ;
     ...
}
...
  • 检查nginx配置后重载服务
/usr/sbin/nginx -t
systemctl reload nginx
netstat -tnulp | grep nginx
  • 查看效果
~# for i in {1..100};do curl http://192.168.8.14;done
<h1>backend_huanying</h1>
...
<h1>backend_huanying</h1>

日志解析

日志功能简介

  • 日志简介
    • Nginx默认提供了两个日志文件 access.log和error.log,通过access.log可以得到用户请求的相关信息;通过error.log可以获取某个web服务故障或其性能瓶颈等信息
    • 而且nginx的日志支持定制化格式,这样我们就可以根据实际的业务情况更好的高效工作。最常见的场景就是获取客户端的IP,记录用户访问量。

官方介绍:nginx.org/en/docs/htt…

  • 基本配置
# cat /etc/nginx/nginx.conf -n
 40 access_log /var/log/nginx/access.log;
 41 error_log /var/log/nginx/error.log;
注意:
    nginx 日志属性设置的完整格式是:
        属性名称 access_log
        存储位置 /var/log/nginx/access.log
        日志格式 位置为空表示使用默认的 combined 日志格式。它是通过 log_format 设置的
  • 默认日志格式
log_format combined '$remote_addr - $remote_user [$time_local] '
     '"$request" $status $body_bytes_sent '
     '"$http_referer" "$http_user_agent"';

注意: log_format是有一批nginx内置变量组合而成的。

  • 日志样式:
# tail /var/log/nginx/access.log
192.168.8.14 - - [12/Nov/2018:08:24:18 -0800] "GET /favicon.ico HTTP/1.0" 404 580 "-" "Mozilla/5.
0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36"

nginx常用内置变量

nginx常用的内置变量主要是用来分析日志中的http记录的,我们可以根据内置的变量精确的获取相关的信息

  • 默认变量
$remote_addr 前一台主机的 ip 地址,不一定是真实的客户端 IP
$remote_user 用于记录远程客户端的用户名称(一般为“-”)
$time_local 用于记录访问时间和时区
$request 用于记录请求的 url 以及请求方法
$status 响应状态码,例如:200 成功、404 页面找不到等。
$body_bytes_sent 给客户端发送的文件主体内容字节数
$http_referer 可以记录用户是从哪个链接访问过来的
$http_user_agent 用户所使用的代理(一般为浏览器)
  • 其他常用变量
$request_uri 包含请求参数的原始 URI,不包含主机名
$uri 不带请求参数的当前 URI,不包含主机名
$http_x_forwarded_for 可以记录客户端 IP,通过代理服务器来记录客户端的 ip 地址
$http_x_real_ip 可以记录客户端 IP,通过代理服务器来记录客户端的 ip 地址
$args 这个变量等于请求行中的参数,同$query_string
$host 请求主机头字段,否则为服务器名称。
$scheme HTTP 方法(如 http,https)
$document_uri 与$uri 相同
$document_root 当前请求文件配置文件中 html 的根目录即 root 值
$request_filename 当前请求的文件路径,由 root 或 alias 指令与 URI 请求生成
  • 示例:
例:http://localhost:10086/sswang1/sswang2/test.txt
$host localhost
$server_port 10086
$request_uri /sswang1/sswang2/test.txt
$document_uri /sswang1/sswang2/test.txt
$document_root /var/www/html
$request_filename /var/www/html/sswang1/sswang2/test.txt

自定义日志实践

  • 需求:
    • 基于代理方式访问app1应用,日志存放在/var/logs/nginx/app1/access.log,要求能从日志中获取客户端的IP地址
    • 因为是获取代理前面客户端的真实IP,需要nginx开启 --with-http_realip_module 功能,使用nginx -V 来检查,ubuntu默认安装的已经开启了该功能。
  • 设置日志格式
~# vim /etc/nginx/nginx.conf
##
# Logging Settings
## 设定日志格式的方法: log_format 格式名称 "日志表现样式"
 log_format proxy_format '$remote_addr - $remote_user [$time_local] '
         '"$request" $status $body_bytes_sent "$http_referer"'
         '"$http_user_agent" "$http_x_real_ip" "$http_x_forwarded_for"';
  • 使用日志格式:
access_log 日志路径 格式名称;
  • 负载均衡配置文件
~# vim /etc/nginx/conf.d/upstream.conf
upstream backends {
     server 192.168.8.14:10086;
}
server {
 listen 80;
 server_name localhost;
 location / {
     proxy_pass http://backends;
     proxy_set_header X-Real-IP $remote_addr;
     proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
 } }
  • 后端代理配置文件
~# vim /etc/nginx/conf.d/backend.conf
server {
     listen 192.168.8.14:10086;
     root /var/www/html/app1/;
     access_log /var/log/nginx/app1/access.log proxy_format;
     real_ip_header X-Forwarded-For; 
     set_real_ip_from 192.168.0.0/16; 
     real_ip_recursive on;
     location / {
             try_files $uri $uri/ =404;
     } 
}
  • 准备后端服务文件
mkdir -p /var/www/html/app1/
echo '<h1>backend_app1</h1>' > /var/www/html/app1/index.html
mkdir /var/log/nginx/app1 -p
  • 检查nginx配置后重载服务
/usr/sbin/nginx -t
systemctl reload nginx
netstat -tnulp | grep nginx
  • 查看效果
在多台主机上执行如下命令
curl http://192.168.8.14
  • 查看日志: app1日志
192.168.8.1 - - [12/Nov/2018:18:28:46 -0800] "GET / HTTP/1.0" 200 22 "-" "Mozilla/5.0 (Windows N
T 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36" "192.1
68.8.1" "192.168.8.1"
192.168.8.14 - - [12/Nov/2018:18:29:30 -0800] "GET / HTTP/1.0" 200 22 "-" "curl/7.47.0" "192.168.
8.14" "192.168.8.14"
192.168.8.15 - - [12/Nov/2018:18:31:43 -0800] "GET / HTTP/1.0" 200 22 "-" "curl/7.29.0" "192.168.
8.15" "192.168.8.15"

注意: 因为我们的虚拟机使用的是nat网络模型,所以我们用外部的宿主机来访问的话,是通过VMnat8网卡IP来访问nginx代理的,所以记录的是192.168.8.1

  • 注意:
    • 如果生产中出现了多级代理,
      • 在第一层代理上添加 proxy_set_header X-Real-IP $remote_addr;属性
      • 在所有代理上必须添加 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;属性
      • 真实主机上使用 real_ip_header X-Forwarded-For;属性