nginx+tomcat集群配置(3)---获取真实客户端IP
前言:
在初步构建的nginx+tomcat服务集群时, 发现webserver获取到的客户端ip都是同一个, 皆为作为反向代理服务的nginx所在的机器IP. 这不太符合我们的基本需求, 为将来的数据挖掘和分析带来了麻烦.
不过不用担心, 本文将简单介绍其背后的原因和原理, 以及具体的解决方案, ^_^.
原因分析:
webserver在获取客户端ip时, 默认的方式是通过request.getRemoteAddr(), 这种方式本质是从直连的socket中获取到的.
因此客户端直连web server服务器, 则获取到的ip即为真实的client ip地址信息. 不过若通过代理, 则直连的ip会被代理服务器的ip所替代.

通过图中的对比, 我们可以清楚的观察到, 在反向代理模式下, 客户端的socket已经被nginx的socket所代替. 若还是按默认的方式来获取客户端ip, 将失去意义.
解决思路:
nginx是7层代理, 不是lvs的4层代理, 因此不可能在tcp/ip这层做手脚. 只能在http/https这个应用层协议中做文章.
事实上, 其解决方案是基于约定的方案, 需要各方的配合来完成并实现.
nginx的策略是: 往http/https请求中, 添加额外的header信息, 以此来完成真实客户端ip的信息传递.

nginx配置:
先来介绍下nginx中的一些内部变量定义.
$host
$remote_addr #来自对端socket的ip地址
$remote_port #来自对端socket的port信息
$proxy_add_x_forwarded_for #http/https请求流经的所有代理的ip
更详细的nginx内部变量, 请参阅"nginx rewrite 参数和例子".
在nginx配置中, 需要在location标签下添加如下项:
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
对于X-Real-IP, 大家肯定容易接受和理解. 但对于X-Forwarded-For, 大家肯定有些疑惑, 这到底是什么鬼, 具体有什么用呢?
• X-Forwarded-For
简称XFF头,它代表客户端,也就是HTTP的请求端真实的IP,只有在通过了HTTP 代理或者负载均衡服务器时才会添加该项。它不是RFC中定义的标准请求头信息,在squid缓存代理服务器开发文档中可以找到该项的详细介绍。
标准格式如下:X-Forwarded-For: client1, proxy1, proxy2, ...
从标准格式可以看出,X-Forwarded-For头信息可以有多个,中间用逗号分隔,第一项为真实的客户端ip,剩下的就是曾经经过的代理或负载均衡的ip地址,经过几个就会出现几个。
光从定义来看, X-Forward-For只是记录了, 来自客户端所流经的代理服务器的链路路程, 好像没啥作用. 获取真实IP, 通过获取设定的X-Real-IP即可.
一般情况下, 好像是可行的, 因为是你忽略了, 你的web架构中, nginx代理只有一层. 当web架构中, 存在多层代理服务器时, 使用X-Real-IP会丢失真实的客户端IP, 而X-Forward-For依旧为你保留了真实的客户端ip, 这也为什么后端web server从X-Forward-For中获取client ip, 而不是从X-Real-IP中获取的本质原因.

tomcat配置:
在server.xml的配置中, 对于日志的输入格式和内容默认为:
<!-- Access log processes all example.
Documentation at: /docs/config/valve.html
Note: The pattern used is equivalent to using pattern="common" -->
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="localhost_access_log" suffix=".txt"
pattern="%h %l %u %t "%r" %s %b" />
注: 格式pattern="%h %l %u %t "%r" %s %b", 默认等价于pattern="common"
输出的样例结果为:
127.0.0.1 - - [17/Feb/2016:16:30:39 +0800] "GET / HTTP/1.1" 200 52
要输出前端nginx传递过来的客户端实际ip, 则需要把格式改为如下:
pattern="%{X-Forwarded-For}i %l %u %t "%r" %s %b"
这样tomcat的就能利用到新注入的header, 并输出真实客户端ip到日志中去.
webapp的修改:
在webapp中, 获取ip可以修改如下:
HttpServletRequest request = ...;
String ip = request.getHeader("X-Forwarded-For");
来代替:
HttpServletRequest request = ...;
String ip = request.getRemoteAddr();
在结合log4j的使用中, 可以借助MDC/NDC来写入ip地址:
java代码如下:
HttpServletRequest request = ...;
String ip = request.getHeader("X-Forwarded-For");
MDC.put("ip", ip);
log4j的配置如下:
log4j.appender.console.layout.ConversionPattern=[%X{ip}] -[%c]-[%p] %m%n
注意[%X{ip}] 这个自定义项.
参考博文"log4j获取IP显示在日志中".
总结:
对于该问题, 网上有很多资料. 这边重复一下, 一方为总结, 一方也觉得有所收获. 权当学习笔记.
公众号&游戏站点:
个人微信公众号: 木目的H5游戏世界

