gpt4 book ai didi

java - Tomcat 6 集群配置是否有 useDirtyFlag 选项?

转载 作者:塔克拉玛干 更新时间:2023-11-01 22:57:43 25 4
gpt4 key购买 nike

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

<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 中的注释表明这可用于进行以下工作:

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

即更改已已放入 session 的对象的状态,您可以确保该对象仍被复制到集群中的其他节点。

根据 Tomcat 6 文档,您只有两个“管理器”选项 - DeltaManager 和 BackupManager ... 这些似乎都不允许使用此选项或类似选项。在我测试默认设置时:

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

在默认情况下您获得 DeltaManager 的地方,它的行为肯定与 useDirtyFlag="true"相同(如我所料)。

所以我的问题是 - Tomcat 6 中是否有等效项?

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

最佳答案

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

  1. 没有与 useDirtyFlag 等效的方法,如果您在 session 中放置可变(即更改)对象,则需要自定义编码解决方案。
  2. Tomcat ClusterValve 似乎是该解决方案的一个有效位置 - 插入集群机制,操作属性以使其在 DeltaManager 看来 session 中的所有属性都已更改。这会强制复制整个 session 。

第 1 步:编写 ForceReplicationValve(扩展 ValveBase 实现 ClusterValve)

我不会包含整个类,但会包含逻辑的关键部分(去掉日志记录和 instanceof 检查):

@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 中)

<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>

session 复制到所有集群节点现在将在每次请求后发生。

旁白:注意 channelSendOptions 设置。这取代了 Tomcat 5.0.x 中的 replicationMode=asynchronous/synchronous/pooled。查看cluster documentation对于可能的 int 值。

附录:根据要求提供完整的 Valve 资源

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");
}
}

}

关于java - Tomcat 6 集群配置是否有 useDirtyFlag 选项?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2680958/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com