是否有用于Tomcat 6群集配置的useDirtyFlag选项? [英] Is there a useDirtyFlag option for Tomcat 6 cluster configuration?

查看:138
本文介绍了是否有用于Tomcat 6群集配置的useDirtyFlag选项?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Tomcat 5.0.x中,您可以在每次请求之后将useDirtyFlag =false设置为强制复制会话,而不是检查set / removeAttribute调用。

In Tomcat 5.0.x you had the ability to set useDirtyFlag="false" to force replication of the session after every request rather than checking for set/removeAttribute calls.

<Cluster className="org.apache.catalina.cluster.tcp.SimpleTcpCluster"
                 managerClassName="org.apache.catalina.cluster.session.SimpleTcpReplicationManager"
                 expireSessionsOnShutdown="false"
                 **useDirtyFlag="false"**
                 doClusterLog="true"
                 clusterLogName="clusterLog"> ...

server.xml中的注释表明这可用于进行以下工作:

The comments in the server.xml stated this may be used to make the following work:

<%
    HashMap map = (HashMap)session.getAttribute("map");
    map.put("key","value");
%>

即。更改已经放入会话的对象的状态,并且您可以确保此对象仍然被复制到群集中的其他节点。

i.e. change the state of an object that has already been put in the session and you can be sure that this object still be replicated to the other nodes in the cluster.

根据Tomcat 6文档,您只有两个经理选项 - DeltaManager& BackupManager ......这些似乎都不允许这个选项或类似的东西。在我的测试中,默认设置为:

According to the Tomcat 6 documentation you only have two "Manager" options - DeltaManager & BackupManager ... neither of these seem to allow this option or anything like it. In my testing the default setup:

  <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>

默认情况下你得到DeltaManager,它肯定表现为useDirtyFlag =true(因为我' d期待)。

where you get the DeltaManager by default, it's definitely behaving as useDirtyFlag="true" (as I'd expect).

所以我的问题是 - Tomcat 6中是否存在等价物?

So my question is - is there an equivalent in Tomcat 6?

查看源代码我可以看到一个管理器实现org.apache.catalina.ha.session.SimpleTcpReplicationManager,它确实有useDirtyFlag但是这个状态下的javadoc注释它是Tomcat 4.0的Tomcat会话复制......我不知道这是否可以使用 - 我猜不是因为主集群配置文档中没有提到它。

Looking at the source I can see a manager implementation "org.apache.catalina.ha.session.SimpleTcpReplicationManager" which does have the useDirtyFlag but the javadoc comments in this state it's "Tomcat Session Replication for Tomcat 4.0" ... I don't know if this is ok to use - I'm guessing not as it's not mentioned in the main cluster configuration documentation.

推荐答案

我在tomcat-users邮件列表上发布了基本相同的问题以及对此的回复以及tomcat中的一些信息bugzilla([43866])让我得出以下结论:

