Nginx/PHP-FPM/Laravel cannot handle concurrent requests with single IP - python

We have two servers:
Nginx/PHP-FPM/Laravel
Python on a different server
Some API calls to Laravel need data from the python server and vice versa. But when both of these occur it appears to be blocking.
My IP makes a call to the Laravel server.
Laravel server makes a call (guzzletransport) to python and waits for a response.
Python server makes a request back to the Laravel server in part of completing the request. This call never completes under these conditions.
I can test the call in (3) by making the appropriate call to the python server and it completes without issue. It appears that the call in (2) blocks the server from processing any additional requests. I am confused why this is occurring as php-fpm should allow simultaneous connections.
While waiting for (1) from my browser and additional requests from my browser also are blocked. I can make requests during this time to the Laravel server from a different IP and it completes it without issue.

Related

What is the proper way to have an asychronous python script wait for a response from a server?

I currently have a program that does work on a large set of data, at one point in the process it sends the data to a server for more work to be done, then my program looks for the completed data periodically, sleeping if it is not ready and repeating until it fetches the data, then continuing to do work locally.
Instead of polling repeatedly until the external server has finished, it has the ability to send a simple http post to an address I designate once the work has finished.
So I assume I need flask running at an address that can receive the notification, but I'm unsure of the best way to incorporate flask into the original program. I am thinking just to split my program into 2 parts.
part1.py
does work --> send to external server
part1 ends
flask server.py
receives data --> spawns part2.py with received data
The original program uses multiprocessing pools to offset waiting for the server responses, but with using flask, can I just repeatedly spawn new instances of part2 to do work on the data as it is received?
Am I doing this all completely wrong, I've just put this together with some googling and feel out of my depth
U can use broker with a message queue implemented ex. Celery + Redis or RabbitMQ. Then, when the other server finishes doing whatever it has to do with the data it can produce an event, and the first server will receive a notification.

Bluemix Flask API Call Timeout

I have an API written with python flask running on Bluemix. Whenever I send it a request and the API takes more than 120 seconds to respond it times out. It does not return anything and it returns the following error: 500 Error: Failed to establish a backside connection.
I need it to be able to process longer requests as well. Is there any way to extend the timeout value or is there a workaround for this issue?
All Bluemix traffic goes through the IBM WebSphere® DataPower® SOA Appliances, which provide reverse proxy, SSL termination, and load balancing functions. For security reasons DataPower closes inactive connections after 2 minutes.
This is not configurable (as it affects all Bluemix users), so the only solution for your scenario is to change your program to make sure the connection is not idle for more than 2 minutes.

Python - best way to wait until a remote system is booted

I am using wake on lan to start a certain server in a python script.
The server is online when I can do a successfull API request, such as:
return requests.get(
url + path,
auth=('user', user_password),
headers={'Content-Type':'application/json'},
verify=False,
timeout=0.05
).json()
What is the best method to wait for the server bootup process (until it is reachable via API) without spamming the network with requests in a loop?
I believe you're very close. Why not put that request in while a d try except blocks?
while True:
try:
return requests.head(...)
except requests.exceptions.ConnectionError:
time.sleep(0.5)
Your two choices are to poll the remote service until it responds or configure the service to in some way notify you that it's up.
There's really nothing wrong with sending requests in a loop, as long as you don't do so unnecessarily often. If the service takes ~10 seconds to come up, checking once a second would be reasonable. If it takes ~10 minutes, every 30 seconds or so would probably be fine.
The alternative - some sort of push notification - is more elegant, but it requires you having some other service up and running already, listening for the notification. For example you could start a simple webserver locally before restarting the remote service and have the remote service make a request against your server when it's ready to start handling requests.
Generally speaking I would start with the polling approach since it's easier and involves fewer moving parts. Just be sure you design your polling in a fault-tolerant way; in particular be sure to specify a maximum time to wait or number of polling attempts to make before giving up. Otherwise your script will just hang if the remote service never comes up.

