Permalink
Browse files

Add example of running multiple zerogw on single socket/port/fd

  • Loading branch information...
tailhook committed Aug 19, 2012
1 parent 37a4f56 commit 96a941c2cef76966866881aacd713c1ce2f33fa2
@@ -13,6 +13,14 @@ Which runs multiple processes of python and zerogw, to show how it could be
scaled. But you need to turn sockets into tcp ones to scale it to multiple
machines, and also fix redis config which is awfully slow for testing purposes.
+There is also::
+
+ ./single_socket.sh
+
+Which is merely same as ``scale.sh``, but running multiple zerogw instances
+on single port.
+
+
You can also find this chat online at http://tabbedchat.zerogw.com
@@ -0,0 +1,34 @@
+#!/usr/bin/env python3
+
+"""
+This script is intended to run multiple zerogw instances with single shared
+port/socket. This works by creating a socket externally, and pasing it as
+a file descriptor to all zerogw instances, during exec.
+
+You must configure zerogw to use the file descriptor to run correctly
+(example zerogw_fd.yaml does this)
+"""
+
+import socket
+import os
+import sys
+
+# Let's open shared socket
+zgwsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+zgwsock.bind(('0.0.0.0', 8000))
+zgwsock.listen(100000)
+zgwsock.setblocking(False) # Crucial for zerogw with older libwebsite
+
+# Now make it file descriptor zero
+os.dup2(zgwsock.fileno(), 0)
+
+# Now close old socket (we have dup as fd zero)
+zgwsock.close()
+
+# Each zerogw has it's own socket directory, so we use pass directory
+# names as arguments and create a zerogw instance per directory
+for dir in sys.argv[1:]:
+ if dir != sys.argv[-1]: # last instance is our process, no more forks
+ if os.fork(): # parent continues to fork processes
+ continue
+ os.execlp('zerogw', 'zerogw', '-c', 'zerogw_fd.yaml', '-Ddir=' + dir)
@@ -0,0 +1,51 @@
+#!/bin/sh
+
+# Setting up signal handlers
+# All this code is needed to do not leave dangling children
+killchildren() {
+ if [ "x$(jobs)" == "x" ]; then
+ exit 0
+ fi
+ trap killchildren 0 1 2 3 15
+ kill $(jobs -p) 2>/dev/null
+}
+trap killchildren 0 1 2 3 15
+
+# running several redis instances is given as exercise for the reader
+# basically you just need more python code for that
+redis-server redis.conf &
+
+# We provide each zerogw instance a separate directory for zeromq sockets
+# because zeromq sockets are bound, but use special startup script for
+# running them on single port
+mkdir -p ./run/z{1,2,3} 2> /dev/null
+# passing three dirs means start three zerogw instances one per dir
+python single_port_zerogw.py ./run/z1 ./run/z2 ./run/z3 &
+
+# because of zeromq features, and because we are using bind sockets in zerogw
+# side (which is most useful use case), we can run any number of backends
+# with equal configuration
+# BTW, storing data in redis also helps
+for i in $(seq 0 4); do
+ python3 -m tabbedchat \
+ --auth-connect "ipc://./run/z1/auth.sock" \
+ --auth-connect "ipc://./run/z2/auth.sock" \
+ --auth-connect "ipc://./run/z3/auth.sock" \
+ --chat-connect "ipc://./run/z1/chat.sock" \
+ --chat-connect "ipc://./run/z2/chat.sock" \
+ --chat-connect "ipc://./run/z3/chat.sock" \
+ --output-connect "ipc://./run/z1/output.sock" \
+ --output-connect "ipc://./run/z2/output.sock" \
+ --output-connect "ipc://./run/z3/output.sock" \
+ &
+done
+
+echo "========================================================================"
+echo "You can now browse:"
+echo " http://localhost:8000/"
+echo "Depending on your luck you will hit different zerogw instance each time"
+echo "NOTE: Long polling (websocket fallback) doesn't work correctly"
+echo "WARNING: Danging zerogw processes may exist after stopping"
+echo "========================================================================"
+
+while ! wait; do true; done;
@@ -0,0 +1,56 @@
+# This is example of configuration file with listening socket passed by
+# file descriptor. It's useful to bind to port 80 either using openport or
+# using procboss, and to run multiple instances of zerogw on single port
+# (see single_socket.sh)
+
+# Zerogw's configuration library allows you to override variables
+# from a command line, so we create one, to be able to override port and socket
+# directory. See ./scale.sh for example of how to use it
+# (we use yaml anchors and $-style variables interchangeably with coyaml)
+_dir: &dir ./run
+
+Server:
+ zmq-io-threads: 1
+ disk-io-threads: 1
+ listen:
+ - host: 0.0.0.0
+ port: 8000
+ fd: 0 # File descriptor number zero is used instead of host/port
+ control:
+ socket:
+ - !zmq.Bind ipc://$dir/zerogw-ctl
+ error-log:
+ level: 3
+ warning-timeout: 300
+ filename: ./run/error.log
+
+Routing:
+ routing: !Prefix ~
+ routing-by: !Uri ~
+ map:
+ "/":
+ static:
+ enabled: yes
+ root: ./public
+ restrict-root: no # bad for production
+ index-file: index.html
+ "/ws*":
+ websocket:
+ enabled: yes
+ forward: !zmq.Push
+ - !zmq.Bind "ipc://$dir/auth.sock"
+ named-outputs:
+ chat: !zmq.Push
+ sync-interval: 10 # too low, for example purposes
+ =:
+ - !zmq.Bind "ipc://$dir/chat.sock"
+ subscribe: !zmq.Pull
+ - !zmq.Bind "ipc://$dir/output.sock"
+ children:
+ - match:
+ - "/js/*"
+ - "/css/*"
+ static:
+ enabled: yes
+ root: ./public
+ restrict-root: no # bad for production

0 comments on commit 96a941c

Please sign in to comment.