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