I posted essentially the same question on the tomcat-users mailing list and the responses to this along with some information in the tomcat bugzilla ([43866]) led me to the following conclusions:


  1. 没有等效的useDirtyFlag,如果你推出了mutable(在会话中你需要一个自定义的编码解决方案。

  2. 一个Tomcat ClusterValve似乎是这个解决方案的一个有效的地方 - 插入集群机制,操纵属性使它出现到DeltaManager,会话中的所有属性都已更改。这会强制复制整个会话。

第1步:编写 ForceReplicationValve (extends ValveBase 实现 ClusterValve

Step 1: Write the ForceReplicationValve (extends ValveBase implements ClusterValve)

我不会包括整个类,但逻辑的关键位(取出日志记录和instanceof检查):

I won't include the whole class but the key bit of logic (taking out the logging and instanceof checking):

@Override
public void invoke(Request request, Response response) 
        throws IOException, ServletException {
    getNext().invoke(request, response);
    Session session = request.getSessionInternal();        
    HttpSession deltaSession = (HttpSession) session;
    for (Enumeration<String> names = deltaSession.getAttributeNames(); 
            names.hasMoreElements(); ) {
        String name = names.nextElement();
        deltaSession.setAttribute(name, deltaSession.getAttribute(name));
    }
}

步骤2:更改群集配置(在 conf / server.xml

Step 2: Alter the cluster config (in conf/server.xml)

<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"
            channelSendOptions="8">        
    <Valve className="org.apache.catalina.ha.tcp.ForceReplicationValve"/>
    <Valve className="org.apache.catalina.ha.tcp.ReplicationValve"
          filter=".*\.gif;.*\.jpg;.*\.png;.*\.js;.*\.htm;.*\.html;.*\.txt;.*\.css;"/>
    <Valve className="org.apache.catalina.ha.session.JvmRouteBinderValve"/>

    <ClusterListener className="org.apache.catalina.ha.session.JvmRouteSessionIDBinderListener"/>
    <ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/>
</Cluster>

现在,每次请求后都会复制到所有集群节点的会话。

Replication of the session to all cluster nodes will now happen after every request.

除此之外:注意 channelSendOptions 设置。这将替换Tomcat 5.0.x中的 replicationMode = asynchronous / synchronous / pooled 。有关可能的int值,请参阅集群文档

Aside: Note the channelSendOptions setting. This replaces the replicationMode=asynchronous/synchronous/pooled from Tomcat 5.0.x. See the cluster documentation for the possible int values.

附录:按要求提供完整阀门来源

package org.apache.catalina.ha.tcp;

import java.io.IOException;
import java.util.Enumeration;
import java.util.LinkedList;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpSession;

import org.apache.catalina.Lifecycle;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.LifecycleListener;
import org.apache.catalina.Session;
import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;
import org.apache.catalina.ha.CatalinaCluster;
import org.apache.catalina.ha.ClusterValve;
import org.apache.catalina.ha.session.ReplicatedSession;
import org.apache.catalina.ha.session.SimpleTcpReplicationManager;
import org.apache.catalina.util.LifecycleSupport;
//import org.apache.catalina.util.StringManager;
import org.apache.catalina.valves.ValveBase;

/**
 * <p>With the {@link SimpleTcpReplicationManager} effectively deprecated, this allows
 * mutable objects to be replicated in the cluster by forcing the "dirty" status on 
 * every request.</p> 
 * 
 * @author Jon Brisbin (via post on tomcat-users http://markmail.org/thread/rdo3drcir75dzzrq)
 * @author Kevin Jansz
 */
public class ForceReplicationValve extends ValveBase implements Lifecycle, ClusterValve {
    private static org.apache.juli.logging.Log log =
        org.apache.juli.logging.LogFactory.getLog( ForceReplicationValve.class );

    @SuppressWarnings("hiding")
    protected static final String info = "org.apache.catalina.ha.tcp.ForceReplicationValve/1.0";

// this could be used if ForceReplicationValve messages were setup 
// in org/apache/catalina/ha/tcp/LocalStrings.properties
//    
//    /**
//     * The StringManager for this package.
//     */
//    @SuppressWarnings("hiding")
//    protected static StringManager sm =
//        StringManager.getManager(Constants.Package);

    /** 
     * Not actually required but this must implement {@link ClusterValve} to 
     * be allowed to be added to the Cluster.
     */
    private CatalinaCluster cluster = null ;

    /**
     * Also not really required, implementing {@link Lifecycle} to allow 
     * initialisation and shutdown to be logged. 
     */
    protected LifecycleSupport lifecycle = new LifecycleSupport(this);    


    /**
     * Default constructor
     */
    public ForceReplicationValve() {
        super();
        if (log.isInfoEnabled()) {
            log.info(getInfo() + ": created");
        }
    }

    @Override
    public String getInfo() {
        return info;
    }

    @Override
    public void invoke(Request request, Response response) throws IOException,
            ServletException {

        getNext().invoke(request, response);

        Session session = null;
        try {
            session = request.getSessionInternal();
        } catch (Throwable e) {
            log.error(getInfo() + ": Unable to perform replication request.", e);
        }

        String context = request.getContext().getName();
        String task = request.getPathInfo();
        if(task == null) {
            task = request.getRequestURI();
        }
        if (session != null) {
            if (log.isDebugEnabled()) {
                log.debug(getInfo() + ": [session=" + session.getId() + ", instanceof=" + session.getClass().getName() + ", context=" + context + ", request=" + task + "]");
            }
            if (session instanceof ReplicatedSession) {
                // it's a SimpleTcpReplicationManager - can just set to dirty
                ((ReplicatedSession) session).setIsDirty(true);
                if (log.isDebugEnabled()) {
                    log.debug(getInfo() + ": [session=" + session.getId() + ", context=" + context + ", request=" + task + "] maked DIRTY");
                }
            } else {
                // for everything else - cycle all attributes
                List cycledNames = new LinkedList();

                // in a cluster where the app is <distributable/> this should be
                // org.apache.catalina.ha.session.DeltaSession - implements HttpSession
                HttpSession deltaSession = (HttpSession) session;
                for (Enumeration<String> names = deltaSession.getAttributeNames(); names.hasMoreElements(); ) {
                    String name = names.nextElement();
                    deltaSession.setAttribute(name, deltaSession.getAttribute(name));

                    cycledNames.add(name);                    
                }

                if (log.isDebugEnabled()) {
                    log.debug(getInfo() + ": [session=" + session.getId() + ", context=" + context + ", request=" + task + "] cycled atrributes=" + cycledNames + "");
                }
            }
        } else {
            String id = request.getRequestedSessionId();
            log.warn(getInfo()  + ": [session=" + id + ", context=" + context + ", request=" + task + "] Session not available, unable to send session over cluster.");
        }
    }


    /* 
     * ClusterValve methods - implemented to ensure this valve is not ignored by Cluster  
     */

    public CatalinaCluster getCluster() {
        return cluster;
    }

    public void setCluster(CatalinaCluster cluster) {
        this.cluster = cluster;
    }


    /* 
     * Lifecycle methods - currently implemented just for logging startup 
     */

    /**
     * Add a lifecycle event listener to this component.
     *
     * @param listener The listener to add
     */
    public void addLifecycleListener(LifecycleListener listener) {
        lifecycle.addLifecycleListener(listener);
    }

    /**
     * Get the lifecycle listeners associated with this lifecycle. If this 
     * Lifecycle has no listeners registered, a zero-length array is returned.
     */
    public LifecycleListener[] findLifecycleListeners() {
        return lifecycle.findLifecycleListeners();
    }

    /**
     * Remove a lifecycle event listener from this component.
     *
     * @param listener The listener to remove
     */
    public void removeLifecycleListener(LifecycleListener listener) {
        lifecycle.removeLifecycleListener(listener);
    }

    public void start() throws LifecycleException {
        lifecycle.fireLifecycleEvent(START_EVENT, null);
        if (log.isInfoEnabled()) {
            log.info(getInfo() + ": started");
        }
    }

    public void stop() throws LifecycleException {
        lifecycle.fireLifecycleEvent(STOP_EVENT, null);
        if (log.isInfoEnabled()) {
            log.info(getInfo() + ": stopped");
        }
    }

}

这篇关于是否有用于Tomcat 6群集配置的useDirtyFlag选项?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