`

nginx+tomcat - nginx和Tomcat集成后发生的重定向问题分析和解决

 
阅读更多

Tomcat前端配置一个HTTP服务器应该是大部分应用的标配了,基本思路就是所有动态请求都反向代理给后端的Tomcat,HTTP服务器来处理静态请求,包括图片、js、css、html以及xml等。这样可以让你的应用的负载能力提高很多,前端这个HTTP服务器主流用的最多的当属Apache HTTP Server和nginx。今天这篇文章主要讲解的是这种组合的方式的前提下,后端的Tomcat中的app在301跳转的时候遇到的一个问题。

问题

先把问题说清楚,前端nginx占用81端口,因为80干了别的,暂时懒得停80的应用,暂时修改为81端口而已。然后Tomcat占用8080端口,具体配置如下(只是截取了server中的一段):

location /app1/{
    index index.jsp index.html index.html index.shtml;
    proxy_pass http://localhost:8080/app1/;

    proxy_set_header   Host             $host;
     proxy_set_header   X-Real-IP        $remote_addr;
    proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;}

location ~*^.+\.(png|jpg|jpeg|gif|ico|css|js|xml)$ {
    root /home/gap/app/apache-tomcat-5.5.14/webapps;}

上面的代码只是简单举例,其中处理静态内容的部分也可以用目录alias或者root的方式去处理,效果应该一样的,但是具体区别我也没深入了解,不过这不是今天的重点。在这个配置下出现的问题就是当访问http://host:81/app1/Login.do的时候,登录成功需要301跳转到用户中心页面,然后跳转的地址本应该是http://host:81/app1/userindex.do,但是结果不太尽如人意,浏览器实际出现的地址http://host/app1/userindex.do。这里面的问题就是81端口没了,跑80端口去了,自然就404了。扯了一大段,这就是今天想说的问题。

问题出现了,自然得分析原因,由于我们这个项目中需要支持ssl,使用了Struts1.2的Framework,于是采用了SecurePlugIn(想了解的可以参照SSLExt Command 2.3节)的插件来处理。那么我首先怀疑是不是这个东西在作怪,看了下配置文件这个插件的enable都直接为false。看来不是这个插件作怪了,那么在不是应用本身逻辑在作怪的话那么可能是服务器配置有问题了,这个时候就应该直接从http请求开始分析了。

首先我打开chrome,然后来分析这次request发生了什么(打开开发者工具中的Network面板),能发现的基本就是请求Login.do是没问题的,但是Login.do之后发生的301重定向是错误的,一个重要的线索就是Login.do的请求中response中的Location的值是http://host/usercenter.do,这里丢掉了端口号。这个地方的具体原因后边会提到,先说下解决思路。

解决思路可以有两个,第一个就是nginx是可以利用proxy_redirect来修改response的Location和Refresh的值,Location自然可以被重新修改为81端口的地址,第二个就是找到是谁把Location搞错了,修改这个地方别搞错Location就行了。

解决思路1:利用nginx的proxy_redirect

这个思路其实有点偏重解决问题型,就是我看到这里错了,原因不纠结,我让你好使就可以了。可能好多人都是这个思路,毕竟解决问题是首要目的。

很多人在配置nginx的时候,习惯参考官方wiki的Full Example (taken from Nginx site),来做一些配置,参考这个肯定比参考baidu搜索出来的文档要靠谱很多,建议不了解每个属性的可以来参照下这个官方示例。这个配置里面proxy_redirect的属性为off,很多人应该没有问过为什么就直接根据人家来做了,之所以这样下结论是因为我看到太多国内人的集成例子中都是这样设置的了。我这里也是这样设置的,以前也倒是没想起来问下为啥,的确不太符合我的风格。反正服务器是这样配置的,现在是出来问题了,我们先来看下这个属性能做什么。

首先看官方文档Reference:proxy_redirect的说明:

Sets a text that should be changed in the header fields “Location” and “Refresh” of a response from the proxied server. Suppose a proxied server returned the header field “Location: http://localhost:8000/two/some/uri/”.

基本意思就是修改代理服务器(也就是此时的nginx)的response的头信息里面的LocationRefresh的值,按照这个解释的话我们的问题肯定就迎刃而解了,因为现在遇到的问题就是这个能够修改的两个中的一个Location出了问题,那么下面的代码就可以解决问题

proxy_redirect     http://host http://host:81;

这样重启sudo nginx -s reload然后再访问应该就ok了。其实你google搜索nginx proxy_redirect 重定向有好多这样的例子和这个解决方式是一样的,就不细说了,如果有人想了解的可以自己参照nginx官方文档和结合例子来操作下试试就可以理解了。

解决思路2:找到问题原因,修改出错的地方解决

根据上个思路解决了问题以后,一点都没如释重负的感觉,反而各个地方都觉得很空的感觉,因为有好几个疑问没解决,其中包括为啥是80而不是81或者8080没道理?这个Location是不是应该nginx来重写,修改掉那个跳转错的地方是不是比这个思路会更好?

那就先来分析下问题的原因:既然response的Locaiton不对,那么首先想到的就是这个Location是谁构造出来的,了解HTTP协议的人应该都知道,request中的header都是client(浏览器等)构造好发送给服务器的,服务器收到请求以后构造response信息返回给client。那么这样Location这个值肯定就是nginx或者Tomcat给搞出的问题了,这个地方nginx只是一个proxy server,那么response肯定是Tomcat发给nginx的,也就是说我们应该从Tomcat下手来分析这个问题。

首先我就看了下Tomcat的官方文档 Proxy Support,这里面对这个介绍如下:

The proxyName and proxyPort attributes can be used when Tomcat is run behind a proxy server. These attributes modify the values returned to web applications that call the request.getServerName() and request.getServerPort() methods, which are often used to construct absolute URLs for redirects. Without configuring these attributes, the values returned would reflect the server name and port on which the connection from the proxy server was received, rather than the server name and port to whom the client directed the original request.

意思就是proxyPort的属性就是用来我这种nginx做前端代理服务器Tomcat在后端处理动态请求的情况的。修改属性的值可以作用于应用的两个方法,主要用于绝对路径和重定向之用。如果不配置的话,可能会不对头。那么既然是这里不对头,我就先把server.xml中我这个http的connector的配置加入了proxyPort="81",重启Tomcat,然后把nginx上步骤的修改注释掉,重启测试。结果基本如所料,完全正常跳转了。

事情到了这个时候,其实问题基本明了了,不过我还是对这个Tomcat为啥默认解析了80端口很是疑惑。我下载了Tomcat的source来看下问题究竟,看了以后用通俗的语言来表述的话就是这样:如果默认不配置proxyPort默认为0,然后在构造response的时候判断如果proxyPort为0那么就不添加端口,不添加端口当然就默认走了80端口,源代码如下:

// FIXME: the code below doesnt belongs to here, // this is only have sense // in Http11, not in ajp13..// At this point the Host header has been processed.// Override if the proxyPort/proxyHost are set String proxyName = connector.getProxyName();int proxyPort = connector.getProxyPort();if(proxyPort !=0){
    req.setServerPort(proxyPort);}if(proxyName !=null){
    req.serverName().setString(proxyName);}

到了这里就真相大白了,心里也没结了,一块石头终于落地了。

总结

也就是说Tomcat在设计的时候是对这种代理服务器和Tomcat集成的情况做了考虑,80端口之所以没问题是因为port为空,浏览器会默认走80端口,如果nginx这代理服务器不是80这个端口应该需要配置proxyPort的属性的,这样就不会遇到这个问题。

那么基于这个来总结的话,两种解决方式都可以,不过修改Tomcat配置文件的方式是我最推荐的,因为这个思路看起来是又合理、又易于理解。我的感觉就是谁的事情谁来解决比较好,nginx作为proxy server 你就只需要做你的静态文件的解析,和把动态请求方向代理的服务器就可以了,既然Tomcat把这个信息构造错了,人家也有提供了解决方案,就根据你的情况合理配置就可以了。

 

原文来自:http://www.ituring.com.cn/article/48042

分享到:
评论

相关推荐

    nginx+tomcat+redis完成session共享

    通过引入session共享,即使用户请求被重定向到不同的Tomcat实例,他们也能保持会话状态。 3. **Redis**:Redis是一个内存高速缓存数据库,常用于存储临时数据,如session。在此场景下,当用户在某台Tomcat服务器上...

    haproxy+nginx+tomcat 练习1

    总结,这个实验涵盖了Haproxy、Nginx和Tomcat的集成,创建了一个高可用性的Web服务环境。通过负载均衡和反向代理,我们可以实现服务的扩展性和高容错性,同时利用日志管理工具进行监控和故障排查,提升系统的运维...

    【LINUX】Nginx + Tomcat 动静分离实现负载均衡

    本文将详细介绍如何使用 Nginx 和 Tomcat 实现动静分离负载均衡。动静分离是指将静态资源(如图片、CSS、JavaScript 文件等)和动态资源(如 JSP、Servlet 等)分离,使用不同的服务器或服务器组来处理不同的资源...

    linux下Nginx+tomcat安装与配置

    ### Linux 下 Nginx + Tomcat 的安装与配置详解 #### 一、环境准备与基础知识 在开始安装之前,我们先来了解一下相关的基础知识。 - **Linux 系统**:本教程适用于大多数 Linux 发行版,如 CentOS、Ubuntu、...

    linux下Nginx+tomcat整合的安装与配置

    为了配置Nginx与Tomcat的整合,我们需要创建一个名为`proxy.conf`的配置文件,设置代理参数,如禁用代理重定向、设置请求头信息以及调整代理超时和缓冲大小。这些设置有助于优化Nginx处理请求的方式,并确保与Tomcat...

    负载均衡和session 共享(Nginx + Memcached + Tomcat)

    这样,即使某台Tomcat服务器出现问题,Nginx也能将请求智能地转发到其他正常运行的服务器,保证服务的连续性。 接下来,我们讨论session共享的问题。在Web应用中,session用于存储用户状态信息,比如登录状态、...

    Nginx+Tomcat+Redis负载均衡、数据分离、session共享

    - 当某个Tomcat实例出现问题时,Nginx会自动将其从负载均衡池中移除,待其恢复后再重新加入。 - 可以通过Nginx的`keepalive`指令设置TCP连接复用,减少新连接的建立时间,提高响应速度。 6. **安全考虑**: - ...

    Web服务器三剑客运维配置实战 Nginx+JVM+Tomcat+HTTP协议 视频教程+笔记+课件+资料

    - **Nginx简介**:Nginx是一款轻量级的Web服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器。 - **选择Nginx的原因**: - 高性能:处理并发连接能力强。 - 资源消耗低:相较于Apache等其他服务器,Nginx在...

    Nginx与tomcat 负载均衡

    Nginx与Tomcat的负载均衡是指通过Nginx服务器来实现Tomcat集群的负载均衡,以提高系统的高性能和可扩展性。下面是实现负载均衡的详细步骤和知识点: 一、环境准备 * Nginx 1.8.0 * Apache Tomcat 6.0.33 二、目标...

    Nginx+Apache负载均衡

    - **高性能负载均衡**:Nginx+Apache 组合提供了一个高性能、低成本的负载均衡解决方案,能够显著提高网站性能和服务可用性。 - **易于配置与管理**:相比昂贵的商用硬件负载均衡器,Nginx 的配置更加简单直观。 - *...

    nginx+tomcat单个域名及多个域名配置教程

    【知识点详解】 1. **Nginx与Tomcat的组合** Nginx是一个高性能的HTTP和反向代理服务器,通常用于处理静态内容和作为应用服务器(如Tomcat)的前端,提供负载均衡和...在实践中,不断学习和解决问题是成长的关键。

    Nginx + Tomcat实现请求动态数据和请求静态资源的分离详解

    主要给大家介绍了关于Nginx + Tomcat实现请求动态数据和请求静态资源的分离的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

    web服务器nginx+部署前端vue项目

    ### Nginx 与前端 Vue 项目的部署 #### 一、Nginx 概述 Nginx 是一款广泛使用的高性能 HTTP 和反向代理 web 服务器。它以其出色的并发处理能力和较低的内存消耗而闻名。根据相关报告,Nginx 能够支持高达 50,000 ...

    nginx和tomcat的整合.pdf

    整合Nginx与Tomcat主要是为了解决两者在Web服务架构中的不同优势。Nginx擅长处理静态内容、提供高并发的HTTP连接处理,优化网络传输效率,以及负载均衡等功能;而Tomcat是一个优秀的开源Java应用服务器,擅长处理...

    tomcat-kb.zip

    标题中的"tomcat-kb.zip"表明这是一个关于Tomcat服务器的知识库压缩文件,可能包含了与配置、优化或问题解决相关的资料。描述中提到的"tomcat.nginx.conf"和"nginx-kb.conf"配置文件,暗示了这个知识库不仅涉及...

    nginx-1.9.8.zip

    2. **反向代理**:作为反向代理服务器,Nginx可以接收客户端请求,并将它们转发到后端的应用服务器,如Apache或Tomcat,从而实现负载均衡和性能优化。 3. **负载均衡**:通过配置不同的负载均衡策略,如轮询、最少...

    apache+tomcat负载

    7. JK模块通过心跳检测和负载算法确保Tomcat实例间的负载均衡,并在某个实例出现问题时,能够将请求重定向到其他健康的实例。 **实现步骤:** 1. **系统环境准备**:首先确保系统环境满足部署要求,通常包括安装...

Global site tag (gtag.js) - Google Analytics