Backend Development 10 min read

Design and Implementation of a Unified WebSocket Communication Service for Backend Systems

This article describes the background, objectives, core design, reliability mechanisms, message classification, API design, and unified calling approach of a company‑wide WebSocket abstraction layer that replaces polling, supports asynchronous communication, and ensures reliable message delivery using RabbitMQ and confirm mechanisms.

Code Ape Tech Column
Code Ape Tech Column
Code Ape Tech Column
Design and Implementation of a Unified WebSocket Communication Service for Backend Systems

1. Background

The company previously had many backend services that directly interacted with frontend web code, resulting in tightly coupled code and the need to re‑integrate WebSocket for new business scenarios, which consumed a lot of time and effort. Therefore, WebSocket (ws) is abstracted into an internal communication service to address various business needs such as:

Polling to obtain asynchronous results (payment callbacks, business orders).

Some features already use push (QR code refresh, charging port refresh).

Improving response speed by converting synchronous calls to asynchronous, pushing results via WebSocket to reduce latency.

Future business may require WebSocket‑based instant communication.

2. Goals

Standardize the ws communication project structure and coding style.

Separate business logic to improve integration efficiency.

Replace unreasonable polling with push notifications.

Support converting existing synchronous calls to asynchronous, delivering results through ws to improve overall system responsiveness.

Use MQ instead of Redis pub/sub and micro‑service calls.

Core Design

Project Structure

3. Business Process

3.1 Application Relationship Diagram

Message Push (Fanout)

Message Receiving & Processing (Topic)

3.2 Business Sequence Diagram

From top to bottom:

WebSocket client registration and connection flow.

Push message to server flow.

Push message to client flow.

4. Ensuring Reliable Message Transmission

During architecture design, guaranteeing that messages are not lost is a key technical challenge. For RabbitMQ, three typical loss scenarios are:

The producer loses the message while sending to the RabbitMQ server.

The server crashes before persisting the message.

The consumer crashes after receiving the message but before processing it, causing RabbitMQ to consider the message consumed.

✔ Ensure producer‑side reliability (two methods):

Method 1: Enable transaction mechanism. The producer starts a RabbitMQ transaction before sending; if the message is not successfully received, an exception is thrown and the transaction can be rolled back with channel.txRollback() , then retry.

Method 2: Enable publisher confirm mechanism. RabbitMQ returns an ACK if the message reaches the server, otherwise a NACK is returned, allowing the producer to retry.

Analysis of pros and cons: Transactions are synchronous and block the thread, while confirms are asynchronous and allow higher throughput; therefore confirms are generally preferred for reliable delivery.

✔ How the MQ server prevents loss

Enable message persistence so that messages are written to disk; after a server restart, persisted messages are recovered.

✔ Ensure consumer‑side reliability

Disable automatic ACK and enable manual acknowledgment ( consumer ack ). The consumer acknowledges only after business logic completes; if it crashes before ACK, RabbitMQ will re‑queue the message for another consumer, preventing loss.

5. Message Classification

5.1 Client → Server

Description

Clients actively push messages to the server, triggering business processes.

Examples: QR code scan refresh, user‑initiated refresh.

5.2 Server → Client

Description

The server pushes results to a client after an event occurs.

Examples: Payment completion callbacks.

5.3 Client → Client

Description

One client pushes a message to another client.

Examples: C‑end user sends a request, response is pushed to the user’s H5 page.

6. WebSocket API Design

6.1 Request WebSocket Connection Token

Method: GET

Unified request URL:

domain/xxx/websocket/token

{
  "result": 0,
  "description": "无",
  "data": "wss://dws.test.com:8086/socket/asrwqgvsd" // connection URL
}

6.2 Connect to WebSocket Using Returned URL

Connection scheme: wss

Connection URL:

wss://dws.test.com:8086/socket/{token}

7. Unified Message Body

{
  "sendType":"",
  "messageType":"消息类型",
  "businessType":"",
  "fromUniqueId":"发送端唯一id",
  "toUniqueId":"接收端唯一id",
  "fromClientType":"发送端类型",
  "toClientType":"接收端类型",
  "timestamp":0,
  "content":"业务数据",
  "tags":[
    "标签集"
  ],
  "businesses":[
    "业务集"
  ]
}

8. Unified Call Method

8.1 WebSocket API Aggregation Wrapper

8.2 Business Unified Call

Conclusion

This article records the overall design ideas of abstracting and encapsulating WebSocket to achieve instant messaging. By applying DDD modeling, code coupling is reduced, and different business units can use ws communication “plug‑and‑play” without worrying about low‑level configuration and logic.

backend architectureWebSocketMessage QueueRabbitMQReliabilityAsynchronous Communication
Code Ape Tech Column
Written by

Code Ape Tech Column

Former Ant Group P8 engineer, pure technologist, sharing full‑stack Java, job interview and career advice through a column. Site: java-family.cn

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.