PHP and Golang Communication

Source: Internet
Author: User
A recently encountered scene: http://www.php.cn/"target=" _blank ">php project needs to use a third-party function (stuttering participle), and GitHub has a class library that is written in Golang. So the question is, how do you achieve communication between different languages?

The general scenario:

    • Write a http/tcp service with Golang, PHP communicates with Golang via HTTP/TCP

    • The Golang is more encapsulated as a PHP extension.

    • PHP uses system commands to fetch Golang executable files.

Problems that exist:

    • HTTP requests, network I/O will consume a lot of time

    • Need to encapsulate a lot of code

    • PHP every time the Golang program, you need to initialize, time consuming a lot

Optimization objectives:

    • Golang program is initialized only once (because initialization is time-consuming)

    • All requests do not need to go to the network

    • Try not to change the code a lot

Solution:

    • A simple Golang package that compiles a third-party class library into an executable file

    • PHP and Golang communicate through two-way pipelines

Advantages of using two-way pipeline communication:

1: Only a few packages of the original Golang class library are required
2: Best Performance (IPC communication is the best way to communicate between processes)
3: No need to go network request, save a lot of time
4: The program only needs to be initialized once and remains in memory

Specific implementation steps:

  • 1: Original fetch demo in class library

          Package main      Import (          "FMT"          "Github.com/yanyiwu/gojieba" "          Strings"      )      func main () {          x: = Gojieba. Newjieba ()          defer x.free ()          s: = "Xiao Ming Master graduated from the Institute of Chinese Academy of Sciences, after studying at Kyoto University in Japan"          Words: = X.cutforsearch (S, true)          FMT. PRINTLN (Strings. Join (words, "/"))      }

    Save the file as Main.go and you can run it

  • 2: The adjusted code is:

          Package main      Import (          "Bufio"          "FMT" "Github.com/yanyiwu/gojieba" "          io" "          os" "          Strings"      )      Func Main () {          x: = Gojieba. Newjieba (              "/data/tmp/jiebadict/jieba.dict.utf8",               "/data/tmp/jiebadict/hmm_model.utf8",               "/data/ Tmp/jiebadict/user.dict.utf8 "          )          defer x.free ()          inputreader: = Bufio. Newreader (OS. Stdin)          for {              s, err: = inputreader.readstring (' \ n ')              if err! = Nil && Err = = Io. EOF {                  break              }              s = strings. Trimspace (s)              if s! = "" {                  words: = X.cutforsearch (S, true)                  FMT. PRINTLN (Strings. Join (words, ""))              } else {                  fmt. Println ("Get Empty \ n")}}}      

    Only a few simple lines of adjustment are needed to achieve: receive string from standard input, pass word and output
    Test:

      # Go build Test  #./test  #//wait for user input, enter "This is a test"  # This is a test//program
  • 3: Simple test with cat and Golang communication

      Prepare a title.txt, each line is a sentence of text  # cat Title.txt |./test

    Normal output, which means that cat has been able to interact properly with Golang.

  • 4:php and Golang Communication
    The cat shown above communicates with the Golang using a unidirectional pipe. That is, the data can only be passed from cat to Golang, and the data Golang output is not passed back to cat, but is output directly to the screen. However, the requirement in this paper is: PHP communicates with Golang. That is, PHP will pass data to Golang, and Golang must return the execution results to PHP. Therefore, two-way pipelines need to be introduced.
    The use of pipelines in PHP: popen("/path/test") Specifically, do not expand, because this method does not solve the problem in the article.
    Bidirectional piping:

          $descriptorspec = Array (0 = = Array (           "pipe", "R"),             1 = = Array ("Pipe", "w")      );      $handle = Proc_open (          '/webroot/go/src/test/test ',           $descriptorspec,           $pipes      );      Fwrite ($pipes [' 0 '], "This is a test text \ n");      Echo fgets ($pipes [1]);

    Explanation: Use Proc_open to open a process and invoke the Golang program. Also returns a bidirectional pipe pipes array, PHP writes data to $pipe[' 0 '], reading data from $pipe[' 1 '].