个人游戏作品集站点(尚在建设中...): www.mmxfgame.com, 也可直接ip访问: http://120.26.221.54/.
nginx+tomcat集群配置(3)---获取真实客户端IP的更多相关文章
- nginx+tomcat集群配置(4)--rewrite规则和多应用根目录设定思路
前言: nginx中有一块很重要的概念, 就是rewrite规则. 它会对URL进行修改, 然后进行内部的重定向. rewrite授予了nginx更多的自由, 使得后级服务的接入更加地方便. 本文将简 ...
- nginx+tomcat集群配置(1)---根目录设定和多后端分发配置
前言: 对于javaer而言, nginx+tomcat集群配置, 已然成了web应用部署的主流. 大公司如此, 小公司亦然. 对于个人开发者而言, 资源有限, 往往多个web应用混部于一台服务器(云 ...
- Nginx+Tomcat集群配置
Nginx+Tomcat集群配置 一台虚拟机作为Nginx服务 两太虚拟机配置Tomcat+jdk环境 Nginx测试 启动: cd usr/local/nginx/sbin ./nginx ---& ...
- nginx+tomcat集群配置(2)---静态和动态资源的分离
前言: 在web性能优化的领域, 经常能听到一个词, 就是静态/动态资源分离. 那静态/动态资源分离究竟是什么呢? 本文不讲文件系统服务, 云存储, 也不讲基于CDN的优化. 就简单讲讲基于nginx ...
- Nginx+Memcached+Tomcat集群配置实践(Sticky Session)
准备工作 创建一个简单的web应用,名为session.其中有两个页面,分别如下所示: 页面login.jsp <%@ page language="java" conten ...
- Nginx+Memcached+Tomcat集群配置(MSM--win7 64bit)
本次主要是在win7 64 上演示操作. web应用构建 Memcached安装配置启动 Tomcat配置 所需jar包 memcached-session-manager 序列化 contextxm ...
- 【nginx+tomcat集群】Nginx1.12.2+Tomcat7集群+负载均衡+Session共享
今天想着将项目优化一下,就想的实现集群分布,在本机测试:利用nginx+tomcat实现 通过上一篇博客(http://www.cnblogs.com/qlqwjy/p/8535235.html),N ...
- 160513、nginx+tomcat集群+session共享(linux)
第一步:linux中多个tomcat安装和jdk安装(略) 第二步:nginx安装,linux中安装nginx和windows上有点不同也容易出错,需要编译,这里做介绍 一.安装依赖 gcc open ...
- Nginx+Tomcat集群+session共享
Nginx+Tomcat集群+session共享 1)安装Nginx 2)配置多个Tomcat,在server.xml中修改端口(端口不出现冲突即可) 3)在nginx.conf文件中配置负载均衡池, ...
随机推荐
- DAO
DAO Data Access Object DAO(Data Access Object)是一个数据访问接口,数据访问:顾名思义就是与数据库打交道. 夹在业务逻辑与数据库资源中间. DAO模式是标准 ...
- python_way ,day26 django_admin 自定义
1.想在admin中增加新的字段如图: 默认django只显示 def __str__(self)里面的return的值 from django.contrib import admin # Regi ...
- php的rss订阅
一般来说我们很少自己造轮子,读取rss还是用git上的开源库吧 https://github.com/dg/rss-php 这个开源库不能读取博客园的rss订阅,新浪微博的格式显示有问题. 博客园的订 ...
- HDU-4522 湫湫系列故事——过年回家 最短路
题意:很乱 分析:把数据处理下,dijkstra下就行了,floyd超时了,我还想着优化一下输入,因为使用了vector和string等等,但是计算数据规模后,处理输入的时间复杂度比floyd要低一个 ...
- GreenPlum简单性能测试与分析--续
版权声明:本文由黄辉原创文章,转载请注明出处: 文章原文链接:https://www.qcloud.com/community/article/259 来源:腾云阁 https://www.qclou ...
- Centos 关闭后台进程 .sh 等
命令后加 & 符号可以让其在后台运行 如: node app.js & 想要关闭分两步: ps aux | grep app.js 查看app.js 所运行的进程号 kill 进程号 ...
- hdu ----3695 Computer Virus on Planet Pandora (ac自动机)
Computer Virus on Planet Pandora Time Limit: 6000/2000 MS (Java/Others) Memory Limit: 256000/1280 ...
- JVM类加载机制
一.概述 JVM把描述类的数据从class文件加载到内存,并对数据进行校验.转换解析和初始化,最终形成可以被虚拟机直接使用的java类型,这就是JVM的类加载机制 二.类加载过程 加载—(验证—准备— ...
- F2工作流引擎模型
工作流引擎(Workflow Engine ) [编辑] 工作流引擎概述 工作流引擎是指workflow(工作流)作为应用系统的一部分,并为之提供对各应用系统有决定作用的根据角色.分工和条件的不同决定 ...
- Octopus系列之UploadValues异步上载
不多说了直接上代码 public void ProcessRequest(HttpContext context) { context.Response.ContentType = "tex ...