本文介绍了如何在Wildfly 8.2.0.Final中寻找晦涩的HA群集错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个Wildfly 8.2.0.Final应用程序服务器使用Full-ha配置文件在域模式下运行集群。群集由Wildfly的两个实例(主实例和从实例)组成,每个实例都在自己的虚拟机上运行。

I have a Wildfly 8.2.0.Final application server running a cluster in domain mode using the full-ha profile. The cluster consists of two instances of wildfly, master and slave, each running on its own virtual machine.

我的项目作为War文件部署在应用程序服务器上。为了测试目的,我的负载均衡器使用循环分发请求。

My project is deployed as a war-file on the application server. For test purposes my loadbalancer distributes the requests using round-robin.

匿名用户可以通过按钮使用此项目提供的服务,该按钮将分两个步骤进行调用,首先进行注册然后登录。登录将使用在注册阶段创建的会话,并提供在注册调用期间创建的凭据。

Anonymous users can use the service provided by this project using a button, which will call in two steps first register then login. Login will use the session that is created during the register phase providing the credentials created during the register call.

登录端点是一个请求范围内的CDI bean,除其他成员外,该成员还有一个保存用户信息的成员。用户信息是一个SessionScopped EJB Bean,它在会话实例化期间创建,并注入到登录端点CDI bean中。用户信息应该在群集成员之间分配。

The login endpoint is a request scoped CDI bean, which among other members has a member which holds user information. The user information is a SessionScopped EJB Bean which is created during session instantiation and which is injected into the login endpoints CDI bean. The user information is supposed to get distributed among cluster members.

