Scaling real-time servers with NATS (Part 2)

Scaling real-time servers with NATS (Part 2)

Real time without hustle

ยท

3 min read

Cover image from github.com/MariaLetta/free-gophers-pack

๐Ÿ‘‰๐Ÿป Read part 1 here


With the latest release of NATS 2.2, it supports websocket, we will refactor our code to completely remove own implementation of websocket server

Setup

Upgrade/install NATS, and begin to refactor

Complete source code available at the scaling-ws on solution-nats-ws-part2 branch

Refactor

Enable websocket support on NATS server

Create a config file, nats.conf, and write the following value to enable websocket

websocket {
 # using port 5000
 listen: "0.0.0.0:5000"
 # For test environments, you can disable the need for TLS
 no_tls: true
 same_origin: false
}

Full config available option can be found here

Start NATS with config file

 $ nats-server -c nats.conf

Starting nats-server
Version:  2.2.5
Git:      [not set]
Name:     NAHVXR2PJK7EVJCZEKFVZ67UCUG7LV75574SVAYJKYNZKDHMNOYNJYDE
ID:       NAHVXR2PJK7EVJCZEKFVZ67UCUG7LV75574SVAYJKYNZKDHMNOYNJYDE
[INF] Using configuration file: nats.conf
[INF] Listening for websocket clients on ws://0.0.0.0:5000
WRN] Websocket not configured with TLS. DO NOT USE IN PRODUCTION!
[INF] Listening for client connections on 0.0.0.0:4222
[INF] Server is ready

Now, we can connect NATS from ws://0.0.0.0:5000

install NATS ws client

npm install nats.ws

Connect Subscribe to NATS on client side

import { connect, StringCodec } from 'nats.ws/nats.cjs'

const nc = await connect({servers: 'ws://127.0.0.1:5000'});
console.log(nc.status());
const sc = StringCodec();
const sub = nc.subscribe('com.scaling-ws.updates')
 void await (async () => {
      for await (const m of sub) {
        this.messages.push(sc.decode(m.data));
        console.log(`[${sub.getProcessed()}]: ${sc.decode(m.data)}`);
     }
      console.log("subscription closed");
 })();

Remove websocket server

Remove all the websocket code from internal directory and its usage at main.go

View the code difference

View the comparison after refactor on Github

Run the solution

Checkout to solution-nats-ws-part2 branch, close all terminal that run Go code and start new terminal

# start nats-server
# make sure it is installed
# nats-server version
# nats-server: v2.2.5
nats-server -c nats.conf


# open another terminal
cd web
npm i && npm run serve

# open another terminal
# start api server
make start-api

Monitor the subscription

NATS has release a command line tool natscli for ease of management, more info from here

Use natscli to subscribe to a subject for debugging purpose

nats sub com.scaling-ws.updates

Open up localhost:8080 on browser, click on the button, should see messages prompting on terminal and browser.

image.png

Overview architecture

image.png The refactored architecture would look something like this. This is much simpler compared to part 1 solution

Conclusion

Handling and scaling real-time servers can be very troublesome. By offloading the complexity to NATS, we can have a simpler architecture and yet achieving our goals. Please do note that the post only to demonstrate the idea, do not directly use it in production, as security features are not being discussed here.

Feel free to comment below if you have any suggestions. Thanks for reading ๐Ÿป

Complete source code available at the scaling-ws on solution-nats-ws-part2 branch

Did you find this article valuable?

Support Wei Lun by becoming a sponsor. Any amount is appreciated!