最近遭遇したシーン: phpプロジェクトではサードパーティの機能 (吃音の単語分割) を使用する必要があり、github だけを使用する必要があります。 Golang で書かれた クラス ライブラリ が存在します。 そこで問題は、異なる言語間の通信をどのように実装するかです。
従来の解決策: Golang で http/TCP サービスを記述し、php が通信します。 http/TCP を介して Golang と接続する
Golang は PHP 拡張機能としてカプセル化される
PHP はシステムコマンドを介して Golang 実行可能ファイルを呼び出す
-
既存の問題:
http リクエストとネットワーク I/O が消費される多くの時間がかかります
多くのコードをカプセル化する必要があります
PHP が Golang プログラムを呼び出すたびに初期化が必要となり、多くの時間がかかります
最適化目標:
Golang プログラムは 1 回だけ初期化されます (初期化には時間がかかるため)
すべてのリクエストがネットワークを経由する必要はありません
コードをあまり変更しないようにしてください
解決策:
シンプルな Golang パッケージ化、サードパーティのクラス ライブラリを実行可能ファイルにコンパイルします
PHP は双方向パイプラインを通じて Golang と通信します
双方向パイプライン通信を使用する利点:
1: ほんのわずかです元の Golang クラス ライブラリへの変更が必要です カプセル化
3: ネットワーク リクエストが不要で、時間を大幅に節約します
4: プログラムは一度初期化され、メモリに残ります
詳細な実装手順:
1: クラス ライブラリ内の元の呼び出しデモ
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, "/")) }
- ファイルを main.go として保存すると、実行できます
2:調整されたコードは:
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") } } }
ほんの数ステップで行調整が可能: 標準入力から - string
を受け取り、単語分割後に出力
# go build test # ./test # //等待用户输入,输入”这是一个测试“ # 这是 一个 测试 //程序
3: Cat を使用して Golang と通信する簡単なテスト用//准备一个title.txt,每行是一句文本 # cat title.txt | ./test
通常の出力、cat の準備ができていることを示します Golang と通常どおり対話します -
4: PHP は Golang と通信します
上に示した cat と Golang 間の通信は、一方向のパイプライン、つまりデータを使用します。 cat から Golang にのみ転送でき、Golang が出力するデータは同じではありません。cat に戻されるのではなく、画面に直接出力されます。ただし、この記事の要件は、php がデータを に送信する必要があることです。 Golang は実行結果を php に返す必要があるため、双方向パイプラインを導入する必要があります: -
双方向パイプ:$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]);
説明: proc_open を使用してプロセスを開き、Golang プログラムを呼び出します。同時に、双方向パイプラインの Pipes配列popen("/path/test")
,具体就不展开说了,因为此方法解决不了文中的问题。
双向管道:<?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);
解释:使用proc_open打开一个进程,调用Golang程序。同时返回一个双向管道pipes数组,php向$pipe['0']中写数据,从$pipe['1']中读数据。
popen("/path/test")
)。 >, この方法ではこの記事の問題を解決できないため、詳細には触れません 好吧,也许你已经发现,我是标题档,这里重点要讲的并不只是PHP与Golang如何通信。而是在介绍一种方法: 通过双向管道让任意语言通信。(所有语言都会实现管道相关内容)
测试:
通过对比测试,计算出各个流程占用的时间。下面提到的title.txt文件,包含100万行文本,每行文本是从b2b平台取的商品标题
1: 整体流程耗时<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>
耗时:14.819秒,消耗时间包含:
进程cat读出文本
通过管道将数据传入Golang
Golang处理数据,将结果返回到屏幕
2:计算分词函数耗时。方案:去除分词函数的调取,即:注释掉Golang源代码中的调取分词那行的代码time cat title.txt | ./test > /dev/null
が $pipe['0 にデータを書き込みます。 ']、$pipe['1'] の読み取りデータから。
🎜2: 単語の分割を計算します 機能🎜に時間がかかります。解決策: 単語セグメンテーション関数呼び出しを削除します。つまり、Golang ソース コード内の単語セグメンテーション呼び出しをコメント アウトします。コード行 🎜さて、おそらく私がタイトルファイルであることに気づいたでしょう。ここで焦点を当てているのは、PHP と Golang がどのように通信するかだけではありません。代わりに、次の方法を導入します。
- あらゆる言語が双方向パイプを通じて通信できるようにします。
テスト:(すべての言語はパイプライン関連のコンテンツを実装します)
- 比較テスト
に合格し、各プロセスにかかる時間を計算します。以下の title.txt ファイルには 100 万行のテキストが含まれており、各テキスト行は B2B プラットフォームから取得した製品タイトルです1: 全体的なプロセスには時間がかかります
🎜🎜🎜 所要時間: 14.819 秒 (以下を含む) 🎜🎜🎜🎜Process cat がテキストを読み取る🎜🎜🎜🎜 パイプラインを介して Golang にデータを転送する🎜🎜🎜🎜 Golang はデータを処理し、結果を画面に返します🎜🎜🎜<a href="http:/%20/www.php%20.cn/wiki/1268.html" target="_blank">time</a>
cat title.txt | ./test > /dev/null
time cat title.txt | ./test >/dev/null
🎜🎜🎜 消費時間: 1.817 秒、消費時間は次のとおりです。 🎜🎜🎜🎜 プロセス cat は、テキスト🎜 🎜🎜🎜データを Golang にパイプ🎜🎜🎜🎜🎜Golang はデータを処理🎜し、結果を画面に返します🎜 分词耗时 = (第一步耗时) - (以上命令所耗时)
分词耗时 : 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进程。
以上がPHP は Golang と通信しますの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

