系列文章目录
接下来介绍nginx中ip_hash的用法。
文章目录
- 系列文章目录
- 前言
- 一、ip_hash
- 二、自定义ip_hash
-
- [1.真实 IP 提取](#1.真实 IP 提取)
- [2.使用自定义 hash 策略](#2.使用自定义 hash 策略)
- 总结
前言
通常后端服务器集群无法会话共享(cookie,session,jwt)的时候,这就造成我们访问第一台服务器,获取了cookie信息,后续接口携带该cookie访问集群中其他服务器就会失败,因为这是第一台服务器分发的cookie,集群中其他服务器是无法识别的;无法改变上游系统的时候只能我们自己改变,ip哈希就是一个不错的方案,通过请求方ip计算固定路由到某台后端服务器,也就是我的cookie是从你这获取的,我后续的请求也还是固定发到你这台服务器;当然,这样就无法再负载均衡,可能会导致某台后端服务器比集群中其他服务器压力大,所以集群能做cookie共享,就尽量做cookie共享。
提示:以下是本篇文章正文内容,下面案例可供参考
一、ip_hash
bash
#user nobody;
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" "$http_cookie" "$upstream_addr"';
access_log logs/access.log main;
#新增-start
upstream sysservers {
ip_hash; #启用IP哈希负载均衡
server 127.0.0.1:2005;
server 127.0.0.2:2005;
server 127.0.0.3:2005;
}
#新增-end
server {
listen 8099;
server_name localhost;
location / {
root resource;
index index.html index.htm;
try_files $uri /index.html;
}
location /gdp {
alias resource/gdp;
proxy_set_header Host $host:$server_port;
}
location /sys {
alias /home/sys/app/system/web/sys;
try_files $uri $uri/ /index.html;
}
#修改proxy_pass
location /api/ {
proxy_pass http://sysservers/;
proxy_set_header Host $host:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
client_max_body_size 100m;
client_body_buffer_size 128k;
proxy_connect_timeout 90;
proxy_send_timeout 300;
proxy_read_timeout 300;
proxy_buffer_size 4k;
proxy_buffers 4 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
通过
ip_hash声明,这样就能根据请求ip将请求固定到某台后端服务器这里
log_format的参数值也很重要,方便我们查看日志,分析请求链路
二、自定义ip_hash
Nginx 原生 ip_hash 不支持直接使用 http_x_forwarded_for,需通过 自定义 hash 配置 实现,核心是先提取真实客户端 IP(从 http_x_forwarded_for 中),再基于该 IP 计算 hash。
有些时候我们会遇到些复杂的请求,或者经过
squid、F5的代理导致我们的ip_hash失效,这时候就需要我们自己进行处理,下面是具体步骤,按步骤操作即可
1.真实 IP 提取
先通过 map 指令从 http_x_forwarded_for 中提取第一个真实客户端 IP(因该字段格式通常为 "客户端 IP, 代理 1IP, 代理 2IP"),并赋值给自定义变量 real_client_ip。若未获取到 http_x_forwarded_for(无代理场景),则默认使用 remote_addr 兜底。
bash
# 在 http 块中配置(与 server 块同级)
map $http_x_forwarded_for $real_client_ip {
# 正则提取第一个非空IP(匹配 IPv4 格式)
~^(\d+\.\d+\.\d+\.\d+) $1;
# 若 $http_x_forwarded_for 为空,默认用 $remote_addr
default $remote_addr;
}
2.使用自定义 hash 策略
在
upstream块中,不使用原生ip_hash,而是用hash $real_client_ip; 指令,基于第一步提取的真实 IP 计算哈希。
bash
#user nobody;
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" "$http_cookie" "$upstream_addr"';
access_log logs/access.log main;
#新增-start
upstream sysservers {
hash $real_client_ip; #基于真实客户端IP计算hash(替代原生ip_hash)
server 127.0.0.1:2005;
server 127.0.0.2:2005;
server 127.0.0.3:2005;
}
#新增-end
server {
listen 8099;
server_name localhost;
location / {
root resource;
index index.html index.htm;
try_files $uri /index.html;
}
location /gdp {
alias resource/gdp;
proxy_set_header Host $host:$server_port;
}
location /sys {
alias /home/sys/app/system/web/sys;
try_files $uri $uri/ /index.html;
}
#修改proxy_pass
location /api/ {
proxy_pass http://sysservers/;
proxy_set_header Host $host:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
client_max_body_size 100m;
client_body_buffer_size 128k;
proxy_connect_timeout 90;
proxy_send_timeout 300;
proxy_read_timeout 300;
proxy_buffer_size 4k;
proxy_buffers 4 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
这样我们就能通过自定义ip_hash实现将请求固定到某台后端服务器,只要ip是稳定的,就能保证请求正常。
总结
提一嘴,现在豆包真挺好用