配置类
package com.ruimin.ifs.boot.config;
import lombok.Data;
import org.apache.catalina.Engine;
import org.apache.catalina.ha.session.DeltaManager;
import org.apache.catalina.ha.tcp.SimpleTcpCluster;
import org.apache.catalina.tribes.group.GroupChannel;
import org.apache.catalina.tribes.group.interceptors.MessageDispatchInterceptor;
import org.apache.catalina.tribes.group.interceptors.StaticMembershipInterceptor;
import org.apache.catalina.tribes.group.interceptors.TcpFailureDetector;
import org.apache.catalina.tribes.membership.StaticMember;
import org.apache.catalina.tribes.transport.nio.NioReceiver;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.context.annotation.Configuration;
@Data
@Configuration
@ConfigurationProperties("cluster")
public class TomcatClusterContextCustomizer implements WebServerFactoryCustomizer<TomcatServletWebServerFactory> {
private Boolean enable = false;
/**
* 接收配置 本地服务器的配置
*/
private ReceiverConfig receiver = new ReceiverConfig();
/**
* 集群成员不包括自己
*/
private MemberConfig[] member = new MemberConfig[0];
@Override
public void customize(TomcatServletWebServerFactory factory) {
if (enable) {
factory.addContextCustomizers(context -> {
configureCluster((Engine) context.getParent().getParent());
context.setManager(new DeltaManager());
context.setDistributable(true);
});
}
}
private void configureCluster(Engine engine) {
SimpleTcpCluster cluster = new SimpleTcpCluster();
GroupChannel groupChannel = new GroupChannel();
cluster.setChannel(groupChannel);
NioReceiver nioReceiver = new NioReceiver();
nioReceiver.setPort(receiver.getPort());
nioReceiver.setAddress(receiver.getAddress());
groupChannel.setChannelReceiver(nioReceiver);
StaticMembershipInterceptor staticMembershipInterceptor = getStaticMembershipService();
groupChannel.addInterceptor(new TcpFailureDetector());
groupChannel.addInterceptor(staticMembershipInterceptor);
groupChannel.addInterceptor(new MessageDispatchInterceptor());
engine.setCluster(cluster);
}
private StaticMembershipInterceptor getStaticMembershipService() {
StaticMembershipInterceptor staticMembershipInterceptor = new StaticMembershipInterceptor();
for (MemberConfig memberConfig : member) {
StaticMember staticMember = new StaticMember();
staticMember.setUniqueId(memberConfig.getId());
staticMember.setHost(memberConfig.getHost());
staticMember.setPort(memberConfig.getPort());
staticMember.setLocal(memberConfig.getLocal());
staticMembershipInterceptor.addStaticMember(staticMember);
}
return staticMembershipInterceptor;
}
/**
* 成员配置
*
*/
@Data
public static class MemberConfig {
/**
* id 必须是16位byte数组
*/
private String id;
/**
* 集群成员的接收配置中的address
*/
private String host;
/**
* 集群成员的接收配置中的port
*/
private Integer port;
/**
* 集群成员是否在本机中
*/
private Boolean local = false;
}
/**
* 接收配置
*
*/
@Data
public static class ReceiverConfig {
/**
* 接收地址
*/
private String address = "auto";
/**
* 端口
*/
private Integer port = 4000;
}
}
yml配置
#session共享
cluster:
enable: false
# receiver 保持默认即可 端口可以修改
# receiver:
# port: 4000
# address: "auto"
member:
# 必须是16位的byte数组
- id: '{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}'
host: 172.20.10.2
port: 4000
# 是否是本地成员
# local: true