PHP communique avec Golang
Une scène que j'ai rencontrée récemment : phpUne fonction tierce (segmentation des mots balbutiants) doit être utilisée dans le projet, et il se trouve qu'il y a une bibliothèque de classes écrite en Golang sur github Alors la question se pose, comment réaliser la communication entre différentes langues. . Qu'en est-il ?
Solution conventionnelle :
Écrivez un service http/TCP en Golang, et php communique avec Golang via http/TCP
-
Golang est encapsulé sous forme d'extension php
PHP appelle le fichier exécutable Golang via les commandes système
Problèmes existants :
Requêtes http, les E/S réseau prendront beaucoup de temps
Beaucoup de code doit être encapsulé
Chaque fois que PHP appelle un programme Golang, il doit être initialisé, ce qui prend beaucoup de temps
Objectifs d'optimisation :
-
Le programme Golang n'est initialisé qu'une seule fois (car l'initialisation prend du temps)
Toutes les requêtes n'ont pas besoin de passer par le réseau
-
Essayez de ne pas trop modifier le code
Solution :
Package Golang simple, compilez la bibliothèque de classes tierce dans un exécutable fichier
-
PHP et Golang communiquent via des tuyaux bidirectionnels
Avantages de l'utilisation de la communication par canal bidirectionnel :
1 : encapsulation minimale de la bibliothèque de classes Golang originale est requise
2 : Meilleures performances (la communication IPC est le meilleur moyen de communiquer entre les processus)
3 : Aucune requête réseau n'est requise, ce qui permet de gagner beaucoup de temps
4 : Le programme ne doit être initialisé qu'une seule fois et reste en mémoire
Étapes spécifiques de mise en œuvre :
-
1 : Démo d'appel originale dans la bibliothèque de classe
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, "/")) }
Copier après la connexionEnregistrez le fichier sous main.go , vous pouvez exécuter
- 2 : Le code ajusté est :
Cela ne prend qu'un quelques ajustements simples à réaliser : à partir de l'entrée standard Recevez
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") } } }
Copier après la connexionchaîne , puis sortie
après la segmentation des mots Test :# go build test # ./test # //等待用户输入,输入”这是一个测试“ # 这是 一个 测试 //程序
Copier après la connexion3 : Utilisez cat pour communiquer avec Golang pour un test simple -
Sortie normale, indiquant que cat peut interagir avec Golang normalement
//准备一个title.txt,每行是一句文本 # cat title.txt | ./test
Copier après la connexion4 : PHP communique avec Golang -
Chat illustré ci-dessus Pour communiquer avec Golang, un tuyau unidirectionnel est utilisé. Autrement dit : les données ne peuvent être transmises que de cat à Golang. Les données sorties par Golang ne sont pas renvoyées à cat, mais sont directement affichées à l'écran. Mais l'exigence de l'article est la suivante : php communique avec Golang. Autrement dit, php doit transmettre les données à Golang, et Golang doit également renvoyer les résultats d'exécution à php. Un pipeline bidirectionnel doit donc être mis en place.
L'utilisation des pipes en PHP :
, je n'entrerai pas dans les détails car cette méthode ne peut pas résoudre le problème de l'article.popen("/path/test")
Pipeline bidirectionnel :Explication : Utilisez proc_open pour ouvrir un processus et appeler le programme Golang. Dans le même temps, un pipeline bidirectionnel pipes$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]);
Copier après la connexionarray est renvoyé. PHP écrit les données dans $pipe['0'] et lit les données dans $pipe['1'].
Eh bien, peut-être avez-vous découvert que je suis le fichier titre, et l'accent ici n'est pas seulement sur la façon dont PHP et Golang communiquent. Au lieu de cela, nous introduisons une méthode :
(Toutes les langues implémenteront le contenu lié au pipeline) Test :
Grâce au
test de comparaison, calculez le temps pris par chaque processus. Le fichier title.txt mentionné ci-dessous contient 1 million de lignes de texte. Chaque ligne de texte est le titre du produit extrait de la plateforme b2b1 : Le processus global prend du temps
<a. href="http%20://www.php.cn/wiki/1268.html" target="_blank">time<p> cat title.txt ./test > /www.php .cn/wiki/62.html" target="_blank">null<br></p></a.>
<a href="http://www.php.cn/wiki/1268.html" target="_blank">time</a> cat title.txt | ./test > /dev/<a href="http://www.php.cn/wiki/62.html" target="_blank">null</a>
Prend du temps : 14,819 secondes, dont :2 : Il faut du temps pour calculer la fonction de segmentation de mots
- Le processus cat lit le texte
- Transmettre les données à Golang via le tuyau
- Golang traite les données et renvoie le résultat à l'écran
. Solution : Supprimez l'appel de la fonction de segmentation de mots, c'est-à-dire : Commentaire et supprimez la ligne de code qui appelle la segmentation de mots dans le code source de Golang time cat title.txt | ./test > /dev/null
Prend du temps : 1,817 secondes, le temps consommé comprend :
- le processus cat lit le texte
- transfère les données vers Golang via un pipeline
Golang traite les données et renvoie le résultat à l'écran
分词耗时 = (第一步耗时) - (以上命令所耗时)
分词耗时 : 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进程。
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Outils d'IA chauds

