Should I terminate database connections when doing a cURL? - php

I have my app hosted in a hosting company that sometimes ends up having problems in their virtual machines/internal network, there are rare moments that for a few milliseconds there is a high latency in the network or a service is inaccessible.
With that, I noticed that the connections of the database start to increase a lot, making a chain reaction that increases the average load of the server of the application and of the database.
This application is in PHP, in several situations it needs to make requests to external pages and to other servers in the same network, using cURL, send emails or even fsockopen.
My main suspicion is that when there is a network problem, cURL will keep trying to finish the request (or until a timeout occurs). But in the meantime, the database connection that was opened by the PHP script is still open, so I will have multiple users opening connections that are not closed because the cURL is waiting for the request to complete.
This leads to my question, is it good practice to close the database connection when a connection to an external service is made and reopen after (if necessary)?
I know that the CPU can suffer from opening/closing connections, but today the entire application already works that way, without using persistent connections (pool), always opening/closing a connection for each request.

Related

PHP SSE vs PHP WebSockets(Ratchet)

I will start developing a multiplayer card game in a few weeks and until then, I am doing research on the best techniques available. I will be using PHP+MySQL for server-side and JS/HTML5 for client side. The game will be also be played from mobile browser.
The gameplay of my game involves 4 or more users playing at a table, each having up to 30 seconds to take an action. There will be multiple tables available and an user can play at more than 1 table at the same time.
From my research it would seem easy to sync the client with the server by having the server push data trough SSE each time another player made an action. Then when the current player takes an action, the request data would be sent through XMLHttpRequest from client to server and then synced to other players through SSE.
Now from what I read, there is a big downfall to this because for each player that listens to the SSE process, a connection stays opened on the server, consuming a lot of memory.
The application that I will build is intended to support over 10000 players on a dedicated server with modern hardware(8core CPU,64GB RAM), with time. Some may say PHP is not good for this, but the debate here is how to use PHP to make this work.
The alternative to the SSE implementation would be to use Websockets (I am currently checking Ratchet and managed to set up the Chat server from the doc), but overall I have some dillemas which prevent me from taking a decision:
Websockets: When establishing the handshake, a connection stays open on the server too, same as in SSE, but I guess that this is a different type of connection which consumes less memory. Is that right? So websockets would be more efficient.
Any estimates on memory usage for both SSE and WebSockets? I read somewhere that each connection through SSE would consume around 20mb with APACHE and PHP. That's going to be 200GB for 10000 users (too much). I hope I am wrong.I dont know how much memory a socket connection would consume. An idle one I mean.
Will SSE consume more battery (on mobile phones) and will cause more web traffic than the sockets connection?
SSE: If an user will be playing at two tables, do I need to open two SSE processes (one for each table) or how do I tell the SSE process if I am requesting data for table1 or table2? Or I am forced to receive data for all tables at the same time? It wouldnt be a problem to receive data for all the tables that the user is now active at, but I am curious if there are ways of customizing this.
How about dealing with people that have unstable internet connection? Does websockets support automatic reconnection? Or this needs to be done manually from the client?
1) Do both WebSockets and SSEs keep the connection open?
Yes. Both WebSockets and SSEs keep the connection open as long as the server is configured to do so or connection is closed by either client or server. Because many times, servers are default configured to close the connection when it's idle for more than the time specified in configuration.
2) If both keeps the connection open then do both have same memory consumption and network overhead? Which one is lighter and faster?
First thing is that both seems to share same resources in terms of connection making because both has to handshake for the first time and check the heart beat by pinging and rest is a normal single TCP connection.
But there is an important point to note that Websocket is Bi-Directional and SSEs are Uni-Directional so even if a SSE connection is alive and you have to send some data from client to server then you will have to use some kind of XHR which will again create another connection to server. And creating connections is resource intensive. So, it seems like WebSockets is better at resource utilizing when this is about Bi-Directional like in case of above OP case of Card Game of multiplayers. And also this makes WebSockets more faster and Lighter than SSEs. SSEs are good when you just have to send data from server to clients like some Stock Market Prices, Game Scores etc.
3) If the your preferred choice is WebSocket then do we need to worry about URL Rewrite, Response Headers etc
I don't think so because if WebSockets are used with PHP then most of the time it is CLi based separate PHP Script twith a websocket connecting to something like ws://example.com:8092/websocket.php. So, I don't think there will be more to worry about URL Rewrite or response headers. And also as I think headers can be added/modified by PHP script itself if needed anyway.
4) Will SSE consume more battery (on mobile phones) and will cause more web traffic than the sockets connection?
I don't think SSE will consume more battery as compare to WebSockets. But yes it will definitely create more traffic to server because as mentioned above that SSE is Uni-Directional and each data from Client to Server will create another connection to server.
5) How about dealing with people that have unstable internet connection? Does websockets support automatic reconnection? Or this needs to be done manually from the client?
Well there are some techniques which can handle this part to reconnect in such conditions.

