I'm assuming that for every page request, the webserver (eg. Apache) creates a new instance of a script in memory. Can these instances communicate with each other while running? and pass data too?
If you want to pass data between scripts in PHP I suggest using either memcached or a database. Or possibly APC.
If the scripts belong to the same session, they could theoretically communicate via the session but this would be effectively a one-way communication in most cases because only one script can access the session at any one time (session_start() locks the session until that script ends the session implicitly or explicitly).
I believe Martin and Cletus' suggestions are valid. My choice would be function of the end goal of the script.
How much data will you be throwing around? Can you handle the overhead of an external process?
What kind of data are you exchanging? Is it normalized? Or is it now worth normalizing?
Will you need to refer to that data later on? Or can it be discarded after being processed?
Will those scripts ever run on different servers?
Flat files, with a locking mechanism
Relational DB
Document DB (key/value store, whether persistent or not)
Shared memory (APC, or core functions)
Message queues (Active MQ and company)
I think you'll get the most value by externalizing the process as you can have more than one machine managing the messages/data and more than one producing/consuming them.
The model that PHP scripts operate off of doesn't really contain the notion of any kind of persistence in memory for those scripts, since generally they're designed to only run for the minimum of time required to serve the requested page. This would make it hard to have any meaningful use for stateful communication between those scripts, since typically once the page is served there's nothing more for the script to do. Thus usually any communication between PHP scripts is done more through manipulation of database entries and the like.
If you have some sort of continual processing that should be happening for which you'd want to be passing data around, you might want to look into other web application models such as servlets.
You should be able to do this with some shared memory, as described here: http://blog.taragana.com/index.php/archive/how-to-use-shared-memory-in-php/ (assuming you're not running on Windows)
Related
We have a need to keep a collection of socket objects around that are associated with different client browser sessions, so that when the client's browser makes a subsequent request, we can use the existing socket connection/session to make a request on their behalf. The socket is to something that is not HTTP. Is there a way to store objects like this in PHP that will survive across page requests?
Is there a way to store objects like this in PHP that will survive across page requests?
No.
To quote zombat's answer to a very similar question:
In PHP, there is no concept of page instances. Every request to the web server is a fresh start. All the classes are re-loaded, so there is no concept of class sharing, nor is there a concept of resource pooling, unless it is implemented externally. Sharing sockets between web requests therefore isn't really possible.
If the objects were serializable, you could use PHP's serialize() and unserialize() in conjunction with MySQL memory tables to solve this issue. Other than that, I don't think there's much else you can do.
In php script dies after page load so there is no way to do it. Hovewer you can create a long-living daemon which will open all required by process sockets and keep it opened between page reload. Of course you'll need to isolate these sockets by some kind of access key to make sure different sessions won't have access to other user's sockets. Also you need to keep in mind that it will die at some moment so make sure you have logic to restart all the sockets which were opened. But it can be achieved for sure.
Thanks.
This isn't a complete answer; but it steps towards an answer.
As has been pointed out ad nauseum elsewhere, the standard, classic model of using PHP, via a web server (Apache, Nginx, etc) does not allow you to do this, because each page hit starts with an entirely fresh set of variables.
Three thoughts:
You need a persistence layer. Obviously this is where you store stuff in a database, or use APC (APCu in PHP7+), Redis, or something similar.
Your problem, however, is that you specify "unserializable."
My next suggestion would be, perhaps you could persist the elements necessary to construct the object, and re-initialise the object for each PHP request. It won't be as amazingly performant as you'd like, but it's the most useful solution without having to rewrite eveything. Perhaps you've already tried it.
The next step is to do something completely out-there. One of the advantages the NodeJS infrastructure has is that the entire server loop persists.
So you could try one of the alternate methods of running PHP, like ReactPHP or PHP FastCGI. (There are others, but I can't remember them off the top of my head. I'll edit this if I remember.)
This involves an entirely different way of writing PHP--as different as NodeJS programming is from stuffing around with jQuery inside your browser. It wouldn't run within Apache. Rather, it would run directly as an app on your Unix server. And you'll have to cater for things like garbage collection so you don't have memory leaks, and write nice tight event loops.
The plus side is, because your thread persists and handles each subsequent request, you're able to handle requests in exactly the way you're after.
Your comment mentions these are local sockets. And it sounds like the PHP application acts as a socket client. So the only thing which is needed by the PHP session is a common identifier, such as a user ID, and for the sockets to be named consistently.
So, for example:
<?php
$userid = $_SESSION['userid'];
$fp = stream_socket_client("unix:///tmp/socket-" . $userid, $errno, $errstr, 30);
if ($fp) {
fread...
}
Here is my question: Consider Django or web2py in Python (as web frameworks) or Java WEB applications (being simple servlets apps or complex struts2/wicket/whatever frameworks). They share at least two things I like:
There's a Context environment or a way to access data out of the request or session contexts (i.e. global data, singletones, pools ... anything that can share in-memory values and behavior).
Classes are loaded/initialized ONCE. Perhaps i'm missing something but AFAIK in PHP a class is loaded and initialized in a PER REQUEST basis (so, in a regular class, if I (e.g.) modify a static value, this will live only in the current request, and even a simultaneous request hitting that value will get a different one).
Is there a way to get that in php? e.g. in Python/Django i can declare a regular class and that class can hold static data or be a true singleton (again: perhaps a pool or a kind of central queue manager), and will be the same object until the django server dies (note: modules in python are kept loaded in the python context when imported).
The fact that PHP's "context" lives on a per-request basis is pretty much core to how the language works with web servers.
If you want to get it working more like Java or other languages where the data doesn't get reset every request, you basically have two options:
Serialize data into a file, DB, whatever, and reload it on the next request
Instead of serving your pages through a web server, write the server using PHP
Serializing data into storage and reloading it on subsequent requests is the typical approach.
Writing a server in PHP itself, while possible, is not something I would recommend. Despite much effort, PHP still has sort of bad memory management, and you are very likely to encounter memory leaks in long-running PHP processes.
I have a situation where my Linux server will be running a website which gets some of its data from a 3rd-party server through a SOAP interface. The data isn't exactly real-time, but it does change every 5 minutes or so. I was told not to have our website hammer their website for data, which I can completely understand.
So I wondered if this was a good candiate to use a cache scheme of some type. Where when a user comes to our web page to display the data, if it's less than 5 minutes old (for example), it would get that data from our server instead of polling the 3rd-party for it. This way, if 100 users at once come to our website, our server won't be access the 3rd-party website 100 times to share the same exact data within a given time-frame.
Is this a practical thing to do in PHP? Or should this be written in a faster language when it comes to caching? Are their cache packages for this sort of situation which can be used along with a PHP Joomla application? Thanks!
I think memcached is a good choice.
You can set timeout when you store content to memcached server, if key-value missed, retrieve data from 3rd-part server and store again.
There is memcached extension for PHP, check doc here.
There's lots of ways to solve the problem -we can't say which is the right one without knowing a lot more about the constraints you are working in or how the service is used. If you are using Joomla then you're obviously not bothered about performance - it would be really hard to write anything which has a measurable impact on your html generation times. This does not need to "be written in a faster language", but....
can you install additional software?
have you got access to cron?
at what rate is the service consumed?
how many webservers do you have consuming the service - do they have a shared filesystem? Are they on the same sub-net?
Is the SOAP response cacheable?
how do you deal with non-availability of the service?
For a very scalable solution I would suggest running a simple forward proxy (e.g. squid) but do make sure that it's not accessible from the internet. Sven (see comment elsewhere) is right about POST sometimes not being cacheable - but you can cache the response from a surrogate script on your own site accessed via GET returning appropriate caching instructions - and this could return the data as a serialized php array / object which is much less expensive to process. Indeed whichever method you choose I would recommend caching the parsed response - not the XML. This also allows you to override poor caching information from the service.
If the rate is less than around 1 per minute then the cron solution is overkill. But if its more than 20 per minute then it makes a lot of sense. If you don't have access to cron / can't install your own software then you might consider simply caching the response and refreshing the cache on demand. Don't bother with memcache unless you are already using it. APC is faster on a single server - but memcache is distributed. If you have multiple servers then use whatever cluster storage you are currently sharing your data in (distributed filesystem / database cluster / shared filesystem....).
Don't try to use locking / mutexes around the cache refresh unless you really have to (i.e. only if accessing the service more than once every 5 minutes is a mortal sin) - this gets real complicated real quick - it's too easy to introduce bugs.
Do make sure you buffer and validate any responses before writing them to the cache.
Yes, just use HTTP. Most of the heavy lifting has already been built into your web server.
Since SOAP is just a simple HTTP POST request with an XML body, you could set up your website or HTTP API in front of the SOAP endpoint to act like a translator to regular HTTP, attaching the appropriate HTTP caching headers on the transformed response body and then configure an NGinx reverse proxy in front of it.
Notably: if the transformation is simple you could just use XSLT to transform the response body from the SOAP API and remove the web service layer entirely.
Your problem is a very small one, which does not require a complicated solution.
You could write a small cron job that is executed every five minutes, sends the request to the SOAP server, and stores the result in a local file. If any script needs the data, it reads the local file. This will result in 288 requests to the SOAP server per day, and have excellent performance for any script call that needs the results because they are already on your server.
If you do not have cron jobs available and cannot fake them, any other cache will do. You really don't need fancy stuff like Memcached, unless it already is available. Storing the result to a cache file will work as well. Note that if you have to really fetch the SOAP result from the origin, this will take some more time and might affect the perceived performance of your site.
There are plenty of frameworks which also offer cache support, and if you use one you should investigate if there is support included. I'm not sure if Joomla has something appropriate for you. Otherwise, you can implement something yourself. It isn't that hard.
Cache functionality comes in various flavours:
memory-based, where a separate process on the server holds data in RAM (or overflows to disk) and you query it like you would a database; very efficient and powerful, and will have options to manage storage use and clear up after themselves, but requires setting up additional software on the server; e.g. memcached, redis
file-based, where you just write the data to disk; less efficient, but can be implemented in "user-land" code, i.e. pure PHP; beware of filling up your disk with variant caches that have expired but not been cleaned up; many frameworks have an implementation of this built in
database-backed, where you push data into an RDBMS (e.g. MySQL, PostgreSQL) or fully-featured NoSQL store (e.g. MongoDB); might make sense if you have a large amount of data, and can trade a bit of performance; as with files, you need to make sure that stale data is cleaned up
In each case, the basic idea is that you create a "key" that can tell one request from another (e.g. the name of the SOAP call and its input parameters, serialized), and pick a "lifetime" (how long you want to carry on using the same copy of the data). The caching engine or library then checks for a cache with that key, and if it is still within its "lifetime" returns the previously cached data. If there is a "cache miss" (there is no cache for that key, or it has expired), you perform the costly operation (in your case, the SOAP call) and save to the cache, using the same key.
You can do more complex things, like pre-caching things in the background so that there is never a cache miss, or having some code paths which accept stale data in order to return quickly, but these can generally be implemented on top of whatever you're using as the main caching solution.
Edit Another important decision is at what level of granularity to cache the data, in relation to processing it. At one extreme, you could cache each individual SOAP call: simple to set up, but means re-processing the same data repeatedly, and can cause problems if two responses are related, but cached independently and may get out of sync. At the other extreme, you can cache whole rendered pages: pages load very fast once cached, but creating variations based on the same data without repeating work becomes tricky. In between are various points in your code where you have processed and combined data into meaningful chunks: if your application is well-written, these are the input and output of major functions, or possibly even complete model objects; this is more work to implement, as you have to choose the right keys (avoiding two contexts overwriting each other's caches while ignoring variables that have no impact on the data in question) and values (avoiding repeats of costly work without having to store huge blobs of data which will be slow to unserialize and use up the capacity of your cache store). As with anything else, no approach suits all needs, and a complex application will probably involve caching at multiple levels for different purposes.
Hi is there anyway to store variable into memory until server restart or manually recreate the same variable using PHP.
Actually the problem is this I nee do have a router in my application which have several configuration to route the URLs on different APIs. I do not want to load my configuration each time a request lands so I am searching a way to keep the configuration data into memory until I manually recreate the same.
Please suggest if there is anyway to do this.
Thanks in Advanced.
PHP stores all variables in memory until the process exits (if the variable is a global) or until the scope ends (if the variable is local).
I think where you're getting confused is that Apache (or whatever webserver you're using) runs continuously, but it only starts PHP for every request, so PHP is never running continuously.
To store things across different requests, you'll need to use external persistence. You can do this with PHP sessions, a database, flat files, etc. but none of these will store the data in memory.
Even though it's external, you can use a caching server like memcached to store data in memory continuously, and then use PHP to access it through the Memcached class.
I am new to php, but in other web technologies, you can share objects between page instances. For example, in java jsp pages you easily have on class that exist as static class for the whole server instance. How to do this in php?
I am not refering to sessions variables (at least I don't think so). This is more for the purpose of resource pooling (perhaps a socket to share, or database connections etc). So a whole class needs to be shared between subsequent loads, not just some primitive variables that I can store in the session.
I have also looked into doing php singleton classes but I believe that class is only shared within the same page and not across pages.
To make things even more clear, I'm looking for something that can help me share, say, a socket connected to a server for a connectSocket.php page such that all users who loads that page uses the same socket and does not open a new one.
This is a bit of a difficult answer, and might not be exactly what you are looking for.
PHP is built upon a 'shared-nothing' architecture. If you require some type of state across your application, you must do this through other means.
First I would recommend looking into the core of the problem.. Do you really need it? If you assume the PHP application could die (and lose state) is it ok to lose the data?
If you must maintain the state, even after the application dies or otherwise, you should assume probably the best place to put the data is in MySQL. PHP is intended as a thin layer around your business logic, so I can highly recommend this.
If you don't care about losing the data after a restart, the problem domain you're looking for is probably caching. I would recommend looking into memcached or if you're on a single machine, apc. APC will definitely work for you with Apache on a single machine, but you will still have to code your application assuming you might lose the data.
If you're worried your underlying datastore (MySQL) is too slow, but you still need to maintain the data after a restart, you should look into a combination of these 2 systems. You can always push and pull your data from the cache, but only when it updates send it over to Mysql.
If the data is purely user or session-bound, you probably want to just looking into the sessions system.
I've personally developed a reasonably large multi-tenant application, and although its a pretty complex application, I've never needed the true state you're looking for.
Update: Sorry, I did not read your note about sharing a socket. You will need a separate daemon to handle this, perhaps if you can explain your problem further, there might be other approaches. What type of socket is this?
There's a fundamental difference between web-served Java and web-served interpreted languages like PHP and Perl. In Java, your web server will have an operating environment that maintains state (ie. Tomcat). With interpreted languages, a request to your web server will generally spawn a new web server thread, which in turn loads a fresh operating environment for that thread, in this case, the PHP environment.
Therefore, in PHP, there is no concept of page instances. Every request to the web server is a fresh start. All the classes are re-loaded, so there is no concept of class sharing, nor is there a concept of resource pooling, unless it is implemented externally.
Sharing sockets between web requests therefore isn't really possible.
This is likely a partial answer but you can save an instance of a class into a Session variable and access it at another time.
Most of the PHP database libraries use connection pooling already. You call, for example, pg_connect as if you were requesting a new connection, but if the connection string is the same as a connection that already exists, you will get the established connection back instead. If you only care about pooling for database access, then you can just confirm that it exists in the db library you're using.
An other horroble solution may be to load the data of the object to any $_SESSION variable and then user it back into the object of the other page.
In fact, this is the solution I'm going to follow in my project, until I get some better one.
Regards!