Undresser.AI Undress
Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover
Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool
Images de déshabillage gratuites

Clothoff.io
Dissolvant de vêtements AI

Video Face Swap
Échangez les visages dans n'importe quelle vidéo sans effort grâce à notre outil d'échange de visage AI entièrement gratuit !

Article chaud

Outils chauds

Bloc-notes++7.3.1
Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise
Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1
Puissant environnement de développement intégré PHP

Dreamweaver CS6
Outils de développement Web visuel

SublimeText3 version Mac
Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Sujets chauds





JWT est une norme ouverte basée sur JSON, utilisée pour transmettre en toute sécurité des informations entre les parties, principalement pour l'authentification de l'identité et l'échange d'informations. 1. JWT se compose de trois parties: en-tête, charge utile et signature. 2. Le principe de travail de JWT comprend trois étapes: la génération de JWT, la vérification de la charge utile JWT et l'analyse. 3. Lorsque vous utilisez JWT pour l'authentification en PHP, JWT peut être généré et vérifié, et les informations sur le rôle et l'autorisation des utilisateurs peuvent être incluses dans l'utilisation avancée. 4. Les erreurs courantes incluent une défaillance de vérification de signature, l'expiration des jetons et la charge utile surdimensionnée. Les compétences de débogage incluent l'utilisation des outils de débogage et de l'exploitation forestière. 5. L'optimisation des performances et les meilleures pratiques incluent l'utilisation des algorithmes de signature appropriés, la définition des périodes de validité raisonnablement,

Liaison statique (statique: :) implémente la liaison statique tardive (LSB) dans PHP, permettant à des classes d'appel d'être référencées dans des contextes statiques plutôt que de définir des classes. 1) Le processus d'analyse est effectué au moment de l'exécution, 2) Recherchez la classe d'appel dans la relation de succession, 3) il peut apporter des frais généraux de performance.

Quelles sont les méthodes magiques de PHP? Les méthodes magiques de PHP incluent: 1. \ _ \ _ Construct, utilisé pour initialiser les objets; 2. \ _ \ _ Destruct, utilisé pour nettoyer les ressources; 3. \ _ \ _ Appel, gérer les appels de méthode inexistants; 4. \ _ \ _ GET, Implémentez l'accès à l'attribut dynamique; 5. \ _ \ _ SET, Implémentez les paramètres d'attribut dynamique. Ces méthodes sont automatiquement appelées dans certaines situations, améliorant la flexibilité et l'efficacité du code.

Dans PHP8, les expressions de correspondance sont une nouvelle structure de contrôle qui renvoie différents résultats en fonction de la valeur de l'expression. 1) Il est similaire à une instruction Switch, mais renvoie une valeur au lieu d'un bloc d'instruction d'exécution. 2) L'expression de correspondance est strictement comparée (===), ce qui améliore la sécurité. 3) Il évite les éventuelles omissions de rupture dans les instructions de commutation et améliore la simplicité et la lisibilité du code.

En PHP, vous pouvez prévenir efficacement les attaques du CSRF en utilisant des jetons imprévisibles. Les méthodes spécifiques comprennent: 1. Générer et intégrer les jetons CSRF dans la forme; 2. Vérifiez la validité du jeton lors du traitement de la demande.

PHP et Python ont chacun leurs propres avantages et choisissent en fonction des exigences du projet. 1.Php convient au développement Web, en particulier pour le développement rapide et la maintenance des sites Web. 2. Python convient à la science des données, à l'apprentissage automatique et à l'intelligence artificielle, avec syntaxe concise et adaptée aux débutants.

Les types stricts en PHP sont activés en ajoutant Declare (strict_types = 1); en haut du fichier. 1) Il force la vérification du type des paramètres de fonction et des valeurs de retour pour éviter la conversion de type implicite. 2) L'utilisation de types stricts peut améliorer la fiabilité et la prévisibilité du code, réduire les bogues et améliorer la maintenabilité et la lisibilité.

Dans PHP, le mot-clé final est utilisé pour empêcher les classes d'être héritées et les méthodes écrasées. 1) Lors du marquage de la classe comme final, la classe ne peut pas être héritée. 2) Lors du marquage de la méthode comme final, la méthode ne peut pas être réécrite par la sous-classe. L'utilisation de mots clés finaux garantit la stabilité et la sécurité de votre code.
