前言:
  在初步构建的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 &quot;%r&quot; %s %b" />

  注: 格式pattern="%h %l %u %t &quot;%r&quot; %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 &quot;%r&quot; %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的更多相关文章

  1. nginx+tomcat集群配置(4)--rewrite规则和多应用根目录设定思路

    前言: nginx中有一块很重要的概念, 就是rewrite规则. 它会对URL进行修改, 然后进行内部的重定向. rewrite授予了nginx更多的自由, 使得后级服务的接入更加地方便. 本文将简 ...

  2. nginx+tomcat集群配置(1)---根目录设定和多后端分发配置

    前言: 对于javaer而言, nginx+tomcat集群配置, 已然成了web应用部署的主流. 大公司如此, 小公司亦然. 对于个人开发者而言, 资源有限, 往往多个web应用混部于一台服务器(云 ...

  3. Nginx+Tomcat集群配置

    Nginx+Tomcat集群配置 一台虚拟机作为Nginx服务 两太虚拟机配置Tomcat+jdk环境 Nginx测试 启动: cd usr/local/nginx/sbin ./nginx ---& ...

  4. nginx+tomcat集群配置(2)---静态和动态资源的分离

    前言: 在web性能优化的领域, 经常能听到一个词, 就是静态/动态资源分离. 那静态/动态资源分离究竟是什么呢? 本文不讲文件系统服务, 云存储, 也不讲基于CDN的优化. 就简单讲讲基于nginx ...

  5. Nginx+Memcached+Tomcat集群配置实践(Sticky Session)

    准备工作 创建一个简单的web应用,名为session.其中有两个页面,分别如下所示: 页面login.jsp <%@ page language="java" conten ...

  6. Nginx+Memcached+Tomcat集群配置(MSM--win7 64bit)

    本次主要是在win7 64 上演示操作. web应用构建 Memcached安装配置启动 Tomcat配置 所需jar包 memcached-session-manager 序列化 contextxm ...

  7. 【nginx+tomcat集群】Nginx1.12.2+Tomcat7集群+负载均衡+Session共享

    今天想着将项目优化一下,就想的实现集群分布,在本机测试:利用nginx+tomcat实现 通过上一篇博客(http://www.cnblogs.com/qlqwjy/p/8535235.html),N ...

  8. 160513、nginx+tomcat集群+session共享(linux)

    第一步:linux中多个tomcat安装和jdk安装(略) 第二步:nginx安装,linux中安装nginx和windows上有点不同也容易出错,需要编译,这里做介绍 一.安装依赖 gcc open ...

  9. Nginx+Tomcat集群+session共享

    Nginx+Tomcat集群+session共享 1)安装Nginx 2)配置多个Tomcat,在server.xml中修改端口(端口不出现冲突即可) 3)在nginx.conf文件中配置负载均衡池, ...

随机推荐

  1. hihoCoder太阁最新面经算法竞赛18

    比赛链接:http://hihocoder.com/contest/hihointerview27/problems A.Big Plus 模拟水 #include <bits/stdc++.h ...

  2. [linux] shellshock

    1> Test if the system is vulnerable env X="() { :;} ; echo vulnerable" /bin/sh -c " ...

  3. Pycharm使用问题# 快捷键设置

    Pycharm内部设置也已经变得非常复杂,此处说明我改变字体大小的快捷键设置. 在Settings中找到Keymap一项,默认显示会展开Editor Actions一项: 在里面分别找到Decreas ...

  4. MFC编程入门之十五(对话框:一般属性页对话框的创建及显示)

    属性页对话框包括向导对话框和一般属性页对话框两类,上一节讲了如何创建并显示向导对话框,本节将继续介绍一般属性页对话框的创建和显示. 实际上,一般属性页对话框的创建和显示过程和向导对话框是很类似的.将上 ...

  5. git github 异常

    git :版本控制工具 github:项目托管 git clone failed:git是否安装正确 github commit failed:github 是否账号 / 密码是否正确(密码错误也可以 ...

  6. Win7精简成功后的总结

    vsax 发表于 2014-7-20 20:59:43  https://www.itsk.com/forum.php?mod=viewthread&tid=333816&highli ...

  7. 打造高大上的Canvas粒子(一)

    HTML5 Canvas <canvas>标签定义图形,比如图表和其他图像,必须用脚本(javascript)绘制图形. 举例:绘制矩形 <script> var c = do ...

  8. win10窗口设置眼睛保护色

    经常电脑前坐着,习惯了豆沙色窗口(据说保护眼睛): 目标 记事本,ide,office等窗口颜色豆沙色:如下图 步骤 打开注册表:win+r 运行"regedit": 依次打开[H ...

  9. Windows7系统下JAVA运行环境下载、安装和设置(第二次更新:2012年03月14日)

    1.下载 地址:http://www.oracle.com/technetwork/java/javase/downloads/index.html,(由于Sun于2009年被oracle收购所以网址 ...

  10. c运行库冲突问题

    按照网上的方法,各种调试不成功,后来改成用共享MFC的dll,然后回退新加的代码,再把 #include <afxwin.h> #ifndef _AFX_NO_DB_SUPPORT#inc ...