Tomcat启动地址解析错误

贴log:
SEVERE: Protocol handler pause failed
java.net.UnknownHostException: NEOSTA: NEOSTA
at java.net.InetAddress.getLocalHost(InetAddress.java:1474)
at org.apache.jk.common.ChannelSocket.unLockSocket(ChannelSocket.java:484)
at org.apache.jk.common.ChannelSocket.pause(ChannelSocket.java:283)
at org.apache.jk.server.JkMain.pause(JkMain.java:681)
at org.apache.jk.server.JkCoyoteHandler.pause(JkCoyoteHandler.java:153)
at org.apache.catalina.connector.Connector.pause(Connector.java:1073)
at org.apache.catalina.core.StandardService.stop(StandardService.java:563)
at org.apache.catalina.core.StandardServer.stop(StandardServer.java:744)
at org.apache.catalina.startup.Catalina.stop(Catalina.java:628)
at org.apache.catalina.startup.Catalina$CatalinaShutdownHook.run(Catalina.java:671)
关键词:UnknownHostException, JK
原因在google的第一个,虽然上面说的是AIX,但也适用于普通Linux:RHEL5原装的GCJ太山寨了,记得在启动tomcat前要指定JAVA_HOME。

简单比较Apache+Tomcat的mod_jk和mod_proxy方法

这几天服务上线。由于80端口还需要blog和wiki两个服务,所以把80给了Apache管理,然后再通过apache连接后面8080的Tomcat。
Apache+Tomcat主要有三种办法实现: mod_jk, mod_proxy和ajp_proxy。mod_jk是比较专门针对Tomcat的方法,通过AJP协议连接Tomcat,mod_proxy不止可以连接Tomcat,只要是HTTP应用都可以进行反向代理。ajp_proxy不是很清楚,具体参见这里
我前后碰到过三种不同的配置环境。第一次是搭建试验服务的时候,服务搭建在一台内网机器上,通过外网机器的8080端口映射内网的80端口进行访问。由于可对外暴露的端口只有被映射的一个80端口,自然把Apache推了上去。使用mod_proxy进行反向代理配置。后来上面要求搭建两个运行实例,于是开了两份Tomcat,配了两份的proxy。一个在18080,一个在28080。

