Tomcat: 常见问题记录_20220607_七侠镇莫尛貝

1. Q.启动报错:INFO: The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: /usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib

A.开启apr协议:参考 配置Tomcat apr运行模式 - 星朝 - 博客园

大概过程:

安装对应的apr库;

bin/catalina.sh文件引入apr:

JAVA_OPTS="$JAVA_OPTS -Djava.library.path=/usr/local/apr/lib"

server.xml:

   
<!-- 默认开启apr监听,注释掉,启动tomcat时就不去找apr库了 -->
<!--APR library loader. Documentation at /docs/apr.html -->
<Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />

......


 <Connector port="9082" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="9443" URIEncoding="UTF-8" />

 <Connector port="9182" protocol="org.apache.coyote.http11.Http11NioProtocol"
               connectionTimeout="20000"
               redirectPort="9443" URIEncoding="UTF-8" />

 <Connector port="9082" protocol="org.apache.coyote.http11.Http11AprProtocol"
               connectionTimeout="20000"
               redirectPort="9443" URIEncoding="UTF-8" />

注意:

tomcat性能:apr >= nio > bio ,apr和nio性能差不多,不必强行使用apr。

tomcat8及高版本 默认使用nio,tomcat7 默认使用bio。

2. Q.server.xml里<Server port="9006" shutdown="SHUTDOWNxx"> 什么意思:

telnet localhost 9006,输入SHUTDOWNxx,就可以关闭tomcat.

注意:9006监听在127.0.0.1,所以只能 telnet localhost ,除非自己做端口转发。

注意:如果去掉port参数,则默认使用8005端口。

3.Q. 设置JAVA_OPTS: 

catalina.sh:

JAVA_OPTS="$JAVA_OPTS -server -Xms1024m -Xmx3000m -XX:PermSize=256M -XX:MaxNewSize=256m -XX:MaxPermSize=256m -Djava.awt.headless
    =true -Dfile.encoding='UTF-8'"

4.Q. 登陆manager:

tomcat-users.xml:

<role rolename="manager-gui"/>
<user username="tomcat" password="mypassword" roles="manager-gui"/>

5.Q. 多个tomcat7 (tomcat8以上暂时没有合适的库)使用redis做session共享,可免去在nginx做会话保持:

tomcat7/lib下放置库:commons-logging-1.2.jar  commons-pool2-2.4.2.jar  jedis-2.8.2.jar  tomcat-juli.jar  tomcat-redis-session-manage-tomcat7.jar

context.xml 增加:

<Valve className="com.orangefunction.tomcat.redissessions.RedisSessionHandlerValve" />
    <Manager className="com.orangefunction.tomcat.redissessions.RedisSessionManager" 
       host="127.0.0.1"
       port="6379" 
       password="redispassword"
       database="0" 
       maxInactiveInterval="60"/>

6.Q. /ROOT/index.jsp 自动跳转:

<%@ page language="java" pageEncoding="UTF-8" %>

<script type="text/javascript">
   window.location = "/sso/logon/password.jsp";
</script>

7.Q. AJP端口(反向代理长连接专用端口)可以关闭,除非有反向代理连接这个端口。

server.xml

<!-- Define an AJP 1.3 Connector on port 8009 -->
<!--
   <Connector port="9009" protocol="AJP/1.3" redirectPort="8443" />
-->

8.Q.  多个tomcat负载均衡调试jsp页面: 可以显示服务器IP,只修改header.jsp内容做区分即可。

index.jsp:

<%@ page language="java" pageEncoding="UTF-8" %>
<%@ page import="java.util.*" %>
<%@ page import="java.net.InetAddress" %>

<%
        InetAddress address = InetAddress.getLocalHost();  
        String ip=address .getHostAddress().toString();  
        pageContext.setAttribute("ip",ip);
%>

<script type="text/javascript">
//window.location = "/sso/logon/password.jsp";
</script>

    <body>

<jsp:include page="header.jsp"/>

