当前位置: 首页 > 工具软件 > Hazelcast > 使用案例 >

SpringCloud集成hazelcast分布式缓存

子车高歌
2023-12-01

1.hazelcast配置

关于hazelcast是什么应该不用细说了,如果不太明白,百度一下,大概都能知道,下面直接说使用,hazelcast-demo地址:https://github.com/chkui/hazelcast-demo(转载,不是我写的)由于我只使用到了map类型,所以这里只写map的配置

simple-config.xml配置

<?xml version="1.0" encoding="UTF-8"?>
<hazelcast
	xsi:schemaLocation="http://www.hazelcast.com/schema/config hazelcast-config-3.6.xsd"
	xmlns="http://www.hazelcast.com/schema/config" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
	<group>
		<name>default</name>
		<password>default</password>
	</group>
	<management-center enabled="false">http://localhost:8080/mancenter
	</management-center>
	<network>
		<port auto-increment="true" port-count="110">7701</port>
		<outbound-ports>
			<ports>0</ports>
		</outbound-ports>
		<join>
			<multicast enabled="true">
				<multicast-group>224.2.2.3</multicast-group>
				<multicast-port>54327</multicast-port>
			</multicast>
			<!-- TCP/IP协议 -->
			<tcp-ip enabled="false">
			</tcp-ip>
		</join>
	</network>
	<partition-group enabled="false" />
	<executor-service name="default">
		<pool-size>16</pool-size>
		<queue-capacity>0</queue-capacity>
	</executor-service>
	<map name="demo.config">
		<backup-count>2</backup-count>
		<time-to-live-seconds>604800</time-to-live-seconds>
		<max-idle-seconds>1800</max-idle-seconds>
		<eviction-policy>LFU</eviction-policy>
		<max-size policy="USED_HEAP_SIZE ">20</max-size>
		<eviction-percentage>25</eviction-percentage>
		<merge-policy>com.hazelcast.map.merge.LatestUpdateMapMergePolicy
		</merge-policy>
		<entry-listeners>
			<entry-listener>com.palm.vert.cluster.listener.ClusterCacheListener</entry-listener>
		</entry-listeners>
	</map>
</hazelcast>

package org.palm.hazelcast.config;

import java.util.Map;

import com.hazelcast.config.ClasspathXmlConfig;
import com.hazelcast.config.Config;
import com.hazelcast.config.MapConfig;
import com.hazelcast.config.NetworkConfig;
import com.hazelcast.core.Hazelcast;
import com.hazelcast.core.HazelcastInstance;

/**
 * 展示如何读取和引入配置
 * 
 * @author chkui
 */
public class HazelcastConfigSimple {
	public static void main(String[] args) {
		// 从classpath加载配置文件
		Config config = new ClasspathXmlConfig("xmlconfig/simple-config.xml");
		// 获取网络配置
		NetworkConfig netConfig = config.getNetworkConfig();
		// 获取用户定义的map配置
		MapConfig mapConfigXml = config.getMapConfig("demo.config");
		// 获取系统默认的map配置
		MapConfig mapConfigDefault = config.getMapConfig("default");
		// 输出集群监听的起始端口号
		System.out.println("Current port:" + netConfig.getPort());
		// 输出监听端口的累加号
		System.out.println("Current port count:" + netConfig.getPortCount());
		// 输出自定义map的备份副本个数
		System.out.println("Config map backup count:" + mapConfigXml.getBackupCount());
		// 输出默认map的备份副本个数
		System.out.println("Default map backup count:" + mapConfigDefault.getBackupCount());

		// 测试创建Hazelcast实例并读写测试数据
		HazelcastInstance instance1 = Hazelcast.newHazelcastInstance(config);
		HazelcastInstance instance2 = Hazelcast.newHazelcastInstance(config);

		Map<Integer, String> defaultMap1 = instance1.getMap("defaultMap");
		defaultMap1.put(1, "testMap");
		Map<Integer, String> configMap1 = instance1.getMap("configMap");
		configMap1.put(1, "configMap");

		Map<Integer, String> testMap2 = instance2.getMap("defaultMap");
		System.out.println("Default map value:" + testMap2.get(1));
		Map<Integer, String> configMap2 = instance2.getMap("configMap");
		System.out.println("Config map value:" + configMap2.get(1));
	}
}

