nginx代理后如何获取用户真实访问的ip,以及访问耗时接口是nginx报504问题处理


前言

1、工作中遇到记录用户访问记录的操作,随即想到记录一篇nginx代理后获取用户真实ip的文章
2、访问耗时接口时nginx报504错误,记录nginx配置访问接口超时时间的操作。


一、nginx代理后获取用户真实ip

1.1、背景:

在实际应用中,我们可能需要获取用户的ip地址,比如做异地登陆的判断,或者统计ip访问次数等,通常情况下我们使用 request.getRemoteAddr() 就可以获取到客户端ip,但是当我们使用了nginx 作为反向代理后,使用 request.getRemoteAddr() 获取到的就一直是nginx 服务器的ip的地址。

1.2、解决办法

一个请求肯定是可以分为请求头和请求体的,而我们客户端的IP地址信息一般都是存储在请求头里的。如果你的服务器有用Nginx做负载均衡的话,你需要在你的location里面配置X-Real-IP和X-Forwarded-For请求头。

location /api {
    
    
                limit_req zone=allipse burst=24000 nodelay;
                add_header 'Access-Control-Allow-Origin' '*';
                add_header 'Access-Control-Allow-Credentials' 'true';
                add_header 'Access-Control-Allow-Headers' 'x-requested-with,content-type';
                proxy_pass http://api;
                proxy_set_header   Host    $host;
                proxy_set_header   Remote_Addr    $remote_addr;  
                proxy_set_header   X-Real-IP    $remote_addr;  //一层代理时是用户真实ip,二层代理时是第一台nginxip
                proxy_set_header   X-Forwarded-For    $proxy_add_x_forwarded_for;//一层代理时没有值,多层代理里面会存储多个ip值,第一个值就是真实用户ip
       }

1)proxy_set_header X-real-ip $remote_addr;

在web服务器端获得用户的真实ip。

但是,实际上要获得用户的真实ip,不是只有这一个方法,下面我们继续看。

2)proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

我们先看看这里有个X-Forwarded-For变量,这是一个squid开发的,用于识别通过HTTP代理或负载平衡器原始IP一个连接到Web服务器的客户机地址的非rfc标准,如果有做X-Forwarded-For设置的话,每次经过proxy转发都会有记录,格式就是client1,
proxy1,
proxy2,以逗号隔开各个地址,由于他是非rfc标准,所以默认是没有的,需要强制添加,在默认情况下经过proxy转发的请求,在后端看来远程地址都是proxy端的ip
。也就是说在默认情况下我们使用request.getAttribute(“X-Forwarded-For”)获取不到用户的ip,如果我们想要通过这个变量获得用户的ip

1.3、例子

有一个web应用,在它之前通过了两个nginx转发,www.linuxidc.com 即用户访问该web通过两台nginx。

扫描二维码关注公众号,回复: 15404200 查看本文章

在第一台nginx中,使用

proxy_set_header X-Forwarded-For$proxy_add_x_forwarded_for;

现在的KaTeX parse error: Double subscript at position 12: proxy_add_x_̲forwarded_for变量…remote_addr,而$remote_addr的值是用户的ip,于是赋值以后,X-Forwarded-For变量的值就是用户的真实的ip地址了。

到了第二台nginx,使用

proxy_set_header X-Forwarded-For$proxy_add_x_forwarded_for;

现在的KaTeX parse error: Double subscript at position 12: proxy_add_x_̲forwarded_for变量…remote_addr部分的值是上一台nginx的ip地址,于是通过这个赋值以后现在的X-Forwarded-For的值就变成了“用户的真实ip,第一台nginx的ip”,这样就清楚了吧。

最后我们看到还有一个KaTeX parse error: Double subscript at position 7: http_x_̲forwarded_for变量…http_x_forwarded_for时会发现,web服务器端使用request.getAttribute(“X-Forwarded-For”)获得的值是null。如果想要通过request.getAttribute(“X-Forwarded-For”)获得用户ip,就必须先使用proxy_set_header X-Forwarded-For$proxy_add_x_forwarded_for;这样就可以获得用户真实ip。

1.4、总结

存:配置在nginx的location块中配置以下请求头
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

取:在后端通过request.getHeader("X-Real-IP ‘’),request.getHeader("X-Forwarded-For ‘’)

结论:一层代理时是用户真实ip用X-Real-IP配置取就可以,二层代理时是第一台nginxip,一层代理时没有值,多层代理里面会存储多个ip值,第一个值就是真实用户ip,这时就得用 X-Forwarded-For

二、访问耗时接口nginx报错504

2.1、问题原因

nginx响应超时,页面出现504 gateway time-out

这种情况多发生在用 nginx 做反向代理的时候,例如用 nginx 做反向代理转发某一个 swagger 接口,当访问接口时报错,状态码一般为 504 ,也就是代理超时的问题,一般是访问一个响应慢的接口超出我们nginx接口访问的默认超时时间了。

2.2、解决办法

Proxy 方式
一般我们用的是 nginx 的 proxy 机制做反向代理,此时我们需要修改 nginx 配置文件 nginx.conf ,在 http 或者 server 段添加如下内容:

large_client_header_buffers 4 16k;
client_max_body_size 30m;
client_body_buffer_size 128k;

proxy_connect_timeout 90; #后端服务器连接的超时时间,发起握手等候响应超时时间
proxy_send_timeout 90;  #后端服务器数据回传时间,就是在规定时间内后端服务器必须传完所有的数据
proxy_read_timeout 90;  #连接成功后,等候后端服务器响应时间,其实已经进入后端的排队之中等候处理(也可以说是后端服务器处理请求的时间,页面等待服务器响应时间)
proxy_buffers 4 32k;  #4是数量 32k是大小 该指令设置缓存区的大小和数量,从被代理的后端服务器取得的第一部分响应内容,会放置到这里,默认情况下,一个缓存区的大小等于内存页面大小,可能是4k也可能是8k取决于平台
proxy_busy_buffers_size 64k; #nginx在收到服务器数据后,会分配一部分缓冲区来用于向客户端发送数据,这个缓存区大小由proxy_busy_buffers_size决定的。大小通常是proxy_buffers单位大小的两倍,官网默认是8k/16k

proxy_temp_file_write_size 64k;

然后重启 nginx ,一般超时问题就会解决了。

Fastcgi 方式
大多数情况下我们用的是 proxy 方式,但是有时候我们还会遇到 fastcgi 的方式,例如用 nginx 处理 php 页面的场景。其实处理方式类似,同样是修改 nginx 配置文件 nginx.conf ,在 http 或者 server 段添加如下内容:

large_client_header_buffers 4 16k;
client_max_body_size 30m;
client_body_buffer_size 128k;
fastcgi_connect_timeout 600 :指定连接到后端FastCGI的超时时间。
fastcgi_send_timeout 600 :向FastCGI传送请求的超时时间。
fastcgi_read_timeout 600 :指定接收FastCGI应答的超时时间。
fastcgi_buffer_size 64k :指定读取FastCGI应答第一部分需要用多大的缓冲区,默认的缓冲区大小为。fastcgi_buffers指令中的每块大小,可以将这个值设置更小。
fastcgi_buffers 4 64k :指定本地需要用多少和多大的缓冲区来缓冲FastCGI的应答请求,如果一个php脚本所产生的页面大小为256KB,那么会分配4个64KB的缓冲区来缓存,如果页面大小大于256KB,那么大于256KB的部分会缓存到fastcgi_temp_path指定的路径中,但是这并不是好方法,因为内存中的数据处理速度要快于磁盘。一般这个值应该为站点中php脚本所产生的页面大小的中间值,如果站点大部分脚本所产生的页面大小为256KB,那么可以把这个值设置为“8 32K”、“4 64k”等。
fastcgi_busy_buffers_size 128k :建议设置为fastcgi_buffers的两倍,繁忙时候的buffer。
fastcgi_temp_file_write_size 128k :在写入fastcgi_temp_path时将用多大的数据块,默认值是fastcgi_buffers的两倍,该数值设置小时若负载上来时可能报502BadGateway。

然后重启 nginx ,一般超时问题就会解决了。

例子:
在这里插入图片描述

2.3、结论

主要在http块或者具体的代理server块中添加如下配置增加接口响应超时时间

proxy_connect_timeout 90; #后端服务器连接的超时时间,发起握手等候响应超时时间
proxy_send_timeout 90; #后端服务器数据回传时间,就是在规定时间内后端服务器必须传完所有的数据
proxy_read_timeout 90;

猜你喜欢

转载自blog.csdn.net/wei1359765074410/article/details/127683608