ProxyPass /app http://localhost:18080/app
ProxyPassReverse /app http://localhost:18080/app
ProxyPass /app2 http://localhost:28080/app2
ProxyPassReverse /app2 http://localhost:28080/app2
第二次的环境并不是Apache+Tomcat,而是IIS+Tomcat。对IIS的不熟悉让我一段时间之内挠破了头。IIS上我没有找到比较实用的mod_proxy组件,特别是使用ISAPI的mod_proxy。而另外一个重大变化在需求上,这次要求服务支持SaaS,而我们服务的SaaS通过访问的域名来区别不同的租户。比如通过abc.example.com和def.example.com访问的用户,虽然使用的是同一个应用,但是却在不同的租户空间内进行操作。
可行的办法是使用ISAPI Rewrite。ISAPI Rewrite事实上是提供Proxy功能的,但那是收费版本。免费的Lite版本只有URL Rewrite的功能。我只好彻底放弃了Proxy的打算,对用户做重定向。比如访问http://abc.example.com的用户将被重定向到http://abc.exmaple.com:8080/app。对于wiki和blog这些访问,在配置文件中当作例外处理。以下是配置文件:
RewriteCond %{HTTP:Host} example\.com$
RewriteCond %{HTTP:Host} !www\.example\.com$
RewriteCond %{HTTP:Host} !wiki\.example\.com$
RewriteCond %{HTTP:Host} !blog\.example\.com$
RewriteRule app/(.*) http://%{HTTP:Host}\:8080/app/$1 [NC,R=301]
RewriteCond %{HTTP:Host} example\.com$
RewriteCond %{HTTP:Host} !www\.example\.com$
RewriteCond %{HTTP:Host} !wiki\.example\.com$
RewriteCond %{HTTP:Host} !blog\.example\.com$
RewriteRule (.*) http://%{HTTP:Host}\:8080/app [NC,R=301]
RewriteCond %{HTTP:Host} www\.example\.com$
RewriteRule ^/$ http://%{HTTP:Host}/app/index.htm [NC,R=301]
RewriteCond %{HTTP:Host} wiki\.example\.com$
RewriteRule ^/(.*)$ http://www.example.com/wiki/$1
RewriteCond %{HTTP:Host} blog\.example\.com$
RewriteRule ^/(.*)$ http://www.example.com/blog/$1
第三次,经过争取,服务器的80端口让位于Apache。当我打算切回第一次的mod_proxy配置时,却发现一个致命的问题:Request里Host的内容已经被mod_proxy修改成了配置文件里的localhost,没有反映用户真实请求里的abc.example.com或者def.example.com。况且系统还要求支持实时添加租户,即在不重启系统的情况下增加新的*.example.com的访问。
mod_proxy虽然能对后台任何的HTTP服务做反向代理,却把泛域名访问给挡在了门边。另外我也终于明白了为什么试验服务器上的Tomcat访问日志里,来源都是127.0.0.1——因为来源都是Apache这个代理。
mod_jk的配置里,虽然仍然需要输入Tomcat的Host,但是似乎AJP协议的保留了前台访问的域名(后台程序通过request.getServerName()获得)。而客户端的IP地址也被成功的记录下来。有兴趣的同学们可以参见AJP 1.3的协议参考。mod_jk的配置就不贴出来了,具体可以看开头介绍proxy_ajp的那个链接

使用Cache-Control和gzip提升tomcat应用性能(整理)

这个其实应该是常识,只不过以前做的J2EE应用大部分是内网里跑的东西,所以性能上没什么问题。这次APIS由于有在外面用的可能,加上使用了一些比较大的javascript框架(Ext),所以性能问题瞬间窜了上来。
以前做的J2EE应用没有使用上达500K的框架,最多就是几十K的Prototype,所以没什么问题。一个页面一般也就几十K最多了。但这次还在开发中的APIS,由于还在用debug版本的库,所以单单Ext就膨胀到了一个多M,加上不知道是Struts还是Tomcat默认写入Response的cache-control: no cache,在远程用起来就很慢,一般一个页面需要十多秒种甚至更久,实在无法忍受。前几天集中解决了问题。
首先是Cache-Control的问题,Google了好一阵,没有什么直接配置的方法,只好自己抄了一个一个Filter,通过和web.xml里配置的配合勉强凑合着用。一般就是对*.do实施no-cache政策,其他需要缓存的img, js文件,统统加上长达两周的缓存期限。ETag实在不会用,就先用这个缓存策略吧。
Filter的代码:

  1. public class ResponseHeaderFilter implements Filter {
  2. FilterConfig fc;
  3. public void doFilter(ServletRequest req, ServletResponse res,
  4. FilterChain chain) throws IOException, ServletException {
  5. HttpServletResponse response = (HttpServletResponse) res;
  6. // set the provided HTTP response parameters
  7. for (Enumeration e = fc.getInitParameterNames(); e.hasMoreElements();) {
  8. String headerName = (String) e.nextElement();
  9. response.addHeader(headerName, fc.getInitParameter(headerName));
  10. }
  11. // pass the request/response on
  12. chain.doFilter(req, response);
  13. }
  14. public void init(FilterConfig filterConfig) {
  15. this.fc = filterConfig;
  16. }
  17. public void destroy() {
  18. this.fc = null;
  19. }
  20. }