Does php automaticly close the TCP connection after every request?

I have Apache 2.4/PHP 5.6.13 running on Windows Server 2008 R2.
I have an API connector which make 1 call per second per user to read a messaging queue.
I am using setInterval(...., 1000) to make an ajax request to a handler which does the actual API call.
The handler makes cURL calls to the API service to read the messaging queue.
This works fine for 2 users but now I have 10 users using the system which mean more API calls being sent from my server.
Many users "using the API caller or not" have been facing a timeout error. When I look at the php logs I see this fatal error
[14-Aug-2015 16:37:08 UTC] PHP Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[HY000] [2002] An operation on a socket could not be performed because the system lacked sufficient buffer space or because a queue was full.
I did a research on this issue and found out that it is not really a SQL error but rather a windows error. It is explained here.
It seems to me that I will need to edit the Windows Registry to correct the issue as it is explained here but I don't like touching windows registry specially on a production server.
My question is does PHP keep ths TCP connection open or does it close it after every request?
I have 10 users using the "API caller" and about 200 that were not. This is only addition was 10 users/10 API calls per second.
Assuming that PHP/cURL automaticly close the TCP connection, then how could I be reaching and 5000 connection from only 10 people using the API?
The problem lies in your application's architecture. Ajax polling is not scalable.
Short polling (what you do) is not scalable, because it just floods the server with requests. You have one request per second and per user. This gives already 10 requests per second for 10 users. You set up a DoS attack against your server!
Long polling (also called comet) means that your server does not immediately respond to the request, but waits until there's a message to send or until a timeout is reached. This is better, because you have lesser requests now. But it is still not scalable because on the server you will continue to hammer onto the database.
Websockets is what you are looking for. Your browser connects to the websocket server, and keeps the connection forever. It is a two way communication channel that is always available to both sides. There are two more things to know :
you need another server for websockets, Apache can't do it.
on the server side you need an event system. Hammering on the database is just not a solution.
Look into ratchet as a php based websocket deamon, and into Autobahn.js for the client side.
Edit: Ratchet is unfortunately no longer maintained. I switched to node.js.
PHP database connections use the PDO base class. By default they are closed each time a request is finished (the PHP script finishes). You can find out more information related to this here http://php.net/manual/en/pdo.connections.php.
You can force your database connection to be persistent which is normally beneficial if you are going to reuse the database connection often.
Apache is (im assuming) like other servers. It is constantly listening on a given port for incoming connections. It establishes that connection reads the request sends out a response and then closes the connection.
Your error is caused by taking up to many connections (the OS will only allow so many) OR overflowing the buffer for the connection. Both of these can be inferred from your error message.

Long polling PHP. Keep DB connection or not?

I'm trying out long polling for the first time.
In the PHP script I have a while-loop with a sleep-timer that freezes the script for 10 seconds, then it looks for new stuff in the database again.
I'm thinking performance and server/database load/connections:
What is worse for the server: Many GET-requests (ajax), or many opening/closing of the DB connection?
Would it in any way be better to use long polling but close and re-open the DB connection in each round of the while-loop (to free the limited number of connections)?
This is less trivial, than it sounds: What starts with a simple "should I or not" alternative rapidly increases in complexity with scaling to more servers.
Having hit walls with both approaches, we have come up with a proxy scheme, that seems to work well even on cheap shared hosting:
Run a single instance of a simple proxy script, that polls the DB (On shared hosting we start this from a cron job, that starts an instance only, if no other is running, so we easily survive reboots)
Have that proxy script translate the expensive DB poll into a cheaper poll: SysV SHM and flagfiles in the filesystem both work fine. The proxy should keep its single DB connection open
Have your potentiallly many long-pollers check the proxied flag.
This has made it possible to implement a short server-sided polling intervall without running into problems, when concurrent polls increase.

PHP's curl on Apache only opens one connection per server per browser