データベースストレージセッションを使用することの主な利点には、持続性、スケーラビリティ、セキュリティが含まれます。 1。永続性:サーバーが再起動しても、セッションデータは変更されないままになります。 2。スケーラビリティ:分散システムに適用され、セッションデータが複数のサーバー間で同期されるようにします。 3。セキュリティ:データベースは、機密情報を保護するための暗号化されたストレージを提供します。

PHPでのカスタムセッション処理の実装は、SessionHandlerInterfaceインターフェイスを実装することで実行できます。具体的な手順には、次のものが含まれます。1)CussentsessionHandlerなどのSessionHandlerInterfaceを実装するクラスの作成。 2)セッションデータのライフサイクルとストレージ方法を定義するためのインターフェイス(オープン、クローズ、読み取り、書き込み、破壊、GCなど)の書き換え方法。 3)PHPスクリプトでカスタムセッションプロセッサを登録し、セッションを開始します。これにより、データをMySQLやRedisなどのメディアに保存して、パフォーマンス、セキュリティ、スケーラビリティを改善できます。

SessionIDは、ユーザーセッションのステータスを追跡するためにWebアプリケーションで使用されるメカニズムです。 1.ユーザーとサーバー間の複数のインタラクション中にユーザーのID情報を維持するために使用されるランダムに生成された文字列です。 2。サーバーは、ユーザーの複数のリクエストでこれらの要求を識別および関連付けるのに役立つCookieまたはURLパラメーターを介してクライアントに生成および送信します。 3.生成は通常、ランダムアルゴリズムを使用して、一意性と予測不可能性を確保します。 4.実際の開発では、Redisなどのメモリ内データベースを使用してセッションデータを保存してパフォーマンスとセキュリティを改善できます。

APIなどのステートレス環境でのセッションの管理は、JWTまたはCookieを使用して達成できます。 1。JWTは、無国籍とスケーラビリティに適していますが、ビッグデータに関してはサイズが大きいです。 2.cookiesはより伝統的で実装が簡単ですが、セキュリティを確保するために慎重に構成する必要があります。

セッション関連のXSS攻撃からアプリケーションを保護するには、次の測定が必要です。1。セッションCookieを保護するためにHTTPonlyとセキュアフラグを設定します。 2。すべてのユーザー入力のエクスポートコード。 3.コンテンツセキュリティポリシー(CSP)を実装して、スクリプトソースを制限します。これらのポリシーを通じて、セッション関連のXSS攻撃を効果的に保護し、ユーザーデータを確保できます。

PHPセッションのパフォーマンスを最適化する方法は次のとおりです。1。遅延セッション開始、2。データベースを使用してセッションを保存します。これらの戦略は、高い並行性環境でのアプリケーションの効率を大幅に改善できます。

thesession.gc_maxlifettinginttinginphpdethinesthelifsessessiondata、setinseconds.1)it'sconfiguredinphp.iniorviaini_set()。 2)AbalanceSneededToAvoidPerformanceIssues andunexpectedLogouts.3)php'sgarbagecollectionisisprobabilistic、影響を受けたBygc_probabi

PHPでは、session_name()関数を使用してセッション名を構成できます。特定の手順は次のとおりです。1。session_name()関数を使用して、session_name( "my_session")などのセッション名を設定します。 2。セッション名を設定した後、session_start()を呼び出してセッションを開始します。セッション名の構成は、複数のアプリケーション間のセッションデータの競合を回避し、セキュリティを強化することができますが、セッション名の一意性、セキュリティ、長さ、設定タイミングに注意してください。


ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

Video Face Swap
完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

人気の記事

ホットツール

MantisBT
Mantis は、製品の欠陥追跡を支援するために設計された、導入が簡単な Web ベースの欠陥追跡ツールです。 PHP、MySQL、Web サーバーが必要です。デモおよびホスティング サービスをチェックしてください。

EditPlus 中国語クラック版
サイズが小さく、構文の強調表示、コード プロンプト機能はサポートされていません

ZendStudio 13.5.1 Mac
強力な PHP 統合開発環境

Safe Exam Browser
Safe Exam Browser は、オンライン試験を安全に受験するための安全なブラウザ環境です。このソフトウェアは、あらゆるコンピュータを安全なワークステーションに変えます。あらゆるユーティリティへのアクセスを制御し、学生が無許可のリソースを使用するのを防ぎます。

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)