Which web servers are compatible with gevent and how do the two relate?

I'm looking to start a web project using Flask and its SocketIO plugin, which depends on gevent (something something greenlets), but I don't understand how gevent relates to the webserver. Does using gevent restrict my server choice at all? How does it relate to the different levels of web servers that we have in python (e.g. Nginx/Apache, Gunicorn)?
Thanks for the insight.
First, lets clarify what we are talking about:
gevent is a library to allow the programming of event loops easily. It is a way to immediately return responses without "blocking" the requester.
socket.io is a javascript library create clients that can maintain permanent connections to servers, which send events. Then, the library can react to these events.
greenlet think of this a thread. A way to launch multiple workers that do some tasks.
A highly simplified overview of the entire process follows:
Imagine you are creating a chat client.
You need a way to notify the user's screens when anyone types a message. For this to happen, you need someway to tell all the users when a new message is there to be displayed. That's what socket.io does. You can think of it like a radio that is tuned to a particular frequency. Whenever someone transmits on this frequency, the code does something. In the case of the chat program, it adds the message to the chat box window.
Of course, if you have a radio tuned to a frequency (your client), then you need a radio station/dj to transmit on this frequency. Here is where your flask code comes in. It will create "rooms" and then transmit messages. The clients listen for these messages.
You can also write the server-side ("radio station") code in socket.io using node, but that is out of scope here.
The problem here is that traditionally - a web server works like this:
A user types an address into a browser, and hits enter (or go).
The browser reads the web address, and then using the DNS system, finds the IP address of the server.
It creates a connection to the server, and then sends a request.
The webserver accepts the request.
It does some work, or launches some process (depending on the type of request).
It prepares (or receives) a response from the process.
It sends the response to the client.
It closes the connection.
Between 3 and 8, the client (the browser) is waiting for a response - it is blocked from doing anything else. So if there is a problem somewhere, like say, some server side script is taking too long to process the request, the browser stays stuck on the white page with the loading icon spinning. It can't do anything until the entire process completes. This is just how the web was designed to work.
This kind of 'blocking' architecture works well for 1-to-1 communication. However, for multiple people to keep updated, this blocking doesn't work.
The event libraries (gevent) help with this because they accept and will not block the client; they immediately send a response and when the process is complete.
Your application, however, still needs to notify the client. However, as the connection is closed - you don't have a way to contact the client back.
In order to notify the client and to make sure the client doesn't need to "refresh", a permanent connection should be open - that's what socket.io does. It opens a permanent connection, and is always listening for messages.
So work request comes in from one end - is accepted.
The work is executed and a response is generated by something else (it could be a the same program or another program).
Then, a notification is sent "hey, I'm done with your request - here is the response".
The person from step 1, listens for this message and then does something.
Underneath is all is WebSocket a new full-duplex protocol that enables all this radio/dj functionality.
Things common between WebSockets and HTTP:
Work on the same port (80)
WebSocket requests start off as HTTP requests for the handshake (an upgrade header), but then shift over to the WebSocket protocol - at which point the connection is handed off to a websocket-compatible server.
All your traditional web server has to do is listen for this handshake request, acknowledge it, and then pass the request on to a websocket-compatible server - just like any other normal proxy request.
For Apache, you can use mod_proxy_wstunnel
For nginx versions 1.3+ have websocket support built-in

Callback Functions across computers?

I'm writing a python server/client app. If I serialize a function on the client and pass it to the server, can the server use it as a callback? I'm assuming there must be something extra I'd have to do as the client and server are communicating via packets, I just don't know what.
What I actually need is for the server to change one of the client's attributes (when the server is ready to accept another command), and I want an alternative to having the client continuously poll the server. Thanks for any help.
Take a look at Twisted JSON RPC.
A recent SO post: Python Twisted JSON RPC

Categories