Hazelcast客户端-服务端部署示例及对象序列化相关技术问询
Hey there! Let's break down your Hazelcast questions step by step, with practical, production-ready examples to make everything clear.
Hazelcast requires all objects stored in its cache to be serializable. You have a few options, but we’ll cover the two most common and practical approaches:
1. Standard Java Serialization (Simple)
If you don’t need advanced version compatibility, just implement java.io.Serializable for your ABCD class:
import java.io.Serializable; public class ABCD implements Serializable { private static final long serialVersionUID = 1L; // Critical for versioning private String id; private String name; // Constructors, getters, setters }
2. Portable Serialization (Recommended for Version Flexibility)
For better performance and backward compatibility when modifying entity fields, use Hazelcast’s Portable serialization. This avoids breaking cache deserialization when you add/remove fields:
import com.hazelcast.nio.serialization.Portable; import com.hazelcast.nio.serialization.PortableReader; import com.hazelcast.nio.serialization.PortableWriter; import java.io.IOException; public class ABCD implements Portable { public static final int CLASS_ID = 1; public static final int FACTORY_ID = 100; private String id; private String name; // Future field: private int age; @Override public int getFactoryId() { return FACTORY_ID; } @Override public int getClassId() { return CLASS_ID; } @Override public void writePortable(PortableWriter writer) throws IOException { writer.writeUTF("id", id); writer.writeUTF("name", name); // When adding "age", just add: writer.writeInt("age", age); } @Override public void readPortable(PortableReader reader) throws IOException { id = reader.readUTF("id"); name = reader.readUTF("name"); // Handle backward compatibility with a default value age = reader.readInt("age", 0); } // Constructors, getters, setters }
Register the Portable Factory in your server’s hazelcast.xml:
<hazelcast> <serialization> <portable-version>1</portable-version> <portable-factories> <portable-factory factory-id="100">com.yourpackage.ABCDFactory</portable-factory> </portable-factories> </serialization> </hazelcast>
And the factory class:
import com.hazelcast.nio.serialization.Portable; import com.hazelcast.nio.serialization.PortableFactory; public class ABCDFactory implements PortableFactory { @Override public Portable create(int classId) { if (classId == ABCD.CLASS_ID) return new ABCD(); return null; } }
Let’s set up a basic standalone Hazelcast server paired with a Java Web client (using Spring Boot for simplicity):
Server Setup (Standalone Node)
- Download the latest stable Hazelcast distribution and unzip it.
- Package your
ABCDclass andABCDFactoryinto a JAR, then place it in the server’slibfolder. - Update
hazelcast.xmlwith the Portable factory config above. - Start the server: run
bin/hz start(orstart.sh/start.batdepending on your OS).
Java Web Client Setup
- Add Hazelcast dependencies to your
pom.xml(Maven):
<dependency> <groupId>com.hazelcast</groupId> <artifactId>hazelcast</artifactId> <version>5.3.6</version> <!-- Use latest stable version --> </dependency> <dependency> <groupId>com.hazelcast</groupId> <artifactId>hazelcast-spring</artifactId> <version>5.3.6</version> </dependency>
- Configure the client in
application.properties:
hazelcast.client.config=classpath:hazelcast-client.xml
- Create
hazelcast-client.xml:
<hazelcast-client> <cluster-name>dev</cluster-name> <network> <cluster-members> <address>127.0.0.1:5701</address> </cluster-members> </network> <serialization> <portable-version>1</portable-version> <portable-factories> <portable-factory factory-id="100">com.yourpackage.ABCDFactory</portable-factory> </portable-factories> </serialization> </hazelcast-client>
- Use the cache in a web controller:
import com.hazelcast.core.HazelcastInstance; import com.hazelcast.map.IMap; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; @RestController public class CacheController { private final IMap<String, ABCD> abcdCache; // Inject Hazelcast client instance public CacheController(HazelcastInstance hazelcastInstance) { this.abcdCache = hazelcastInstance.getMap("abcd-cache"); } @GetMapping("/cache/abcd/{id}") public ABCD getOrCacheABCD(@PathVariable String id) { // Check cache first ABCD abcd = abcdCache.get(id); if (abcd == null) { // Fetch from database/service abcd = new ABCD(id, "Sample Object"); // Store in cache abcdCache.put(id, abcd); } return abcd; } }
Yes, in almost all production scenarios:
- For standard Java serialization: The server needs the
ABCDclass to deserialize bytes sent from the client into valid objects. - For Portable/IdentifiedDataSerializable: The server still needs the
ABCDclass and its factory to create instances during deserialization.
The only exception is if you use Hazelcast’s cloud-managed service with specific dynamic class loading, but this is not typical for on-prem deployments.
Deployment Mechanism for ABCD on the Server
- Standalone nodes: Package
ABCDinto a JAR and copy it to thelibfolder of every Hazelcast server node. Restart the nodes to load the class. - Embedded Hazelcast (server runs in your app): Include the
ABCDclass in your app’s classpath (e.g., part of your WAR file).
This depends entirely on your serialization strategy:
Standard Java Serialization
- If you modify fields without updating
serialVersionUID: You’ll getInvalidClassExceptionwhen the server tries to deserialize old cache objects into the new class structure. - If you update
serialVersionUID: Old cached objects become unreadable. You’ll need to clear the cache or handle the exception explicitly.
Portable Serialization (Recommended)
- Adding fields: Old objects will load with default values for new fields (e.g.,
0forint), and new objects will work normally. Increment theportable-versionin config to track changes. - Removing fields: The server ignores missing fields during deserialization—no exceptions are thrown.
- Changing field types: This is risky. You’ll need to add manual type conversion logic in
readPortableto avoidIOException.
User Code Deployment lets you push your ABCD class from the client to the server automatically, so you don’t have to manually copy JARs to each node. Here’s how to set it up:
Server Config (hazelcast.xml)
<hazelcast> <user-code-deployment enabled="true"> <provider-mode>LOCAL_AND_CLIENTS</provider-mode> <!-- Allow clients to deploy code --> <class-cache-mode>ETERNAL</class-cache-mode> <!-- Keep classes loaded permanently --> </user-code-deployment> <serialization> <portable-version>1</portable-version> </serialization> </hazelcast>
Client Config (hazelcast-client.xml)
<hazelcast-client> <cluster-name>dev</cluster-name> <network> <cluster-members> <address>127.0.0.1:5701</address> </cluster-members> </network> <user-code-deployment enabled="true"> <!-- Deploy a JAR containing your classes --> <jar-paths> <jar-path>file:/path/to/your/abcd-entities.jar</jar-path> </jar-paths> <!-- Or deploy individual classes --> <class-names> <class-name>com.yourpackage.ABCD</class-name> <class-name>com.yourpackage.ABCDFactory</class-name> </class-names> </user-code-deployment> <serialization> <portable-version>1</portable-version> <portable-factories> <portable-factory factory-id="100">com.yourpackage.ABCDFactory</portable-factory> </portable-factories> </serialization> </hazelcast-client>
How It Works
When the client connects, it sends the specified classes/JARs to the server. The server loads these into its classpath, enabling it to serialize/deserialize ABCD objects without manual JAR deployments.
Important Security Note: User Code Deployment is disabled by default. Only enable it if you trust all clients connecting to your cluster, as it allows remote code execution. You can restrict access using Hazelcast’s security permissions.
内容的提问来源于stack exchange,提问作者Kalpesh Soni

