Develop multi-task applications with PHP V5

Source: Internet
Author: User
Tags php books server memory ibm developerworks stock prices

 

In addition to multiple processes, PHP can also support running in non-blocking mode, which is very powerful: d

This article is transferred from IBM developerworks, and I will try again later to create an original article :)

 

------------------------------------------------------- The post starts -----------------------------------------------------

 

Many PHP developers believe that, because the standard PHP lacks the thread function, it is impossible for the actual PHP application to execute multi-task processing. For example, if an application requires information from other web sites, it must be stopped before the remote retrieval is complete. This is wrong! This article describes how to use stream_select and stream_socket_client to implement multi-task PHP processing in the process.

PHP does not support threads. Even so, in contrast to what most PHP developers believe, PHP applications can perform multitasking. Let's start to describe the meaning of "multi-task" and "Thread" for PHP programming as clearly as possible.

 

Types of concurrency

 

First, let alone a few examples that are irrelevant to the topic. The relationship between PHP and multitasking or concurrency is very complex. At a high level, PHP often involves multi-tasking: using standard server-side PHP installation in a multi-task manner-for example, as an Apache module. In other words, several clients-Web browsers-can simultaneously request pages interpreted by the same PHP, and the web server will return almost all these pages at the same time.

 

A web page does not affect the sending of other web pages, although it may slightly affect each other due to limited resources such as server memory or network bandwidth. In this way, the PHP-based solution may be suitable for implementing the concurrent system-level requirements. In terms of implementation, PHP allows its Web server to manage for concurrency.

In recent years, client concurrency under Ajax has become the focus of developers' attention. Although the meaning of Ajax has become very vague, one aspect of AJAX is that the browser displays the ability to execute computing and retain responses to user operations such as selecting menu items. This is actually a type of multitasking. Php-encoded Ajax is like this-but does not involve any specific PHP; Ajax frameworks for other languages are operated in exactly the same way.

The third concurrent instance that only roughly involves PHP is PHP/TK. PHP/TK is an extension of PHP and is used to provide portable graphical user interface (GUI) binding for core PHP. PHP/tk allows you to write code in PHP to construct a desktop GUI application. The event-based feature simulates a concurrency mode that is easier to master and has fewer errors than threads. In addition, concurrency is a secondary technology that "inherits" from, rather than the basic functions of PHP.

The experiment of adding thread support to PhP itself has been done many times. As far as I know, none of them are successful. However, Ajax framework and PHP/tk event-oriented implementation indicate that the event may better reflect PHP concurrency than the thread. PHP V5 proves that this is true.

 

PHP V5 will provide stream_select ()

With standard PHP V4 and earlier versions, you must perform all the work of the PHP application in sequence. For example, if the program needs to search for the price of the product on two commercial sites, request the price of the first site, wait until the response arrives, then request the price of the second site, and then wait again.

What if the program requests to complete several tasks at the same time? In general, the program will be completed within a period of time, during which it will be processed continuously.

 

Example 1

The new stream_select Function and Its assistants make this possible. Consider the following example.

 

Listing 1. Request multiple HTTP pages at the same time

