How does PHP communicate with Golang?

Source: Internet
Author: User
This is a creation in Article, where the information may have evolved or changed. How does PHP communicate with Golang?

Recently encountered a scene: PHP project needs to use a third-party function (stuttering participle), and on GitHub there is a class library 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

      //准备一个title.txt,每行是一句文本
    # 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

使用cat控制逻辑耗时:        14.819 秒使用PHP控制逻辑耗时:         24.037 秒(比cat多一次管道通信)单向管道通信耗时:           1.8    秒Golang中的分词函数耗时:     13.002 秒

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 code is written in a loop, that is, 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 solves this problem. 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.
      However, if the PHP process does not end, but temporarily no data is passed in, 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 concurrently?

      No. 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.
      You can open several Golang process implementations, each PHP process corresponding to a golang process.

Finally, it's all nonsense. If you know the plumbing, the two-way pipeline, the above explanation is basically useless to you. But if you don't know the plumbing, debugging the code above is fine, but a little modification is likely to fall out of the hole. Haha, recommend a book, "UNIX Network Programming" Volume one or two, all look, perhaps to see two months, but it is necessary!

Read more books, read more newspapers, watch less web pages, sleep more!

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.