Integrating Socket.IO with Spring Boot
The core server uses the Netty-based Socket.IO server implementation for Java. The Maven deppendency is:
<dependency>
<groupId>com.corundumstudio.socketio</groupId>
<artifactId>netty-socketio</artifactId>
<version>1.7.19</version>
</dependency>
Server Configuration and Registration
The application runner configures the Socket.IO server and registers it with a service discovery mechanism.
@Component
@RequiredArgsConstructor
public class SocketServerInitializer implements CommandLineRunner, ApplicationListener<ContextClosedEvent> {
private SocketIOServer ioServer;
private final NetworkAddressResolver addressResolver;
private final ServiceRegistryManager registryManager;
@Value("${socketio.server.port:9000}")
private int serverPort;
@Bean
public SocketIOServer socketServer() {
com.corundumstudio.socketio.Configuration serverConfig = new com.corundumstudio.socketio.Configuration();
int processorCount = Runtime.getRuntime().availableProcessors();
serverConfig.setPort(serverPort);
serverConfig.setOrigin("*");
serverConfig.setBossThreads(processorCount);
serverConfig.setWorkerThreads(processorCount);
serverConfig.setMaxFramePayloadLength(1048576);
serverConfig.setMaxHttpContentLength(1048576);
ioServer = new SocketIOServer(serverConfig);
return ioServer;
}
@Override
public void run(String... args) {
ioServer.start();
registerServiceInstance();
}
@Override
public void onApplicationEvent(ContextClosedEvent event) {
if (ioServer != null) {
ioServer.stop();
}
}
private void registerServiceInstance() {
try {
String hostIp = addressResolver.getPrimaryNonLoopbackAddress();
ServiceInstance instance = new ServiceInstance();
instance.setHost(hostIp);
instance.setPort(serverPort);
instance.setServiceId("realtime-communication-service");
instance.setPriority(1.0);
registryManager.registerInstance("socket-io-cluster", instance);
} catch (RegistryException ex) {
throw new ServiceRegistrationFailedException("Failed to register Socket.IO service", ex);
}
}
}
API Gateway Routing Configuration
The Spring Cloud Gateway routes WebSocket upgrade requests to the appropriate service cluster.
spring:
cloud:
gateway:
routes:
- id: websocket_route
uri: lb://realtime-service-cluster
predicates:
- Path=/socket.io/**
Kubernetes Ingress Configuration
The Ingress resource configures Nginx to handle long-lived WebSocket connnections and large payloads.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: websocket-ingress
annotations:
nginx.ingress.kubernetes.io/proxy-body-size: "200M"
nginx.ingress.kubernetes.io/proxy-send-timeout: "3600"
nginx.ingress.kubernetes.io/proxy-read-timeout: "3600"
nginx.ingress.kubernetes.io/proxy-connect-timeout: "3600"
nginx.ingress.kubernetes.io/upstream-hash-by: "$http_x_forwarded_for"
spec:
ingressClassName: nginx
rules:
- host: app.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: realtime-service
port:
number: 9000
Frontend Nginx Configuration
The frontend web server proxies requests and handles WebSocket upgrade headers.
server {
listen 80;
server_name localhost;
location / {
root /usr/share/nginx/html;
try_files $uri $uri/ /index.html;
}
location /api/ {
proxy_pass http://backend-service/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location /socket.io/ {
proxy_pass http://backend-service;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
External Load Balancer Setup
An external reverse proxy distributes traffic to Kubernetes Ingress endpoints using IP-based session persistance.
upstream kubernetes_ingress {
ip_hash;
server 192.168.33.11:31499;
server 192.168.33.12:31499;
}
server {
listen 80;
server_name app.example.com;
location / {
proxy_pass http://kubernetes_ingress;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}