PHP is a langauge generally not suited for running daemons. That said, PHP can do it, and in certain circumstances does it sufficiently for the job. In this chapter we look at some of the things you need to know about to build a PHP-based daemon. This excerpt doesn't feature any code, but it does set the foundation for why I think PHP is fine for daemons in some circumstances. Later in the chapter we get into the code.
Chapter 1: Networking and Sockets
Chapter 2: Binary Protocols
Chapter 3: Character Encoding
Chapter 4: Streams
Chapter 5: SPL
Chapter 6: Asynchronous Operations with Some Encryption Thrown In
Chapter 7: Structured File Access
Chapter 8: Daemons
Chapter 9: Debugging, Profiling, and Good Development
Chapter 10: Preparing for Success
In reading this chapter you might get the idea that I am saying that you should be using PHP for building large scale, daemon-based applications. While I definitely am of the opinion that PHP can be used for that, PHP was not designed for it. For me, whether or not PHP can be used as a daemon comes out of the “use the right tool for the job” discussion that often happens online. Usually it comes up as an argument after one person bested another in some kind of language shoot-out. The looser of the argument (regardless of the actual merits of their chosen language) half-concedes by saying “Well you just use the best tool for the job.” Meaning, “You got me, but I won’t be made to look the fool.” Or “It’s not worth arguing with this idiot.” Chances are it’s the latter.
The problem is that there are lots of jobs that need to be done that are outside of the specialty of a given language. Following the “best took for the job” mentality you might have part of infrastructure running PHP, part of it running Ruby on Rails, part of it running .NET and part of it running Java. Nothing against any of those languages, but absolutely NONE of them do EVERYTHING well. Java is a good example. I personally like programming in Java. However, to have a web site running in Java you need to have layer upon layer upon layer of application server upon application server upon application server to make it run. Will it run? Yes. Will it run fast? Yes. Are web pages what Java was designed to do? With respect to JSP developers, no. Same thing with Ruby. Ruby is really good if you can afford to have very little flexibility. The benefit of Ruby on Rails comes at the price of inflexibility. If you need specific control over aspects of your application, Ruby is probably not the best choice for you.
Where am I going with this? The question of using “the best tool for the job.” A heterogeneous environment is not a good one to build for or manage. Getting one of those to work should be the goal of academics. Real life, with all its warts, will do much better with a fuller understanding of a smaller subset of features. This is because as soon as you have more than one type of architecture in your organization you now need to have more than one skill set. Having more skill sets means that it will be difficult to find experts. Having fewer experts means more time spent on support calls with other people whose knowledge base is also too wide.
What is the solution to this? I would contend that there is not a solution. Just like there is no vehicle that serves all needs, there is no programming language that serves all needs. Additionally, the people you have around are important factors. If you have developers who are good, but not great, at PHP, Ruby, Python, Java and .NET (who also need to know Flash), where will you have the skill set internally to handle a problem for which there isn’t an answer on Google? It’s like buying a Peugeot in Wyoming. I would contend that if you have several languages and infrastructures that you support, your developers are going to have more problems and be less creative. Creativity for the sake of creativity is not good. However, creativity allows for innovative solutions to difficult problems. Far too many people pick up a language and work with it, thinking that they are experts because someone else said the language was cool. However, the more languages you know the less of an expert you will be in each.
This takes us back to the earlier statement; using “the best tool for the job”. I would contend that this is wrong, or at least, problematic. I would go the route of saying “use the best tool for the organization” instead. That organization could be your place of business, a non-profit you work for, the website for a friend who’s starting a new business, your church, etc. How do you decide which tool you are going to use for a specific problem?
How you make the decision on is not set in stone. In fact, it’s unlikely that your organization made an intentional decision beyond “Hey, we’re building a website; we should use PHP, right?” If your organization has a significant web presence, then that is probably the right decision. PHP does web good. But what if you need something else? Say, for example, you need a simple message queue. You have several options. One is to obtain some kind of third party messaging software. There are plenty of options available for you, and they are probably going to be better than what you would build.
But there is often a problem with taking off the shelf software, both proprietary and open source. Half the time it’s complicated enough that once you install it you need even more experts to manage it. So, say you have simple needs, you need a message queue but your organization does not have the skill to support another language.
That is where building a PHP daemon comes in.
If we’re going to be building a daemon one of the primary purposes is to build something that can handle multiple tasks at one time. To do that we need to be able to handle multiple connections at once. Building an application that can handle multiple connections at once is actually very simple. So simple, in fact, that we’ve already done it back in the chapter on Networking and Sockets. However, there are two problems, one old and one new. And both deal with how to use the resources on the system as best as possible.
The old problem is the question of how do you efficiently use CPU time when you may have significant parts of your work that require other services, and thus, have wait times. These can be things like database calls, network calls or even file system access. Even though disks are relatively fast these days IO contention does occur. This isn’t just a problem that happens for larger organizations with high performance environments but also for smaller shops who have inefficient data structures on disk, or just high performance data requirements. So, how do you do other things while waiting for slower things to do their thing?