现在有趣的部分是:

  • 使用Firefox:
  • Using Firefox:
  1. / rest / register-> 200 OK

  2. / rest / login-> 200 OK



  • 在私有模式下使用Firefox:

  • Using Firefox in private mode:

    1. / rest / register -> 200 OK

    2. / rest / login-> 200 OK



  • 使用Chrome: b $ b

  • Using Chrome:

    1. / rest / register-> 200 OK

    2. / rest / login-> 200 OK



  • 以私密模式使用Chrome:

  • Using Chrome in private mode:

    1. / rest / register-> 200 OK

    2. / rest / login-> 200 OK



  • 使用Internet Explorer 11:

  • Using Internet Explorer 11:

    1. / rest / register-> 200 OK

    2. / rest / login-> 200 OK



  • 在私有模式下使用Internet Explorer 11:

  • Using Internet Explorer 11 in private mode:

    1. / rest / register-> 200 OK

    2. / rest / login-> 500 Internal Server error

  • 这是500的堆栈跟踪:

    This is the stack trace of the 500:

        2015-05-07 10:05:31,734 ERROR [io.undertow.request] (default task-11) UT005023: Exception handling request to /testtest/rest/login: org.jboss.resteasy.spi.UnhandledException: java.lang.NullPointerException
            at org.jboss.resteasy.core.ExceptionHandler.handleApplicationException(ExceptionHandler.java:76) [resteasy-jaxrs-3.0.10.Final.jar:]
            at org.jboss.resteasy.core.ExceptionHandler.handleException(ExceptionHandler.java:212) [resteasy-jaxrs-3.0.10.Final.jar:]
            at org.jboss.resteasy.core.SynchronousDispatcher.writeException(SynchronousDispatcher.java:149) [resteasy-jaxrs-3.0.10.Final.jar:]
            at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:372) [resteasy-jaxrs-3.0.10.Final.jar:]
            at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:179) [resteasy-jaxrs-3.0.10.Final.jar:]
            at org.jboss.resteasy.plugins.server.servlet.ServletContainerDispatcher.service(ServletContainerDispatcher.java:220) [resteasy-jaxrs-3.0.10.Final.jar:]
            at org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:56) [resteasy-jaxrs-3.0.10.Final.jar:]
            at org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:51) [resteasy-jaxrs-3.0.10.Final.jar:]
            at javax.servlet.http.HttpServlet.service(HttpServlet.java:790) [jboss-servlet-api_3.1_spec-1.0.0.Final.jar:1.0.0.Final]
            at io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:85) [undertow-servlet-1.1.0.Final.jar:1.1.0.Final]
            at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:61) [undertow-servlet-1.1.0.Final.jar:1.1.0.Final]
            at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36) [undertow-servlet-1.1.0.Final.jar:1.1.0.Final]
            at org.wildfly.extension.undertow.security.SecurityContextAssociationHandler.handleRequest(SecurityContextAssociationHandler.java:78)
            at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) [undertow-core-1.1.0.Final.jar:1.1.0.Final]
            at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:131) [undertow-servlet-1.1.0.Final.jar:1.1.0.Final]
            at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:56) [undertow-servlet-1.1.0.Final.jar:1.1.0.Final]
            at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) [undertow-core-1.1.0.Final.jar:1.1.0.Final]
            at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:45) [undertow-core-1.1.0.Final.jar:1.1.0.Final]
            at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:63) [undertow-servlet-1.1.0.Final.jar:1.1.0.Final]
            at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:58) [undertow-core-1.1.0.Final.jar:1.1.0.Final]
            at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:70) [undertow-servlet-1.1.0.Final.jar:1.1.0.Final]
            at io.undertow.security.handlers.SecurityInitialHandler.handleRequest(SecurityInitialHandler.java:76) [undertow-core-1.1.0.Final.jar:1.1.0.Final]
            at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) [undertow-core-1.1.0.Final.jar:1.1.0.Final]
            at org.wildfly.extension.undertow.security.jacc.JACCContextIdHandler.handleRequest(JACCContextIdHandler.java:61)
            at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) [undertow-core-1.1.0.Final.jar:1.1.0.Final]
            at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) [undertow-core-1.1.0.Final.jar:1.1.0.Final]
            at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:261) [undertow-servlet-1.1.0.Final.jar:1.1.0.Final]
            at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:247) [undertow-servlet-1.1.0.Final.jar:1.1.0.Final]
            at io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:76) [undertow-servlet-1.1.0.Final.jar:1.1.0.Final]
            at io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:166) [undertow-servlet-1.1.0.Final.jar:1.1.0.Final]
            at io.undertow.server.Connectors.executeRootHandler(Connectors.java:197) [undertow-core-1.1.0.Final.jar:1.1.0.Final]
            at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:759) [undertow-core-1.1.0.Final.jar:1.1.0.Final]
            at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) [rt.jar:1.7.0_65]
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) [rt.jar:1.7.0_65]
            at java.lang.Thread.run(Thread.java:745) [rt.jar:1.7.0_65]
    Caused by: java.lang.NullPointerException
            at org.jboss.weld.context.beanstore.http.AbstractSessionBeanStore.getLockStore(AbstractSessionBeanStore.java:113) [weld-core-impl-2.2.6.Final.jar:2014-10-03 10:05]
            at org.jboss.weld.context.beanstore.AttributeBeanStore.lock(AttributeBeanStore.java:210) [weld-core-impl-2.2.6.Final.jar:2014-10-03 10:05]
            at org.jboss.weld.context.AbstractContext.get(AbstractContext.java:90) [weld-core-impl-2.2.6.Final.jar:2014-10-03 10:05]
            at org.jboss.weld.context.PassivatingContextWrapper$AbstractPassivatingContextWrapper.get(PassivatingContextWrapper.java:76) [weld-core-impl-2.2.6.Final.jar:2014-10-03 10:05]
            at org.jboss.weld.bean.proxy.ContextBeanInstance.getInstance(ContextBeanInstance.java:98) [weld-core-impl-2.2.6.Final.jar:2014-10-03 10:05]
            at org.jboss.weld.bean.proxy.ProxyMethodHandler.invoke(ProxyMethodHandler.java:78) [weld-core-impl-2.2.6.Final.jar:2014-10-03 10:05]
            at ru.exampl.testtest.lobby.UserController$Proxy$_$$_WeldClientProxy.toString(Unknown Source) [classes:]
            at org.apache.log4j.spi.LoggingEvent.<init>(LoggingEvent.java:106) [log4j-jboss-logmanager-1.1.0.Final.jar:1.1.0.Final]
            at org.apache.log4j.Category.forcedLog(Category.java:119) [log4j-jboss-logmanager-1.1.0.Final.jar:1.1.0.Final]
            at org.apache.log4j.Category.debug(Category.java:80) [log4j-jboss-logmanager-1.1.0.Final.jar:1.1.0.Final]
            at ru.exampl.testtest.rest.LobbyEndpoint.login(LobbyEndpoint.java:100) [classes:]
            at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) [rt.jar:1.7.0_65]
            at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) [rt.jar:1.7.0_65]
            at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) [rt.jar:1.7.0_65]
            at java.lang.reflect.Method.invoke(Method.java:606) [rt.jar:1.7.0_65]
            at org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:137) [resteasy-jaxrs-3.0.10.Final.jar:]
            at org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTarget(ResourceMethodInvoker.java:296) [resteasy-jaxrs-3.0.10.Final.jar:]
            at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:250) [resteasy-jaxrs-3.0.10.Final.jar:]
            at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:237) [resteasy-jaxrs-3.0.10.Final.jar:]
            at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:356) [resteasy-jaxrs-3.0.10.Final.jar:]
    



    代码



    这是导致错误的相关代码(或者在某些情况下不起作用):

    The code

    And this is the relevant code which causes the error (or not in those cases where it just works):

    package ru.exampl.testtest.rest;
    
    [... lots of imports ...]
    
    /**
     * The implementation of some general webservice endpoints.
     */
    @RequestScoped
    @Path("rest")
    public class LobbyEndpoint {
    
        private transient static final Logger log4j = Logger.getLogger(LobbyEndpoint.class);
    
        @Inject
        private UserController userController;
    
        [... more injections ...]
    
        @POST
        @Path("/login")
        @Consumes(MediaType.APPLICATION_JSON)
        @Produces(MediaType.APPLICATION_JSON)
        public LoginResponse login(LoginRequest request) {
            log4j.log(userController);
            [... lots of code to handle login ...]
        }
    }
    

    现在有趣的是, userController 显然不是null,因为log4j知道如何处理和记录null对象。该对象显然具有引用,但Weld无法通过代理访问它。如果没有浏览器列表,而这个浏览器列表只有一个特定的浏览器以一种特定的浏览器模式运行,则该应用本身会因此崩溃。

    Now the funny thing is, that userController is obviously not null, since log4j knows how to handle and log null objects. The object obviously has a reference but Weld can't access it through the proxy. This in itself would be only half as funny without the list of browsers where this very same rest endpoint just does its job and only one specific browser in one specific browser mode causing the webapp to crash.

    老实说,我不知道浏览器如何通过其请求引发这种行为。但是为了使事情变得更有趣,我用tshark记录了实际的请求,然后修改了Firefox以发送Internet Explorer 11发送的相同请求。现在屏住呼吸:所有事情都一样,Firefox不会使webapp崩溃,而私有模式下的Internet Explorer 11确实有100%的时间。

    To be honest, I have NO clue how a browser through its requests could provoke such a behavior. But to make things even more funny, I recorded the actual requests with tshark and then modified Firefox to send the very same request the Internet Explorer 11 sends. And now hold your breath: all things being equal Firefox doesn't crash the webapp while Internet Explorer 11 in private mode does 100% of the time.

    我记录了两个请求进行演示(您可以在Wireshark中查看它们):

    I recorded both requests to demonstrate (you can view them in wireshark):


    现在我的问题是:我什至在哪里开始调试呢?
    如果整个请求是相同的(除了请求),那么Web浏览器如何通过代理传递请求甚至对群集中会话同步的结果有最小的影响,从而影响应用程序服务器上的请求处理。标头顺序?时间不涉及。在请求中引入随机等待并没有什么改变。

    Now my question: where do I even start to debug this?How can a web browser delivering its requests through a proxy even have the slightest influence on the outcome of my session synchronization in my cluster and thus influencing the request processing on my application server, if the entire request is identical except for the order of the headers? Timing is not involved. Introducing random waits in the requests didn't change anything.

    推荐答案

    我有一个类似的堆栈跟踪。但是我忘记了在我的wildfly配置的underwow部分中设置了 instance-id。只要服务器不尝试复制会话,问题就不会出现。

    I had a similar looking stack trace. But I forgot set the "instance-id" in the undertow section of my wildfly configuration. The problem didn't come up, as long as the server didn't try to replicate the session.

    所以对我来说,解决方案只是设置一个实例ID,例如这:

    So the solution for me was simply setting an instance-id like this:

    <subsystem xmlns="urn:jboss:domain:undertow:1.2" instance-id="${jboss.server.name}">
    

    也可以通过jboss-cli设置:

    This can also be set via jboss-cli:

    /profile=full-ha/subsystem=undertow:write-attribute(name=instance-id, value="${jboss.server.name}")
    

    [编辑:尝试查找解释]

    [Edit: trying to find explanation]

    NullpointerException发生在以下语句中:

    The NullpointerException happenes with this statement:

    lockStore = (LockStore) session.getAttribute(SESSION_KEY);
    

    在此语句中,仅当 session为null时,才会发生NPE。通过调用由子类实现的getSession()方法,可以更早地获取会话对象。我可以找到两个可能的候选对象:

    At this statement the NPE will only occur if "session" is null. The "session" Object is acquired earlier by calling a getSession() Method which is implemented by a child class. I can find two possible candidates:


    • LazySessionBeanStore(org.jboss.weld.context.beanstore.http)

    • LazyCyclicSessionBeanStore(org.jboss.weld.context.beanstore.http)

    • EagerSessionBeanStore(org.jboss.weld.context.beanstore.http)

    对我来说并不明显,为什么这些类可以为会话返回null。以及这与在untertow部分中设置 instance-id有关。我看到的是,在这些位置创建了许多日志记录语句。为了进一步说明这一点,我将尝试在 org.jboss.weld上将日志级别设置为 TRACE。

    It's not obvious to me, why those classes could return null for "session". And how this is connected to setting the "instance-id" in the untertow section. What I can see is, that many logging statements are created at these. To go further on this, I would try to set the log level to "TRACE" on "org.jboss.weld".

    这篇关于如何在Wildfly 8.2.0.Final中寻找晦涩的HA群集错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

    08-04 04:43
    查看更多