PHP communicates with Golang
A scene I encountered recently: phpThe project needs to use a third-party function (stammering word segmentation) , and github happens to have a class library written in Golang. Then the question arises, how to achieve communication between different languages. What about?
Conventional solution:
- ##Write an http/TCP service in Golang, and php communicates with Golang through http/TCP
- Encapsulate Golang as a php extension
- PHP calls the Golang executable file through system commands
- http request, network I/O will consume a lot of time
- Need to encapsulate a lot of code
- Every time PHP calls a Golang program, it needs to be initialized once, which consumes a lot of time.
- The Golang program is only initialized once (because initialization is time-consuming)
- All requests do not need to go through the network
- Try not to modify the code a lot
- Simple Golang encapsulation, compile the third-party class library into an executable file
- PHP and Golang communicate through two-way pipelines
2: Best performance (IPC communication is the best way to communicate between processes)
3: No network requests are required, saving a lot of time
4: The program only needs to be initialized once and remains in memory.
- 1: Original call demo in the class library
package main import ( "fmt" "github.com/yanyiwu/gojieba" "strings" ) func main() { x := gojieba.NewJieba() defer x.Free() s := "小明硕士毕业于中国科学院计算所,后在日本京都大学深造" words := x.CutForSearch(s, true) fmt.Println(strings.Join(words, "/")) }
Copy after loginSave the file as main.go, just Can run
- 2: The adjusted code is:
It only takes a few simple adjustments to achieve: receiving from standard input
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") } } }
Copy after loginString , after word segmentation, output
Test:# go build test # ./test # //等待用户输入,输入”这是一个测试“ # 这是 一个 测试 //程序
Copy after login - 3: Use cat to communicate with Golang for a simple test
Normal output, indicating that cat can interact with Golang normally
//准备一个title.txt,每行是一句文本 # cat title.txt | ./test
Copy after login - 4: PHP communicates with Golang
The communication between cat and Golang shown above uses a single to the pipeline. That is: data can only be passed from cat to Golang. The data output by Golang is not passed back to cat, but is output directly to the screen. But the requirement in the article is: php communicates with Golang. That is, php needs to pass data to Golang, and Golang must also return the execution results to php. Therefore, a bidirectional pipeline needs to be introduced.
The use of pipes in PHP: popen("/path/test"), I won’t go into details because this method cannot solve the problem in the article.
Bidirectional pipe:$descriptorspec = array( 0 => array("pipe", "r"), 1 => array("pipe", "w") ); $handle = proc_open( '/webroot/go/src/test/test', $descriptorspec, $pipes ); fwrite($pipes['0'], "这是一个测试文本\n"); echo fgets($pipes[1]);
Copy after loginExplanation: Use proc_open to open a process and call the Golang program. At the same time, a bidirectional pipeline pipesarray is returned. PHP writes data to $pipe['0'] and reads data from $pipe['1'].
Let any language communicate through a two-way pipe. (All languages will implement pipeline related content)
Test: Throughcomparison test, calculate the time occupied by each process. The title.txt file mentioned below contains 1 million lines of text. Each line of text is the product title taken from the b2b platform
1: The overall process takes timetime<a href="http://www.php.cn/wiki/1268.html" target="_blank"> cat title.txt | ./test > /dev/</a>null<a href="http://www.php.cn/wiki/62.html" target="_blank"></a>
functionProcess cat reads out text
#2: It takes time to calculate the word segmentation- Transmit data into Golang through pipes
- Golang processes the data and returns the results to the screen
. Solution: Remove the call to the word segmentation function, that is: CommentRemove the line of code in the Golang source code that calls the word segmentation functiontime cat title.txt | ./test > /dev /null## Time consuming: 1.817 seconds, the time consumed includes:
Process cat reads text
- Pass data into Golang through pipes
- Golang processes the data
- and returns the results to the screen
分词耗时 = (第一步耗时) - (以上命令所耗时)
分词耗时 : 14.819 - 1.817 = 13.002秒
3:测试cat进程与Golang进程之间通信所占时间time cat title.txt > /dev/null
耗时:0.015秒,消耗时间包含:
进程cat读出文本
通过管道将数据传入Golang
go处理数据,将结果返回到屏幕
管道通信耗时:(第二步耗时) - (第三步耗时)
管道通信耗时: 1.817 - 0.015 = 1.802秒
4:PHP与Golang通信的时间消耗
编写简单的php文件:
<?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);
流程与上面基本一致,读出title.txt内容,通过双向管道传入Golang进程分词后,再返回给php (比上面的测试多一步:数据再通过管道返回)time php popen.php > /dev/null
耗时:24.037秒,消耗时间包含:
进程PHP读出文本
通过管道将数据传入Golang
Golang处理数据
Golang将返回结果再写入管道,PHP通过管道接收数据
将结果返回到屏幕
结论:
1 :整个分词过程中的耗时分布
使用cat控制逻辑耗时: 14.819 秒 使用PHP控制逻辑耗时: 24.037 秒(比cat多一次管道通信) 单向管道通信耗时: 1.8 秒 Golang中的分词函数耗时: 13.002 秒
2:分词函数的性能: 单进程,100万商品标题分词,耗时13秒
以上时间只包括分词时间,不包括词典载入时间。但在本方案中,词典只载入一次,所以载入词典时间可以忽略(1秒左右)
3:PHP比cat慢 (这结论有点多余了,呵呵)
语言层面慢: (24.037 - 1.8 - 14.819) / 14.819 = 50%
单进程对比测试的话,应该不会有哪个语言比cat更快。
相关问题:
-
1:以上Golang源码中写的是一个循环,也就是会一直从管道中读数据。那么存在一个问题:是不是php进程结束后,Golang的进程还会一直存在?
管道机制自身可解决此问题。管道提供两个接口:读、写。当写进程结束或者意外挂掉时,读进程也会报错,以上Golang源代码中的err逻辑就会执行,Golang进程结束。
但如果PHP进程没有结束,只是暂时没有数据传入,此时Golang进程会一直等待。直到php结束后,Golang进程才会自动结束。 -
2:能否多个php进程并行读写同一个管道,Golang进程同时为其服务?
不可以。管道是单向的,如果多个进程同时向管道中写,那Golang的返回值就会错乱。
可以多开几个Golang进程实现,每个php进程对应一个Golang进程。
The above is the detailed content of PHP communicates with Golang. For more information, please follow other related articles on the PHP Chinese website!

Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics



JWT is an open standard based on JSON, used to securely transmit information between parties, mainly for identity authentication and information exchange. 1. JWT consists of three parts: Header, Payload and Signature. 2. The working principle of JWT includes three steps: generating JWT, verifying JWT and parsing Payload. 3. When using JWT for authentication in PHP, JWT can be generated and verified, and user role and permission information can be included in advanced usage. 4. Common errors include signature verification failure, token expiration, and payload oversized. Debugging skills include using debugging tools and logging. 5. Performance optimization and best practices include using appropriate signature algorithms, setting validity periods reasonably,

Static binding (static::) implements late static binding (LSB) in PHP, allowing calling classes to be referenced in static contexts rather than defining classes. 1) The parsing process is performed at runtime, 2) Look up the call class in the inheritance relationship, 3) It may bring performance overhead.

What are the magic methods of PHP? PHP's magic methods include: 1.\_\_construct, used to initialize objects; 2.\_\_destruct, used to clean up resources; 3.\_\_call, handle non-existent method calls; 4.\_\_get, implement dynamic attribute access; 5.\_\_set, implement dynamic attribute settings. These methods are automatically called in certain situations, improving code flexibility and efficiency.

In PHP8, match expressions are a new control structure that returns different results based on the value of the expression. 1) It is similar to a switch statement, but returns a value instead of an execution statement block. 2) The match expression is strictly compared (===), which improves security. 3) It avoids possible break omissions in switch statements and enhances the simplicity and readability of the code.

Backend learning path: The exploration journey from front-end to back-end As a back-end beginner who transforms from front-end development, you already have the foundation of nodejs,...

In PHP, you can effectively prevent CSRF attacks by using unpredictable tokens. Specific methods include: 1. Generate and embed CSRF tokens in the form; 2. Verify the validity of the token when processing the request.

Strict types in PHP are enabled by adding declare(strict_types=1); at the top of the file. 1) It forces type checking of function parameters and return values to prevent implicit type conversion. 2) Using strict types can improve the reliability and predictability of the code, reduce bugs, and improve maintainability and readability.

Which libraries in Go are developed by large companies or well-known open source projects? When programming in Go, developers often encounter some common needs, ...
