Achieve WebSocket Load Balancing Across Microservice Instances with a Single Annotation
This article explains how to solve the WebSocket message delivery problem in microservice architectures by using a lightweight library that provides an @EnableWebSocketLoadBalanceConcept annotation, detailing its design, connection management, message routing, and customizable selectors for targeted delivery.
Introduction
WebSocket works in monolithic apps, but in a microservice architecture a client connected to one instance may miss messages broadcast by another instance. Example: service A has instances A1 and A2; a client routed to A1 will not receive messages sent by A2.
The library forwards messages between instances so that any instance can deliver messages to all connected clients with a single configuration annotation.
Repository: https://github.com/Linyuzai/concept/wiki/Concept-WebSocket-LoadBalance
Usage
Add the annotation @EnableWebSocketLoadBalanceConcept together with @EnableDiscoveryClient and @SpringBootApplication on the Spring Boot main class:
@EnableWebSocketLoadBalanceConcept
@EnableDiscoveryClient
@SpringBootApplication
public class AServiceApplication {
public static void main(String[] args) {
SpringApplication.run(AServiceApplication.class, args);
}
}Inject WebSocketLoadBalanceConcept where messages need to be sent:
@RestController
@RequestMapping("/ws")
public class WsController {
@Autowired
private WebSocketLoadBalanceConcept concept;
@RequestMapping("/send")
public void send(@RequestParam String msg) {
concept.send(msg);
}
}Abstract Design
The problem is modeled as a “long‑connection cluster”. Both WebSocket and TCP are treated as long‑connection protocols. A top‑level Connection interface is defined with concrete implementations such as WebSocketConnection and TCPConnection. Short‑lived protocols can also be wrapped if needed.
Forwarding Strategy
Each service instance opens client connections to the server endpoints of all other instances (WebSocket client to other WebSocket servers, TCP client to other TCP servers). When an instance receives a message, it forwards the message through these pseudo‑client connections, and the remote instance delivers it to its real clients.
Connection Establishment
Service discovery (Eureka, Nacos, etc.) provides the list of peer instances. Using DiscoveryClient#getInstances(serviceId), the library obtains all instances except itself and initiates connections. After a connection is established, each side exchanges its instance information to create the reciprocal connection, guaranteeing bidirectional links.
Heartbeat detection and automatic reconnection are built in: missed heartbeats close the connection, and the library periodically re‑queries the registry to reconnect missing peers.
Connection Management
Connections are classified into real client connections and forwarding connections. A ConnectionFactory adapts any concrete connection into a unified Connection object. Each connection is paired with a MessageEncoder and MessageDecoder. MessageCodecAdapter allows custom codecs for different connection types.
Message Sending and Selection
When a message is sent, a ConnectionSelector determines which connections should receive it. Custom selectors can implement precise routing similar to Ribbon’s IRule.
Two built‑in selectors are provided:
UserSelector : Sends a message only to connections whose metadata contains a matching userId header.
PathSelector : Routes messages based on a topic‑like path stored in connection metadata and message header.
Metadata and headers are simple key‑value maps, making it easy to extend the routing logic.
Conclusion
The library abstracts long‑connection clustering, manages peer connections, and provides flexible message routing with minimal configuration. By leveraging Spring Cloud discovery and a few annotations, developers can achieve transparent WebSocket load balancing across multiple service instances.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Java Architect Essentials
Committed to sharing quality articles and tutorials to help Java programmers progress from junior to mid-level to senior architect. We curate high-quality learning resources, interview questions, videos, and projects from across the internet to help you systematically improve your Java architecture skills. Follow and reply '1024' to get Java programming resources. Learn together, grow together.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
