For a start, you should be doing something like:
try:
context = zmq.Context()
#print "Connecting to server..." - commented out based on your answer
socket = context.socket(zmq.DEALER)
socket.connect ("ipc://%s <ipc://%s>" % ipc_sock)
try:
# socket.setsockopt(zmq.SOCKOPT_LINGER, 0) this should be the default
for close() and is not in python binding
poll = zmq.Poller()
poll.register(socket, zmq.POLLIN)
socket.send_string (send_msg)
socks = dict(poll.poll(REQUEST_TIMEOUT))
if socket in socks and socks[socket] == zmq.POLLIN:
reply_msg = socket.recv()
if '"Error":' not in reply_msg:
cur_ms = time.time()
elapsed_ms = cur_ms - start_ms
reply_msg = '{"Data": ' + reply_msg + ',"Resp_time": "' +
str(elapsed_ms) + '"}'
else:
reply_msg = '{"Error": "No Response from CMDSRV in ' +
str(REQUEST_TIMEOUT) + ' milliseconds"' + alert_param
socket.setsockopt(zmq.LINGER, 0)
finally:
socket.close()
try:
poll.unregister(socket)
except Exception:
pass
except Exception as e:
reply_msg = '{"Error": "' + e.message + '"' + alert_param
This way if an error occurs and exception passed back, that you ensure you
close the socket promptly, and potentially deregister it from the poller if
necessary.
If don't do that for errors, socket may stay open.
Graham
> On 10 Aug 2018, at 9:58 am, Tim Moody <[email protected]> wrote:
>
> If it is not an imposition here is the entire app:
>
> import zmq
> import os.path
> import time
> import urllib2
>
> cmdsrv_pid_file = "{{ cmdsrv_pid_file }}"
> cmdsrv_ready_file = "{{ cmdsrv_ready_file }}"
>
> alert_param = ',"Alert": "True"}'
>
> def application(environ, start_response):
> start_ms = time.time()
>
> if environ['REQUEST_METHOD'] == 'POST':
> try:
> request_body_size = int(environ.get('CONTENT_LENGTH', 0))
> except (ValueError):
> request_body_size = 0
>
> request_body = environ['wsgi.input'].read(request_body_size)
> # request_body holds command=<text of cmd>
>
> if os.path.exists(cmdsrv_pid_file):
> if os.path.exists(cmdsrv_ready_file):
> # unpack cmd, urldecode, and substitute space for %20
> cmd =
> urllib2.unquote(request_body.split('=')[1]).decode('utf8')
> cmd = cmd.replace('%20', ' ')
>
> response_body = send_command(cmd, start_ms)
> else:
> response_body = '{"Error": "CMDSRV has started but is not
> ready."' + alert_param
> else:
> response_body = '{"Error": "CMDSRV is not running."' + alert_param
>
> response_headers = [('Content-type', 'application/json'),
> ('Content-Length', str(len(response_body)))]
>
> else: # not a POST
> response_body = dump(environ)
> response_headers = [('Content-type', 'text/plain'),
> ('Content-Length', str(len(response_body)))]
> status = '200 OK'
> start_response(status, response_headers)
> return [response_body]
>
> def dump(environ):
> response_body = ['%s: %s' % (key, value) for key, value in
> sorted(environ.items())]
> response_body = '\n'.join(response_body)
> return response_body
>
> def send_command(cmd, start_ms):
>
> REQUEST_TIMEOUT = 30000
> send_msg = cmd
>
> ipc_sock = "/run/cmdsrv_sock"
>
> try:
> context = zmq.Context()
> #print "Connecting to server..." - commented out based on your answer
> socket = context.socket(zmq.DEALER)
> socket.connect ("ipc://%s" % ipc_sock)
> # socket.setsockopt(zmq.SOCKOPT_LINGER, 0) this should be the default
> for close() and is not in python binding
> poll = zmq.Poller()
> poll.register(socket, zmq.POLLIN)
>
> socket.send_string (send_msg)
> socks = dict(poll.poll(REQUEST_TIMEOUT))
>
> if socket in socks and socks[socket] == zmq.POLLIN:
> reply_msg = socket.recv()
> if '"Error":' not in reply_msg:
> cur_ms = time.time()
> elapsed_ms = cur_ms - start_ms
> reply_msg = '{"Data": ' + reply_msg + ',"Resp_time": "' +
> str(elapsed_ms) + '"}'
> else:
> reply_msg = '{"Error": "No Response from CMDSRV in ' +
> str(REQUEST_TIMEOUT) + ' milliseconds"' + alert_param
>
> socket.setsockopt(zmq.LINGER, 0)
> socket.close()
> poll.unregister(socket)
>
> except Exception as e:
> reply_msg = '{"Error": "' + e.message + '"' + alert_param
>
> return reply_msg
>
>
> On Thu, Aug 9, 2018 at 7:48 PM, Tim Moody <[email protected]
> <mailto:[email protected]>> wrote:
> Well, I think it is thread safe. The mod_wsgi application is an end point for
> an ajax request, which it forwards to the multi-threaded backend server over
> a zeromq socket (using a linux ipc socket), polls for a response for up to 30
> seconds, and returns the json result or failure to the ajax caller's callback
> function. It then terminates. All of this is password protected using apache
> mod_auth, part of the reason I didn't just use uwsgi.
>
>
> On Thu, Aug 9, 2018 at 7:30 PM, Graham Dumpleton <[email protected]
> <mailto:[email protected]>> wrote:
>
>
> > On 10 Aug 2018, at 9:22 am, Tim Moody <[email protected]
> > <mailto:[email protected]>> wrote:
> >
> > Thanks for replying so quickly. The message is indeed a print statement in
> > my python wrapper. It was the wsgi.error that threw me off. So I guess it
> > is really an info message.
> >
> > However, I still get failed connections, but perhaps these are from zeromq
> > and not from mod_wsgi. However, to be sure, I should say that I am not
> > using WSGIDaemonProcess but only WSGIScriptAlias and all other defaults (on
> > 4.3.0 Ubuntu 16.04). Is there any chance that mod_wsgi will be starved for
> > connections if 8 requests arrive nearly simultaneously?
>
> Is your use of the client for backend service thread safe?
>
> A typical configuration for Apache/mod_wsgi means that you have multiple
> threads per process handling requests, so you have to be careful to ensure
> that each request has own client instance, or if one client instance that can
> handle multithread access okay.
>
> Anyway, how many concurrent requests mod_wsgi can handle for embedded mode is
> dictated by Apache MPM settings. This is unrelated though to backend
> connections and whether limits enforced by backend service. If capacity to
> handle more requests had been reached as Apache MPM settings low, requests
> would just queue up and never get to the application until free capacity, so
> not going to affect anything in backend connections for those requests which
> are able to be handled.
>
> Graham
>
> --
> You received this message because you are subscribed to a topic in the Google
> Groups "modwsgi" group.
> To unsubscribe from this topic, visit
> https://groups.google.com/d/topic/modwsgi/HMKpmmNacX4/unsubscribe
> <https://groups.google.com/d/topic/modwsgi/HMKpmmNacX4/unsubscribe>.
> To unsubscribe from this group and all its topics, send an email to
> [email protected]
> <mailto:modwsgi%[email protected]>.
> To post to this group, send email to [email protected]
> <mailto:[email protected]>.
> Visit this group at https://groups.google.com/group/modwsgi
> <https://groups.google.com/group/modwsgi>.
> For more options, visit https://groups.google.com/d/optout
> <https://groups.google.com/d/optout>.
>
>
>
> --
> You received this message because you are subscribed to the Google Groups
> "modwsgi" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to [email protected]
> <mailto:[email protected]>.
> To post to this group, send email to [email protected]
> <mailto:[email protected]>.
> Visit this group at https://groups.google.com/group/modwsgi
> <https://groups.google.com/group/modwsgi>.
> For more options, visit https://groups.google.com/d/optout
> <https://groups.google.com/d/optout>.
--
You received this message because you are subscribed to the Google Groups
"modwsgi" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
Visit this group at https://groups.google.com/group/modwsgi.
For more options, visit https://groups.google.com/d/optout.