Well, maybe you've found out that I'm the title file, and the focus here is not just about how PHP communicates with Golang. Instead, it introduces a way to communicate in any language through a two-way pipeline. (all languages will implement pipeline related content)

Test:

The time taken by each process is calculated by comparing the tests . The Title.txt file mentioned below contains 1 million lines of text, and each line of text is a product title taken from the business-to-business platform

1: Overall process time-consuming
time cat title.txt | ./test > /dev/null

Time-consuming: 14.819 seconds, consumption times include:

  • Process Cat read out text

  • Passing data to Golang through a pipeline

  • Golang processing data, returning the results to the screen

2: Calculate the time-consuming function of word breaker. Scenario: Remove the word-breaker function, that is: Comment out the Golang source code of the word to the line of the code
time cat title.txt | ./test > /dev/null

Time consuming: 1.817 seconds, consumption time includes:

  • Process Cat read out text

  • Passing data to Golang through a pipeline

  • Golang processing Data , returning the results to the screen

participle time consuming = (The first step takes time)-(The above command is time consuming)
participle time: 14.819-1.817 = 13.002 seconds

3: Test the time taken to communicate between the cat process and the Golang process
time cat title.txt > /dev/null

Time-consuming: 0.015 seconds, consumption times include:

  • Process Cat read out text

  • Passing data to Golang through a pipeline

  • Go process data , return the results to the screen

Pipeline communication Time consuming:(second step takes time)-(the third step takes time)
Pipeline Communication time: 1.817-0.015 = 1.802 seconds

Time consumption of 4:php and Golang communication
Write a simple PHP file:

        <?php            $descriptorspec = Array (0 = = Array (                 "pipe", "R"),                 1 = = Array ("Pipe", "w")            );            $handle = Proc_open (                '/webroot/go/src/test/test ',                 $descriptorspec,                 $pipes            );            $fp = fopen ("Title.txt", "RB");            while (!feof ($fp)) {                fwrite ($pipes [' 0 '], trim (fgets ($FP)). " \ n ");                Echo fgets ($pipes [1]);            }            Fclose ($pipes [' 0 ']);            Fclose ($pipes [' 1 ']);            Proc_close ($handle);

The process is basically the same as above, read out the Title.txt content, through the bidirectional pipeline into the Golang process participle, and then return to PHP (more than one step above the test: Data again through the pipeline back)
time php popen.php > /dev/null

Time-consuming: 24.037 seconds, consumption times include:

  • Process PHP read out text

  • Passing data to Golang through a pipeline

  • Golang processing Data

  • Golang returns the results to the pipeline, and PHP receives the data through the pipeline

  • Return the results to the screen

Conclusion:

1: Time-consuming distribution throughout the word segmentation process

Using Cat control logic time consuming:        14.819 seconds using PHP control logic time:         24.037 seconds (one more pipe communication than cat) time consuming:           1.8    seconds the word breaker function in Golang time:     13.002 Seconds

2: The performance of the word breaker function: single process, 1 million product title participle, time 13 seconds
The above time only includes the word breaker time, not including the dictionary loading time. However, in this scenario, the dictionary is loaded only once, so loading the dictionary time can be ignored (about 1 seconds)

3:php is slower than cat (this conclusion is a bit superfluous, hehe)
Language level Slow: (24.037-1.8-14.819)/14.819 = 50%
Single-process comparison test, there should be no language faster than cat.

Related issues:

    • 1: The above Golang source is written in a loop, which will always read the data from the pipeline. Then there is a question: is the Golang process still there after the end of the PHP process? The

      Pipeline mechanism itself resolves this issue. The pipeline provides two interfaces: Read and write. When the write process ends or accidentally hangs, the read process will also error, the above Golang source code in the Err logic will be executed, Golang process end.
      But if the PHP process does not end, only temporarily no data is passed in, at which point the Golang process waits. The Golang process will not end automatically until after PHP is finished.

    • 2: Can multiple PHP processes read and write to the same pipeline in parallel, and the Golang process serves it at the same time?

      Not available. The pipeline is unidirectional, and if multiple processes are written to the pipeline at the same time, the return value of the Golang will be garbled. The
      can open several Golang process implementations, each of which corresponds to a golang process.

Related Article

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.