配置中具体参数定义可以在这个文档中查询:https://docs.hazelcast.org/docs/3.5/manual/html-single/hazelcast-documentation.html#preface
以上是demo中的的样例,由于我不喜欢xml配置,改用了java配置,代码为

	@Autowired
    private DiscoveryClient discoveryClient;

    private Config hazelCastConfig() {
        List<ServiceInstance> instances = discoveryClient.getInstances(applicationName);
        List<String> memberList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(instances)) {
            List<String> hostList = instances.stream().map(ServiceInstance::getHost).collect(Collectors.toList());
            memberList = hostList;
        }
        Config config = new Config();
        NetworkConfig networkConfig = new NetworkConfig();
        networkConfig.setInterfaces(new InterfacesConfig().setInterfaces(memberList));
        networkConfig.setPort(20400);
        networkConfig.setPortAutoIncrement(true);
        networkConfig.setPortCount(100);
        networkConfig.setOutboundPorts(Collections.singletonList(0));
        networkConfig.setJoin(new JoinConfig()
                .setMulticastConfig(new MulticastConfig().setEnabled(false))
                .setTcpIpConfig(new TcpIpConfig().setEnabled(true).setMembers(memberList).setRequiredMember(null).setConnectionTimeoutSeconds(5)));
        Map<String, ExecutorConfig> map = new HashMap<>();
        map.put("default", new ExecutorConfig().setPoolSize(16).setQueueCapacity(0));
        List<EntryListenerConfig> entryListenerConfigList = new ArrayList<>();
        EntryListenerConfig entryListenerConfig = new EntryListenerConfig();
        entryListenerConfig.setClassName("com.palm.vert.cluster.listener.ClusterCacheListener");
        entryListenerConfigList.add(entryListenerConfig);
        config.setInstanceName("hazelcast-instance")
                .addMapConfig(new MapConfig().setName("configuration").setMaxSizeConfig(new MaxSizeConfig(200,
                        MaxSizeConfig.MaxSizePolicy.FREE_HEAP_SIZE)).setEvictionPolicy(EvictionPolicy.LFU)
                        .setTimeToLiveSeconds(-1).setMergePolicy("com.hazelcast.map.merge.LatestUpdateMapMergePolicy").setEntryListenerConfigs(entryListenerConfigList))
                .setManagementCenterConfig(new ManagementCenterConfig().setEnabled(false))
                .setGroupConfig(new GroupConfig().setName("default").setPassword("default"))
                .setNetworkConfig(networkConfig)
                .setPartitionGroupConfig(new PartitionGroupConfig().setEnabled(false))
                .setExecutorConfigs(map);
        return config;

    }


    private HazelcastInstance hazelcastInstance() {
        //创建分布式缓存节点
        HazelcastInstance instance = Hazelcast.newHazelcastInstance(hazelCastConfig());
        return instance;
    }

    // 这里用懒加载是为了确保调用hazelCastConfig()方法时,其他节点的服务已经启动,能够获取其他节点ip,这样才能组建集群,如果其他节点没启动,集群无法形成
    @Lazy
    @Bean
    public IMap<String, Object> cacheMap() {
        System.out.println("hazelcast实例创建");
        HazelcastInstance instance = hazelcastInstance();
        //一级分类缓存
        IMap<String, Object> cacheMap = instance.getMap("openapicache");
        return cacheMap;
    }

使用过程中遇到了2个问题
1.我的服务部署在阿里云服务器上,查询发现阿里云服务器不支持multicast组播协议(未确认真假,只是很多文档说的,阿里云之前的文档也说不支持,但是有办法解决,不知道我用这个的时候支持了没),所以我选用了tcp/ip协议配置
2.tcp/ip协议需要配置服务节点的ip地址,但是由有2个问题:
1)我的服务节点数量并不是完全不变的,有时候可能为了分摊请求压力扩容,或者服务不忙时缩容,
2)阿里云每次部署时,服务节点的ip都会变,无法获取固定的ip地址
解决办法:
我们是springcloud工程,用的是nacos注册中心,使用DiscoveryClient可以获取服务节点的ip地址:

List<ServiceInstance> instances = discoveryClient.getInstances(applicationName);
List<String> memberList = new ArrayList<>();
if (CollectionUtils.isNotEmpty(instances)) {
    List<String> hostList = instances.stream().map(ServiceInstance::getHost).collect(Collectors.toList());
    memberList = hostList;
}

但是需要服务启动之后才能获取的到,springcloud的注册行为是发生在spring容器启动之后,所以不能在springboot启动过程中实例化hazelcast,所以我将hazelcast的实例化设置了懒加载,当有请求进入时才会实例化hazelcast,这里又有一个注意点,懒加载需要在@Bean上加@Lazy注解,但是测试发现无效,这是因为,hazelcast在业务中已经被@Autowired了,所以需要在所有引用hazelcast的@Autowired上也加上@Lazy注解。

 类似资料: