Contents
1 Introduction
I've been experimenting with the implementation of microservices using ZeroMQ. What follows is a few notes on what I've been able to do.
I'll give examples written in both Lua and Python. The use of Lua is a bit interesting because Lua is especially useful and convenient for use as an embedded language.
Note that this code originated from the example code in the zguide - https://zguide.zeromq.org/. You can clone the zguide along with example code in multiple languages from https://github.com/imatix/zguide.git.
For similar examples in Node.js, see http://www.reifywork.com/zeromq-python-nodejs.html.
2 A simple first step - Local machine
Here is a simple server in Python - hwserver.py:
#!/usr/bin/env python
"""
synopsis:
Hello World server in Python
Binds REP socket to tcp://*:5555
Expects b"Hello" from client, replies with b"World"
"""
# import time
import zmq
def receive_requests():
"""Receive the requests."""
context = zmq.Context()
socket = context.socket(zmq.REP)
socket.bind("tcp://*:5555")
# socket.bind("tcp://10.0.1.2:5555")
count = -1
while True:
count += 1
# Wait for next request from client
message = socket.recv()
print(f"Received request: {message}")
# Do some 'work'
# time.sleep(1)
# Send reply back to client
socket.send_string(f"World {count}")
def main():
"""Main function"""
receive_requests()
if __name__ == "__main__":
main()
And, a very similar server written in Lua - hwserver.lua:
#!/usr/bin/env lua5.3
-- Hello World server
-- Binds REP socket to tcp://*:5555
-- Expects "Hello" from client, replies with "World"
--
-- Author: Robert G. Jakabosky <bobby@sharedrealm.com>
--
local zmq = require"zmq"
require"zhelpers"
local context = zmq.init(1)
-- Socket to talk to clients
local socket = context:socket(zmq.REP)
socket:bind("tcp://*:5555")
while true do
-- Wait for next request from client
local request = socket:recv()
print("Received Hello [" .. request .. "]")
-- Do some 'work'
-- s_sleep(1000)
-- Send reply back to client
socket:send("World")
end
-- We never get here but if we did, this would be how we end
socket:close()
context:term()
And, here is a simple client written in Python:
#!/usr/bin/env python
"""
synopsis:
Hello World client in Python
Connects REQ socket to tcp://localhost:5555
Sends "Hello" to server, expects "World" back
"""
import sys
import zmq
def send_requests(count):
"""Send the requests."""
context = zmq.Context()
# Socket to talk to server
print("Connecting to hello world server...")
socket = context.socket(zmq.REQ)
socket.connect("tcp://localhost:5555")
for request in range(count):
print(f"Sending request {request} ...")
socket.send_string(f"Hello {request}")
# Get the reply.
message = socket.recv()
print(f"Received reply {request} [ {message} ]")
def main():
"""Main function"""
args = sys.argv[1:]
count = 10
if len(args) == 1:
count = int(args[0])
send_requests(count)
if __name__ == "__main__":
main()
Next, a very similar client written in Lua:
#!/usr/bin/env lua
--
-- Hello World client
-- Connects REQ socket to tcp://localhost:5555
-- Sends "Hello" to server, expects "World" back
--
-- Author: Robert G. Jakabosky <bobby@sharedrealm.com>
--
local zmq = require("zmq")
local fmt = string.format
local context = zmq.init(1)
local count = arg[1] or 10
-- Socket to talk to server
print("Connecting to hello world server...")
local socket = context:socket(zmq.REQ)
socket:connect("tcp://localhost:5555")
for n = 1, count do
print("Sending Hello " .. n .. " ...")
socket:send(fmt("Hello %s", n))
local reply = socket:recv()
print("Received World " .. n .. " [" .. reply .. "]")
end
socket:close()
context:term()
3 A next, not quite so simple step - a remote machine
In order to use ZeroMQ to make requests to and receive responses from a remote machine, we will need to create an SSH tunnel. It's easy, but it's also a bit non-obvious. Here is a bash shell script and the commands that we'll use:
#!/usr/bin/bash ssh -f ec2-user@reifywork.com -L 5555:localhost:5555 -N ssh -f dkuhlman@magpie -L 5556:localhost:5556 -N
Notes:
- You will need to modify this script to reflect your access to your remote machine.
- The above bash script actually creates two (2) SSH tunnels. The first is to a remote machine at reifywork.com out on the WAN (wide area network, i.e. the big Internet) and the second is to the machine magpie on my LAN (local area network).
- In order to use the first tunnel, to reifywork.com, we'll use port 5555. And for the second, to magpie, we'll use port 5556.
- reifywork.com will respond by using port 5555. And, magpie will respond through port 5556.
- So, in this example, on the machine addressable as reifywork.com I'll implement and run a ZeroMQ server app that receives requests and sends responses through port 5555; and on the machine magpie on my LAN I'll implement and run a ZeroMQ server app that receives requests and sends responses through port 5556.
- The above script starts two processes. Use htop or your own process monitor to verify that.
- Because it creates processes, you will need to re-run that script anytime those processes are killed and you need them again. That happens, for example, when you shut down your machine.
- For this to work, you will need access (without a password, I believe) in both directions. You can use ssh-keygen to generate authentication keys for ssh. You can do a Web search for how-to information on how to generate and install the authentication key on the remote machine.