<a href="login.jsp">login</a><br>
<a href="logout.jsp">logout</a><br>
<br>

    <%  
        String user = ""; 

        //if (!StringUtils.isBlank(request.getSession().getAttribute("USER"))) {
        if (null != request.getSession().getAttribute("USER")) {
                user = request.getSession().getAttribute("USER").toString().trim();
        }   

        //User user = (User) request.getSession().getAttribute("USER");
        if ("".equalsIgnoreCase(user)) {
        //out.println("用户为空,没有登录!!!");
    %>  
用户为空,没有登录!!!
<%
} else {
%>
欢迎: <%=user%>
<%
    }   
%>

login.jsp:

<%@ page language="java" pageEncoding="UTF-8" %>

<body>
<jsp:include page="header.jsp"/>

    <form action="/do_login.jsp?type=login" method="post">
        用户名:<input type="text" name="username" value="li_si" /><br/>
        密码:<input type="password" name="password" value="lisi_password" /><br/>
        <input type="submit" value="login">
    </form>
</body>

do_login.jsp:

<%@ page language="java" pageEncoding="UTF-8" %>
<%@ page import="org.apache.commons.lang.StringUtils" %>

<%
    String username = "";
    String password = "";

    if (!StringUtils.isBlank(request.getParameter("username"))) {
        username = request.getParameter("username");
    }
    if (!StringUtils.isBlank(request.getParameter("password"))) {
        password = request.getParameter("password");
    }
    request.getSession().setAttribute("USER", username +  password);
    out.println("User = " + username + " || " + password);
    //Thread.sleep(3000); 
    response.sendRedirect("index.jsp");

%>

logout.jsp:

<%@ page language="java" pageEncoding="UTF-8" %>
<%@ page import="org.apache.commons.lang.StringUtils" %>

<%
    request.getSession().setAttribute("USER", "");
    out.println("User logout! ");
    //Thread.sleep(3000); 
    response.sendRedirect("index.jsp");

%>

header.jsp: 不同的tomcat,修改Tomcat2为其他的,做区分。

<%@ page language="java" pageEncoding="UTF-8" %>
<%@ page import="java.util.*" %>
<%@ page import="java.net.InetAddress" %>

<%
        String path = request.getContextPath();
        String basePath = request.getScheme() + "://" + request.getServerName() + ":" + reque
st.getServerPort() + path + "/";

        InetAddress address = InetAddress.getLocalHost();
        String ip=address .getHostAddress().toString();
        pageContext.setAttribute("ip",ip);
%>
<h2>Session Demo in <font color="red"> Tomcat1 <%=ip%></font></h2>
String basePath = request.getScheme() + "://" + request.getServerName() + ":" + reque
st.getServerPort() + path + "/";
<br><%=basePath%>
<br><br>

9.Q.  nginx + tomcat 负载均衡(https):

/etc/nginx/conf.d/backend.conf:

#http + https loadbalance
upstream sso_backend {
        least_conn;
        #ip_hash;
        # null= round robin
         zone tcp_servers 64k;
         server 127.0.0.1:9181;
         #server 127.0.0.1:9182;
         #server 127.0.0.1:9183;
}

# https://www.ktanx.com/blog/p/5009
server {
         listen 9080;

        # SSL config
        listen 9443 ssl;
        #keepalive_timeout   70;
        ssl_certificate     server_chain.crt;
        ssl_certificate_key server.pkcs8;
        ssl_protocols       TLSv1 TLSv1.1 TLSv1.2;
        ssl_ciphers         HIGH:!aNULL:!MD5;
        ssl_verify_depth    2;

        status_zone tcp_server;
        proxy_redirect http:// $scheme://;
        port_in_redirect on;

        location / {
                #proxy_set_header Host $host:$server_port;
                proxy_set_header Host $host:$server_port;

                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header X-Forwarded-Proto $scheme;
                proxy_pass http://sso_backend;
        }
}

tomcat server.xml: 这里的48190和48144是最终用户在浏览器里打的url 里的端口。

......        
<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" />

<!--
http://tomcat.apache.org/tomcat-6.0-doc/api/org/apache/catalina/valves/RemoteI
pValve.html
-->
    <Valve className="org.apache.catalina.valves.RemoteIpValve"    
    remoteIpHeader="X-Forwarded-For"    
    protocolHeader="X-Forwarded-Proto"    
    protocolHeaderHttpsValue="https"
    httpServerPort="48190"
    httpsServerPort="48144"
    />   


      </Host>
    </Engine>

  </Service>
</Server>