I'm having a problem with curl in PHP that I can't figure out. I have a web server (Apache) that talks to a web service over HTTPS on another Apache server. We'll call them "server A" and "server B".
The problem I'm seeing is that server A only makes one connection at a time using curl to server B per browser that's connected to server A. I'm not sure if this is a curl or apache problem. I have seen references in several places to a max connection per server setting of one for a curl client but I can't verify that it exists.
Scenario:
I load up twenty different pages in three different browsers, each in its own tab/window within that browser. I tried Firefox, Chrome, and Konqueror all at the same time. Firefox had all its per-server connection limits raised significantly through about:config
All of those pages are hosted on server A and loading was started close to simultaneously
Each instance of the page on server A talks to server B using curl
A single call of this type to server B normally takes ~10 seconds
Only one TCP connection from A->B is open at any one time per browser that is connected to server A (3 total from A->B)
I verified that multiple connections from the browsers are opened to server A
AFAICT the requests are all serialized. I'm able to verify that multiple connections are open from browsers to server A, but only one https connection is open from A->B per browser connected to A.
Server B can handle many connections simultaneously but for some reason server A won't open multiple connections to server B. I have tried sending "Connection: close" from both servers A and B to see if that would help. It did not.
I have found lots of people talking about making multiple asynchronous connections per script but what I want to do is open multiple connections across different page instances to one external server.
Any ideas on what the problem is or how to fix it?
Native php sessions(files handler) use an exclusive locking model - only a single process/thread can work with the data for a specific session id at a time. When session_start() is called, execution will block until the process can acquire a lock on the session file. The lock is released when session_write_close() is called, which php automatically calls upon script termination. You can call it manually to release the lock and commit your changes. If desired, you can session_start() and session_write_close() multiple times per script execution.
Did you consider that server B allows only 1 secure connection ?
As i know this is a browser security issues that allows only 1 secure connection to same host at 1 time.

How many connections/s can I expect between PHP and MySQL on separate server?

Trying to separate out my LAMP application into two servers, one for php and one for mysql. So far the application connects locally through a file socket and works fine.
I'm worried about the number connections I can establish if it is over the network. I have been testing tcp connections on unix for benchmark purposes and I know that you cannot exceed a certain amount of connections per second otherwise it halts due to the lack of resources (be it sockets, or file handles or whatever). I also understand that php does not implement connection pooling so for each page load a new connection over the network must be made. I also looked into pconnect for php and it seems to bring more problems.
I know this is a very very common setup (php+mysql), can anyone provide some typical usage and statistics they get out of their servers? Thanks!
The problem is not related to running out of connections allowed my MySQL. The main problem is that unix cannot very quickly create and tear down tcp connections. Sockets end up in TIME_WAIT and you have to wait for a period before you free up more sockets to connect again. These two screenshots clearly shows this pattern. MySQL does work up to a certain point and then pauses because the web server ran out of sockets. After certain amount of time passed, the web server was able to make new connections.
alt text http://img35.imageshack.us/img35/3809/picture4k.png
alt text http://img35.imageshack.us/img35/4580/picture2uyw.png
I think the limit is at 65535. So you'd have to have 65535 connections at the same time to hit that limit since a regular mysql connection closes automatically.
mysql_connect()
Note: The link to the server will be closed as soon as the execution of the script ends, unless it's closed earlier by explicitly calling mysql_close().
But if you're using a persistent mysql connection, then you can run into trouble.
Using persistent connections can require a bit of tuning of your Apache and MySQL configurations to ensure that you do not exceed the number of connections allowed by MySQL.
Each MySQL connection actually uses several meg of ram for various buffers, and takes a while to set up, which is why MySQL is limited to 100 concurrent open connections by default. You can up that limit, but it's better to spend your time trying to limit concurrent connections, via various methods.
Beware of raising the connection limit too high, as you can run out of memory (which, I believe, crashes mysql), or you may push important things out of memory. e.g. MySQL's performance is highly dependent on the OS automatically caching the data it reads from disk in memory; if you set your connection limit too high, you'll be contending for memory with the cache.
If you don't up your connection limit, you'll run out of connections long before your run out of sockets/file handles/etc. If you do increase your connection limit, you'll run out of RAM long before you run out of sockets/file handles/etc.
Regarding limiting concurrent connections:
Use a connection pooling solution. You're right, there isn't one built in to PHP, but there are plenty of standalone ones out there to choose from. This saves expensive connection setup/tear down time.
Only open database connections when you absolutely need them. In my current project, we automatically open a database connection when the first query is issued, and not a moment before; we also release the connection after we've done all our database work, but before the page's HTML is actually generated. The shorter the period of time you hold connections open, the fewer connections will be open simultaneously.
Cache what you can in a lighter-weight solution like memcached. My current project temporarily caches pages displayed to anonymous users (since every anonymous user gets the same HTML, in the end -- why bother running the same database queries all over again a few scant milliseconds later?), meaning no database connection is necessary at all. This is especially useful for bursts of anonymous traffic, like a front-page digg.

Categories