web.xml里的巧妙配置:

  1. <filter>
  2. <filter-name>NoCache</filter-name>
  3. <filter-class>apis.server.common.util.ResponseHeaderFilter</filter-class>
  4. <init-param>
  5. <param-name>Cache-Control</param-name>
  6. <param-value>no-cache, must-revalidate</param-value>
  7. </init-param>
  8. </filter>
  9. <filter>
  10. <filter-name>CacheForWeek</filter-name>
  11. <filter-class>apis.server.common.util.ResponseHeaderFilter</filter-class>
  12. <init-param>
  13. <param-name>Cache-Control</param-name>
  14. <param-value>max-age=604800, public</param-value>
  15. </init-param>
  16. </filter>
  17. <filter-mapping>
  18. <filter-name>NoCache</filter-name>
  19. <url-pattern>*.do</url-pattern>
  20. </filter-mapping>
  21. <filter-mapping>
  22. <filter-name>CacheForWeek</filter-name>
  23. <url-pattern>/images/*</url-pattern>
  24. </filter-mapping>
  25. <filter-mapping>
  26. <filter-name>CacheForWeek</filter-name>
  27. <url-pattern>/img/*</url-pattern>
  28. </filter-mapping>
  29. <filter-mapping>
  30. <filter-name>CacheForWeek</filter-name>
  31. <url-pattern>/icons/*</url-pattern>
  32. </filter-mapping>
  33. <filter-mapping>
  34. <filter-name>CacheForWeek</filter-name>
  35. <url-pattern>/ext/*</url-pattern>
  36. </filter-mapping>
  37. <filter-mapping>
  38. <filter-name>CacheForWeek</filter-name>
  39. <url-pattern>*.js</url-pattern>
  40. </filter-mapping>
  41. <filter-mapping>
  42. <filter-name>CacheForWeek</filter-name>
  43. <url-pattern>*.css</url-pattern>
  44. </filter-mapping>

(插入一段:在探测这些性能问题的时候,我使用的是一个Firebug的插件,也就是Firefox插件的插件-YSlow,好像是Yahoo的,结合Firebug里XHR的Net这块做Profiling,效果很不错,很容易就知道瓶颈)
还有一个gzip的办法,就是在服务器压缩内容,再传给浏览器。现在主流的浏览器都支持gzip压缩,而且这些html和js文本压缩起来很厉害,基本上可以有40%的压缩率。办法在servel.xml的注释里也有写,就是在Connector元素里加上
compression=”on”
compressionMinSize=”2048″
noCompressionUserAgents=”gozilla,traviata”
compressableMimeType=”text/html,text/xml,text/javascript,text/css,text/plain”
以上的内容大部分都是Google得来,我自己做了一下整理

zz:Tomcat的中文乱码的经典解决方案

(转贴注:原来要用filter还有这么多的问题。要分别对待GET和POST方法。GET要在Connector里设好了URIEncoding(不是URLEncoding),今天被搞死了。。)

引言:
近期在做我们学校(华中科技大学)的注册中心的信息速递系统中又遇到了久违中文乱码的问题。由于注册中心的HUB系统需要团队开发完成,这导致中文 乱码问题尤为突出。万般无奈之下,硬下头皮寻根究底的找出问题的真正原因。皇天不负有心人,在查阅了N多资料和做了无数次试验之后,终于找到了个人认为较 为简单和经典的解决方案。
适用环境:
采用Tomcat 4.x或Tomcat 5.x,应用中出现中文乱码现象,且找不到统一的解决方案。
主要现象:
在应用中采用GET方式或POST方式时会出现中文乱码现象,而且针对这两种方式不能使用唯一的解决方案。一般您可能会使用以下的几种方案:
A.request.setCharacterEncoding(“gb2312”);
B.type = new String(type.getBytes(“ISO8859-1”), “GB2312”);
C.在Tomcat的配置文件Server.xml中的Connector标签中加入“URIEncoding=UTF-8”属性;
D.conf\web.xml 指定多个Encoding参数;
E.编写一个filter,处理Post提交的编码问题;
但有时候您可能会发现,这样做会让问题更糟糕。
问题分析:
要解决中文乱码的问题,首先要了解Tomcat在背后的处理机制,在查阅了许多资料以及许多前辈们写的文章并做了无数次试验之后,我找到了导致Tomcat中出现中文乱码的主要原因,即Tomcat对GET和POST两种方式的处理方法:在Tomcat 4.x时,采用的是GET和POST两种方式使用相同的字符集,也就是UTF-8。但在Tomcat 5.x下,GET和POST方式采用了不同的字符集
解决方案:
首先我想申明,我所给出的只是解决方案的一种,并不代表我给出的方案能解决大家所遇到的所有问题,但是有一点是肯定的,大家在同一个系统中必须使用相同的解决方案,如果可以最好统一您应用中各个组件包括数据库、JDK、WEB服务器等等的字符编码方案。
而我所采用的是下面的这种方案(只针对Tomcat):
Tomcat 4.x
1.页面编码采用“charset=gb2312”;
2.接收参数使用“request.setCharacterEncoding(“gb2312”);”;
3.如果需要在转换编码,如“type = new String(type.getBytes(“ISO8859-1”), “GB2312”);”;
Tomcat 5.x
1.在配置文件Server.xml的Connector标签中加入“useBodyEncodingForURI=”true””,这个属性主要 是让Tomcat 5.x在GET和POST方式使用相同的字符集。如果这样做仍不能解决问题,您可以尝试再加入另一个属性“URIEncoding=UTF-8”;
2.其他处理同Tomcat 4.x
以上方法可做参考,如果您有其他好的方法或觉得本文中有任何问题或遗漏欢迎批评斧正。

如何配置tomcat的ROOT为/

修改%TOMCAT_ROOT%/conf/Catalina/localhost下的Web应用配置文件。
1.删除或移走ROOT.xml,这个文件就 是tomcat的root配置;
2.修改server.xml, <Host>里加上
<Context docBase=”test” path=”” workDir=”work\Catalina\localhost\test” reloadable=”true”/>
docBase:为你的Web应用程序所在的路径,可以为相对和绝对路径, 相对路径 为相对于在<Host>里配置的属性appBase的路径;
path:为Web应用的上下文路径,保持为空则会绑定到root路径上;(其实就是如果没有被其他<Context>定义了,就到这个目录去。
workDir: 为Web应用的临时工作目录,存放编译后的类和页面。
Tomcat的doc:
If you specify a context path of an empty string (“”), you are defining the default web application for this Host, which will process all requests not assigned to other Contexts. The value of this field must not be set except when statically defining a Context in server.xml, as it will be infered from the filenames used for either the .xml context file or the docBase.
还有一个debug属性,经常看到人写,但在tomcat的文档里没有看到,不知道是为什么。
文档地址 http://tomcat.apache.org/tomcat-5.5-doc/config/context.html
<![CDATA[修改%TOMCAT_ROOT%/conf/Catalina/localhost下的Web应用配置文件。
1.删除或移走ROOT.xml,这个文件就 是tomcat的root配置;
2.修改server.xml, 里加上

docBase:为你的Web应用程序所在的路径,可以为相对和绝对路径, 相对路径 为相对于在里配置的属性appBase的路径;
path:为Web应用的上下文路径,保持为空则会绑定到root路径上;(其实就是如果没有被其他定义了,就到这个目录去。
workDir: 为Web应用的临时工作目录,存放编译后的类和页面。
Tomcat的doc:
If you specify a context path of an empty string (“”), you are defining the default web application for this Host, which will process all requests not assigned to other Contexts. The value of this field must not be set except when statically defining a Context in server.xml, as it will be infered from the filenames used for either the .xml context file or the docBase.
还有一个debug属性,经常看到人写,但在tomcat的文档里没有看到,不知道是为什么。
文档地址 http://tomcat.apache.org/tomcat-5.5-doc/config/context.html%5D%5D&gt;