10.

启动时有提示:org.apache.jasper.servlet.TldScanner.scanJars 至少有一个JAR被扫描

catalina.properties
jarsToSkip=\  改成 jarsToSkip=*.jar
============================================

# - Test JARs (JUnit, Cobertura and dependencies)
#tomcat.util.scan.StandardJarScanFilter.jarsToSkip=\
tomcat.util.scan.StandardJarScanFilter.jarsToSkip=*.jar
annotations-api.jar,\
ant-junit*.jar,\
ant-launcher.jar,\

11. localhost_access_*.txt 写入延迟:

server.xml   增加:buffered="false"


        <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
               prefix="localhost_access_log" suffix=".txt"
        resolveHosts="false"
        buffered="false"
               pattern="%h %l %u %t &quot;%r&quot; [%{postdata}r] %s %{Referer}i %{User
-Agent}i %T %b %D" />

12. tomcat只监听IPV4地址:

server.xml增加

address="0.0.0.0"       

<Connector port="443" protocol="org.apache.coyote.http11.Http11NioProtocol"
                address="0.0.0.0"       
               maxThreads="150" SSLEnabled="true" scheme="https" secure="true"
               keystoreFile="conf/192.168.103.150.jks" keystorePass="jkspassword"
               clientAuth="false" sslProtocol="TLS"/>

补: 20201012,上面的方法在centos73下无效,原因未知。

建议使用如下方法:

catalina.sh 里增加 -Djava.net.preferIPv4Stack=true -Djava.net.preferIPv4Addresses 有效。

如:

JAVA_OPTS="-Djava.awt.headless=true -Dfile.encoding=UTF-8 -server -Xms1024m -Xmx2048m -XX:NewSize=512m -XX:MaxNewSize=1024m -XX:PermSize=512m -XX:MaxP
ermSize=512m -Djava.net.preferIPv4Stack=true -Djava.net.preferIPv4Addresses"

补:服务器完全禁用IPV6方法:

/etc/sysctl.conf

增加:

# 禁止ipv6
net.ipv6.conf.all.disable_ipv6 =1
net.ipv6.conf.default.disable_ipv6 =1

sysctl -p 立即生效,或者重启生效。

13.记录post参数(2021-02-02):

https://www.cnblogs.com/yinliang/p/7495342.html

================================================
tomcat/conf/server.xml:

<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs_ex"
        buffered="false"
               prefix="post_log" suffix=".txt"
        pattern="%h %l %u %t &quot;%r&quot;  [%{postdata}r] %s %T %b" />


=================================================
tomcat/webapps/uts/WEB-INF/web.xml:

<filter>
        <filter-name>post-data-dumper-filter</filter-name>
        <filter-class>com.terry.PostDataDumperFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>post-data-dumper-filter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

=================================================
com.zip解压到tomcat/webapps/app/WEB-INF/classes/

unipz com.zip -d ./com/

=================================================
查看日志方法:
tail -f logs_ex/post_log.txt

PostDataDumperFilter代码:

package com.terry;

/**
 * Created by Terry2 on 2021/2/2.
 * https://www.cnblogs.com/yinliang/p/7495342.html
 */
import java.io.IOException;
import java.util.Enumeration;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public final class PostDataDumperFilter implements Filter {

    Logger logger = LoggerFactory.getLogger(getClass());

    private FilterConfig filterConfig = null;

    public void destroy() {
        this.filterConfig = null;
    }

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        if (filterConfig == null)
            return;

        Enumeration<String> names = request.getParameterNames();
        StringBuilder output = new StringBuilder();
        while (names.hasMoreElements()) {
            String name = (String) names.nextElement();
            output.append(name).append("=");
            String values[] = request.getParameterValues(name);
            for (int i = 0; i < values.length; i++) {
                if (i > 0) {
                    output.append("' ");
                }

                output.append(values[i]);
            }
            if (names.hasMoreElements())
                output.append("&");
        }
        request.setAttribute("postdata", output);
        //request.setAttribute("log_postdata_only", null);
        logger.debug("postdata: " + output);
        chain.doFilter(request, response);
    }

    public void init(FilterConfig filterConfig) throws ServletException {
        this.filterConfig = filterConfig;
    }
}

14.Q.  xx

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值