alltogether.py
from __future__ import print_function
import threading
import time
import zmq
NBR_CLIENTS = 10
NBR_WORKERS = 3
def worker_thread(worker_url, context, i):
""" Worker using REQ socket to do LRU routing """
socket = context.socket(zmq.REQ)
# Set the worker identity
socket.identity = (u"Worker-%d" % (i)).encode('ascii')
socket.connect(worker_url)
# Tell the borker we are ready for work
socket.send(b"READY")
try:
while True:
address = socket.recv()
empty = socket.recv()
request = socket.recv()
print("%s: %s\n" % (socket.identity.decode('ascii'), request.decode('ascii')), end='')
socket.send(address, zmq.SNDMORE)
socket.send(b"", zmq.SNDMORE)
socket.send(b"OK")
except zmq.ContextTerminated:
# context terminated so quit silently
return
def client_thread(client_url, context, i):
""" Basic request-reply client using REQ socket """
socket = context.socket(zmq.REQ)
socket.identity = (u"Client-%d" % (i)).encode('ascii')
socket.connect(client_url)
# Send request, get reply
socket.send(b"HELLO")
reply = socket.recv()
print("%s: %s\n" % (socket.identity.decode('ascii'), reply.decode('ascii')), end='')
def main():
""" main method """
url_worker = "inproc://workers"
url_client = "inproc://clients"
client_nbr = NBR_CLIENTS
# Prepare our context and sockets
context = zmq.Context()
frontend = context.socket(zmq.ROUTER)
frontend.bind(url_client)
backend = context.socket(zmq.ROUTER)
backend.bind(url_worker)
# create workers and clients threads
for i in range(NBR_WORKERS):
thread = threading.Thread(target=worker_thread, args=(url_worker, context, i, ))
thread.start()
for i in range(NBR_CLIENTS):
thread_c = threading.Thread(target=client_thread, args=(url_client, context, i, ))
thread_c.start()
# Logic of LRU loop
# - Poll backend always, frontend only if 1+ worker ready
# - If worker replies, queue worker as ready and forward reply
# to client if necessary
# - If client requests, pop next worker and send request to it
# Queue of available workers
available_workers = 0
workers_list = []
# init poller
poller = zmq.Poller()
# Always poll for worker activity on backend
poller.register(backend, zmq.POLLIN)
# Poll front-end only if we have available workers
poller.register(frontend, zmq.POLLIN)
while True:
socks = dict(poller.poll())
# Handle worker activity on backend
if (backend in socks and socks[backend] == zmq.POLLIN):
# Queue worker address for LRU routing
worker_addr = backend.recv()
assert available_workers < NBR_WORKERS
# add worker back to the list of workers
available_workers += 1
workers_list.append(worker_addr)
# Second frame is empty
empty = backend.recv()
assert empty == b""
# Third frame is READY or else a client reply address
client_addr = backend.recv()
# If client reply, send rest back to frontend
if client_addr != b"READY":
# Following frame is empty
empty = backend.recv()
assert empty == b""
reply = backend.recv()
frontend.send(client_addr, zmq.SNDMORE)
frontend.send(b"", zmq.SNDMORE)
frontend.send(reply)
client_nbr -= 1
if client_nbr == 0:
break # Exit after N messages
# poll on frontend only if workers are available
if available_workers > 0:
if (frontend in socks and socks[frontend] == zmq.POLLIN):
# Now get next client request, route to LRU worker
# Client request is [address][empty][request]
client_addr = frontend.recv()
empty = frontend.recv()
assert empty == b""
request = frontend.recv()
# Dequeue and drop the next worker address
available_workers -= 1
worker_id = workers_list.pop()
backend.send(worker_id, zmq.SNDMORE)
backend.send(b"", zmq.SNDMORE)
backend.send(client_addr, zmq.SNDMORE)
backend.send(b"", zmq.SNDMORE)
backend.send(request)
# Out of infinite loop: do some housekeeping
frontend.close()
backend.close()
context.term()
if __name__ == "__main__":
main()
以上工作原理。
cycrh6rtp35.rtp.netapp.com{}: ./alltogether.py
Worker-1: HELLO
Worker-0: HELLO
Worker-2: HELLO
Client-0: OK
Client-1: OK
Worker-1: HELLO
Worker-0: HELLO
Client-2: OK
Worker-2: HELLO
Client-5: OK
Client-4: OK
Worker-1: HELLO
Worker-2: HELLO
Client-3: OK
Client-6: OK
Worker-0: HELLO
Worker-1: HELLO
Client-7: OK
Client-8: OK
Client-9: OK
我想把逻辑分成三个py文件
一个为工人
一个客户端
一个经纪人
broker.py
def do_lb():
url_worker = "inproc://workers"
url_client = "inproc://clients"
client_nbr = NBR_CLIENTS
# Prepare our context and sockets
context = zmq.Context()
frontend = context.socket(zmq.ROUTER)
frontend.bind(url_client)
backend = context.socket(zmq.ROUTER)
backend.bind(url_worker)
# create workers and clients threads
#raw_input("Press Enter to continue...")
#print 'continuing...'
# Logic of LRU loop
# - Poll backend always, frontend only if 1+ worker ready
# - If worker replies, queue worker as ready and forward reply
# to client if necessary
# - If client requests, pop next worker and send request to it
# Queue of available workers
available_workers = 0
workers_list = []
# init poller
poller = zmq.Poller()
# Always poll for worker activity on backend
poller.register(backend, zmq.POLLIN)
# Poll front-end only if we have available workers
poller.register(frontend, zmq.POLLIN)
while True:
print 'in while true loop'
socks = dict(poller.poll())
print 'out1'
# Handle worker activity on backend
if (backend in socks and socks[backend] == zmq.POLLIN):
print 'out11'
# Queue worker address for LRU routing
worker_addr = backend.recv()
assert available_workers < NBR_WORKERS
# add worker back to the list of workers
available_workers += 1
workers_list.append(worker_addr)
print 'out12'
# Second frame is empty
empty = backend.recv()
assert empty == b""
print 'out13'
# Third frame is READY or else a client reply address
client_addr = backend.recv()
# If client reply, send rest back to frontend
if client_addr != b"READY":
# Following frame is empty
empty = backend.recv()
assert empty == b""
reply = backend.recv()
frontend.send(client_addr, zmq.SNDMORE)
frontend.send(b"", zmq.SNDMORE)
frontend.send(reply)
client_nbr -= 1
if client_nbr == 0:
break # Exit after N messages
print 'out2'
# poll on frontend only if workers are available
if available_workers > 0:
print 'workers are available'
if (frontend in socks and socks[frontend] == zmq.POLLIN):
# Now get next client request, route to LRU worker
# Client request is [address][empty][request]
client_addr = frontend.recv()
empty = frontend.recv()
assert empty == b""
request = frontend.recv()
# Dequeue and drop the next worker address
available_workers -= 1
worker_id = workers_list.pop()
backend.send(worker_id, zmq.SNDMORE)
backend.send(b"", zmq.SNDMORE)
backend.send(client_addr, zmq.SNDMORE)
backend.send(b"", zmq.SNDMORE)
backend.send(request)
else:
print 'workers are not available'
# Out of infinite loop: do some housekeeping
frontend.close()
backend.close()
context.term()
worker.py
import random
import sys
import threading
import time
import zmq
# using inproc
def worker_thread(context, i):
""" Worker using REQ socket to do LRU routing """
print 'creating worker %s' % i
worker_url = "inproc://workers"
socket = context.socket(zmq.REQ)
# Set the worker identity
socket.identity = (u"Worker-%d" % (i)).encode('ascii')
socket.connect(worker_url)
# Tell the borker we are ready for work
socket.send(b"READY")
try:
while True:
print 'in a while true loop, waiting...'
address = socket.recv()
empty = socket.recv()
request = socket.recv()
print("%s: %s\n" % (socket.identity.decode('ascii'), request.decode('ascii')))
socket.send(address, zmq.SNDMORE)
socket.send(b"", zmq.SNDMORE)
socket.send(b"OK")
except zmq.ContextTerminated:
# context terminated so quit silently
return
和client.py
import random
import sys
import threading
import time
import zmq
#using inproc
def client_thread(context, i):
""" Basic request-reply client using REQ socket """
print 'creating client %s' % i
client_url = "inproc://clients"
socket = context.socket(zmq.REQ)
socket.identity = (u"Client-%d" % (i)).encode('ascii')
socket.connect(client_url)
# Send request, get reply
print 'sending hello'
socket.send(b"HELLO")
reply = socket.recv()
print("%s: %s\n" % (socket.identity.decode('ascii'), reply.decode('ascii')))
我首先启动了broker.py,然后是workers.py,然后是clients.py,它们只是挂起并且什么都不做。
任何人都知道为什么?