<? Php <br/> echo "program starts ". date ('H: I: s '). ". /n "; <br/> $ timeout = 10; <br/> $ result = array (); <br/> $ sockets = array (); <br/> $ convenient_read_block = 8192; </P> <p>/* issue all requests simultaneously; there's no blocking. */<br/> $ delay = 15; <br/> $ id = 0; <br/> while ($ delay> 0) {<br/> $ S = stream_socket_client ("phaseit.net: 80", $ errno, <br/> $ errstr, $ timeout, <br/> stream_client_async_connect | Stream_client_connect); <br/> if ($ s) {<br/> $ sockets [$ id ++] = $ S; <br/> $ http_message = "Get/demonstration/delay? Delay = ". <br/> $ delay. "HTTP/1.0/R/nhost: phaseit.net/r/n/r/n"; <br/> fwrite ($ S, $ http_message ); <br/>} else {<br/> echo "stream ". $ id. "failed to open correctly. "; <br/>}< br/> $ delay-= 3; <br/>}</P> <p> while (count ($ sockets )) {<br/> $ READ = $ sockets; <br/> stream_select ($ read, $ W = NULL, $ e = NULL, $ timeout ); <br/> If (count ($ read) {<br/>/* stream_select generally shuffles $ read, so we Need to <br/> compute from which socket (s) We're reading. */<br/> foreach ($ read as $ R) {<br/> $ id = array_search ($ R, $ sockets ); <br/> $ DATA = fread ($ R, $ convenient_read_block); <br/>/* a socket is readable either because it has <br/> data to read, or because it's at EOF. */<br/> If (strlen ($ data) = 0) {<br/> echo "stream ". $ id. "closes ". date ('H: I: s '). ". /n "; <br/> fclose ($ R); <br/> Unset ($ sockets [$ id]); <br/>}else {<br/> $ result [$ id]. = $ data; <br/>}< br/>} else {<br/>/* a time-out means that * All * streams have failed <br/> receive a response. */<br/> echo "time-out! /N "; <br/> break; <br/>}< br/>?> 

If you run this list, you will see the following output.

 

Listing 2. Typical output from the program in Listing 1

Program starts at 02:38:50.

Stream 4 closes at 02:38:53.

Stream 3 closes at 02:38:56.

Stream 2 closes at 02:38:59.

Stream 1 closes at 02:39:02.

Stream 0 closes at 02:39:05.

Understanding how this works is crucial. At a higher level, the first program will send several HTTP requests and receive the pages that the Web server sends to it. Although production applications are likely to find the addresses of several web servers, such as Google.com, Yahoo.com, and ask.com, all of their requests will be sent to the Enterprise Server in phaseit.net., only to reduce complexity.

The web page request returns results after the latency (variable), as shown below. If the program sends requests in order, it takes about 15 + 12 + 9 + 6 + 3 (45) seconds to complete. For example

As shown in Listing 2, it actually takes 15 seconds to complete. Performance increased by three times.

This may be caused by the new stream_select function of PHP V5. Requests are initiated in a conventional way, the method is to open several stream_socket_client and correspond to the http://phaseit.net/demonstration/delay? Delay = $ delay writes get to each stream_socket_client. If you request this URL through a browser, after a few seconds, you will see:

Starting at THU Apr 12 15:05:01 UTC 2007.

Stopping at THU Apr 12 15:05:05 UTC 2007.

4 second delay.

The latency server is implemented as CGI as follows:

 

Listing 3. latency server implementation

#! /Bin/sh

 

Echo "Content-Type: text/html

 

<HTML>

 

Echo "starting at 'date '."

RR = 'echo $ request_uri | sed-E's /.*? //''

Delay = 'echo $ RR | sed-E's/delay = //''

Sleep $ Delay

Echo "<br> stopping at 'date '."

Echo "<br> $ delay second delay. </body>

 

Although the Special implementations in listing 3 are specific to Unix, almost all implementations in this article will be well applied to Windows (especially Versions later than Windows 98) or php unix installation. In particular, listing 1 can be hosted on any operating system. Therefore, both Linux and Mac OS X are UNIX variants, so all the code here can be run in either of them.

Send requests to the delayed server in the following order.

 

List 4. Process startup sequence

Delay = 15

Delay = 12

Delay = 9

Delay = 6

Delay = 3

Stream_select is used to receive results as quickly as possible. In this case, the execution order is the opposite of the order in which the results are sent. 3 seconds later, the first page is ready for reading. This part of the program also conforms to the conventional PHP-in this example, use fread. Just like in other PHP programs, reading can be done well through fgets.

The processing will continue in the same way. The program stops in stream_select until the data is ready. The important thing is that the program will start to read data as long as any connection has data, regardless of the order. This is a method by which a program processes multiple tasks or concurrently results from multiple requests.

Note that this does not cause any burden on the host CPU. We often encounter such network connection programs that use fread in the while by rapidly increasing the CPU usage to 100%. This is not the case here, because stream_select has the attributes required for immediate response (as long as there is any read information ), however, it will generate negligible CPU load during the wait time between read operations.

 

Required knowledge about stream_select ()

Such event-based programming is not the most basic. Although Listing 1 is simplified to containing only the most basic elements, any encoding that involves callback or coordination as a necessary element of a multitasking application is more unfamiliar than a simple program order. In this case, most of the challenges are concentrated on the $ read array. Note that it is a reference; stream_select returns important information by changing the content of $ read. Just as pointers are the biggest stumbling block to C, referencing seems to be the most tricky part of PHP.

You can use this technology to send requests to any external web site, so that your program will receive all results as soon as possible without waiting for other requests. In fact, this technology will correctly process all TCP/IP connections, not just the connections on the Web port 80. Therefore, you can manage LDAP retrieval, SMTP transmission, and SOAP requests in general.

But that's not all. PHP V5 manages various connections such as "streams", not just simple sockets. The PHP client URL Library (curl) supports HTTPS certificates, FTP uploads, and cookies. (Curl allows PHP applications to connect to the server using various protocols ). Since curl provides a stream interface, the connection is transparent from the program perspective. The next section will show how stream_select transfers local computing.

Pay attention to stream_select. It is still working on documentation, because even the latest PHP books are not related to it. Several code examples that can be obtained on the Web cannot work at all or are confusing. The second and third parameters of stream_select are used to manage the write and exception channels corresponding to the read channel in Listing 1 and should always be null. Except for a few exceptions, selecting these two parameters in the writable or abnormal channel is incorrect. Unless you have experience, please stick to the readable choice.

In addition, at least before PHP v5.1.2, stream_select has obvious errors. The most important thing is that you cannot trust the return value of a function. Although I have not yet debugged the implementation, experience tells me that you can safely test the count ($ read) in Listing 1, but the return value of the test stream_select itself is not safe (although there is an official document ).

 

Local PHP concurrency

Examples and most of the above discussions mainly discuss how to manage several remote resources at the same time and receive the results, rather than waiting to process each request in the order of the initial request. This must be an important application of PHP concurrency. The actual application speed can sometimes be increased by 10 times or more.

What if performance declines? Is there a way to speed up the PHP results that are limited by local processing? There are multiple methods. If there is any difference, these methods are not as well-known as socket-oriented methods in Listing 1. There are many reasons for this situation, including:

Most PHP pages are fast enough-better performance is an advantage, but it is not worth investing in new code.

Using PHP on a web page can discard some minor performance improvements-when the only value criterion is the time required to deliver the entire web page, it is not important to reschedule the calculation to get intermediate results faster.

PHP cannot control local bottlenecks-users may complain about taking 8 seconds to extract details of account records, but it is likely to be a database processing or some other PHP external resource constraints. Even if PHP processing is reduced to zero, it takes more than 7 seconds to simply search.

Even few constraints are parallel-assuming that a specific page will calculate the suggested transaction price for a specific list of common shares, and the calculation is very complex and takes some time. In essence, computing may be executed sequentially. There is no obvious way to divide it into "team collaboration ".

Few PHP programmers are aware of the potential of PHP to achieve concurrency. Among the few who have the need to use parallel performance, most of the people I met all say that PHP "does not support Threads" and is willing to use the existing computing model.

However, sometimes we can do better. Assuming that the PHP page needs to calculate the two stock prices, the two may need to be compared, and the underlying host is just a multi-processor. In this case, by allocating two completely different and time-consuming computations to different processors, the performance may be improved by almost twice.

Such instances are rare in all PHP computing fields. However, since I have found no precise records everywhere, I need to include a model for such acceleration.

 

Listing 5. latency server implementation

<? Php <br/> echo "program starts ". date ('H: I: s '). ". /n "; </P> <p> $ timeout = 10; <br/> $ streams = array (); <br/> $ handles = array (); </P> <p>/* first launch a program with a delay of three seconds, then <br/> one which returns after only one second. */<br/> $ delay = 3; <br/> for ($ id = 0; $ id <= 1; $ id ++) {<br/> $ error_log = "/tmp/error ". $ id. ". TXT "<br/> $ descriptorspec = array (<br/> 0 => array (" pipe "," R "), <Br/> 1 => array (" pipe "," W "), <br/> 2 => array (" file ", $ error_log, "W") <br/>); <br/> $ cmd = 'sleep '. $ delay. '; echo "finished with delay '. <br/> $ delay. '". '; <br/> $ handles [$ id] = proc_open ($ cmd, $ descriptorspec, $ pipes ); <br/> $ streams [$ id] = $ pipes [1]; <br/> $ all_pipes [$ id] = $ pipes; <br/> $ delay-= 2; <br/>}</P> <p> while (count ($ streams )) {<br/> $ READ = $ streams; <br/> stream_select ($ Read, $ W = NULL, $ e = NULL, $ timeout); <br/> foreach ($ read as $ R) {<br/> $ id = array_search ($ R, $ strea ** ms); <br/> echo stream_get_contents ($ all_pipes [$ id] [1]); <br/> If (feof ($ R) {<br/> fclose ($ all_pipes [$ id] [0]); <br/> fclose ($ all_pipes [$ id] [1]); <br/> $ return_value = proc_close ($ handles [$ id]); <br/> unset ($ streams [$ id]); <br/>}< br/>?> 

 

This program generates the following output:

Program starts at 10:28:41.

Finished with delay of 1.

Finished with delay of 3.

 

The key here is that PHP starts two independent sub-processes, retrieves the output of the first process to be completed, and then retrieves the output of the second process, even if the latter is started earlier. If the host is a multi-processor computer and the operating system is correctly configured, the operating system itself is responsible for allocating subprograms to different processors. This is a good way to use PHP in a multi-processor host.

 

Conclusion

PHP supports multiple tasks. PHP does not support threads according to the methods used by other languages such as Java programming language or C ++. However, the above example shows that PHP has more than imagined acceleration potential.

 

------------------------------------------------------- The End Of The Post -----------------------------------------------------

From: http://www.ibm.com/developerworks/cn/opensource/os-php-multitask/index.html? CA = Drs-CN

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.