PHP實現簡單RPC

来源:https://www.cnblogs.com/993089249a/archive/2019/10/27/11749268.html
-Advertisement-
Play Games

1.什麼是rpc RPC全稱為Remote Procedure Call,翻譯過來為“遠程過程調用”。目前,主流的平臺中都支持各種遠程調用技術,以滿足分散式系統架構中不同的系統之間的遠程通信和相互調用。遠程調用的應用場景極其廣泛,實現的方式也各式各樣。 2.從通信協議的層面 基於HTTP協議的(例如 ...


1.什麼是rpc

RPC全稱為Remote Procedure Call,翻譯過來為“遠程過程調用”。目前,主流的平臺中都支持各種遠程調用技術,以滿足分散式系統架構中不同的系統之間的遠程通信和相互調用。遠程調用的應用場景極其廣泛,實現的方式也各式各樣。

2.從通信協議的層面

基於HTTP協議的(例如基於文本的SOAP(XML)、Rest(JSON),基於二進位Hessian(Binary))
基於TCP協議的(通常會藉助Mina、Netty等高性能網路框架)

3.從不同的開發語言和平臺層面

單種語言或平臺特定支持的通信技術(例如Java平臺的RMI、.NET平臺Remoting)
支持跨平臺通信的技術(例如HTTP Rest、Thrift等)

4.從調用過程來看

同步通信調用(同步RPC)
非同步通信調用(MQ、非同步RPC)

5.常見的幾種通信方式

遠程數據共用(例如:共用遠程文件,共用資料庫等實現不同系統通信)
消息隊列
RPC(遠程過程調用)

6.php實現簡單的rpc

目錄結構


  image.png


rpc服務端

  1 <?php
  2 /**
  3  * User: yuzhao
  4  * CreateTime: 2018/11/15 下午11:46
  5  * Description: Rpc服務端
  6  */
  7 class RpcServer {
  8 
  9     /**
 10      * User: yuzhao
 11      * CreateTime: 2018/11/15 下午11:51
 12      * @var array
 13      * Description: 此類的基本配置
 14      */
 15     private $params = [
 16         'host'  => '',  // ip地址,列出來的目的是為了友好看出來此變數中存儲的信息
 17         'port'  => '', //
 18         'path'  => '' // 服務目錄
 19     ];
 20 
 21     /**
 22      * User: yuzhao
 23      * CreateTime: 2018/11/16 上午12:14
 24      * @var array
 25      * Description: 本類常用配置
 26      */
 27     private $config = [
 28         'real_path' => '',
 29         'max_size'  => 2048 // 最大接收數據大小
 30     ];
 31 
 32     /**
 33      * User: yuzhao
 34      * CreateTime: 2018/11/15 下午11:50
 35      * @var nul
 36      * Description:
 37      */
 38     private $server = null;
 39 
 40     /**
 41      * Rpc constructor.
 42      */
 43     public function __construct($params)
 44     {
 45         $this->check();
 46         $this->init($params);
 47     }
 48 
 49     /**
 50      * User: yuzhao
 51      * CreateTime: 2018/11/16 上午12:0
 52      * Description: 必要驗證
 53      */
 54     private function check() {
 55         $this->serverPath();
 56     }
 57 
 58     /**
 59      * User: yuzhao
 60      * CreateTime: 2018/11/15 下午11:48
 61      * Description: 初始化必要參數
 62      */
 63     private function init($params) {
 64         // 將傳遞過來的參數初始化
 65         $this->params = $params;
 66         // 創建tcpsocket服務
 67         $this->createServer();
 68     }
 69 
 70     /**
 71      * User: yuzhao
 72      * CreateTime: 2018/11/16 上午12:0
 73      * Description: 創建tcpsocket服務
 74 
 75      */
 76     private function createServer() {
 77         $this->server = stream_socket_server("tcp://{$this->params['host']}:{$this->params['port']}", $errno,$errstr);
 78         if (!$this->server) exit([
 79             $errno,$errstr
 80         ]);
 81     }
 82 
 83     /**
 84      * User: yuzhao
 85      * CreateTime: 2018/11/15 下午11:57
 86      * Description: rpc服務目錄
 87      */
 88     public function serverPath() {
 89         $path = $this->params['path'];
 90         $realPath = realpath(__DIR__ . $path);
 91         if ($realPath === false ||!file_exists($realPath)) {
 92             exit("{$path} error!");
 93         }
 94         $this->config['real_path'] = $realPath;
 95     }
 96 
 97     /**
 98      * User: yuzhao
 99      * CreateTime: 2018/11/15 下午11:51
100      * Description: 返回當前對象
101      */
102     public static function instance($params) {
103         return new RpcServer($params);
104     }
105 
106     /**
107      * User: yuzhao
108      * CreateTime: 2018/11/16 上午12:06
109      * Description: 運行
110      */
111     public function run() {
112         while (true) {
113             $client = stream_socket_accept($this->server);
114             if ($client) {
115                 echo "有新連接\n";
116                 $buf = fread($client, $this->config['max_size']);
117                 print_r('接收到的原始數據:'.$buf."\n");
118                 // 自定義協議目的是拿到類方法和參數(可改成自己定義的)
119                 $this->parseProtocol($buf,$class, $method,$params);
120                 // 執行方法
121                 $this->execMethod($client, $class, $method, $params);
122                 //關閉客戶端
123                 fclose($client);
124                 echo "關閉了連接\n";
125             }
126         }
127     }
128 
129     /**
130      * User: yuzhao
131      * CreateTime: 2018/11/16 上午12:19
132      * @param $class
133      * @param $method
134      * @param $params
135      * Description: 執行方法
136      */
137     private function execMethod($client, $class, $method, $params) {
138         if($class && $method) {
139             // 首字母轉為大寫
140             $class = ucfirst($class);
141             $file = $this->params['path'] . '/' . $class . '.php';
142             //判斷文件是否存在,如果有,則引入文件
143             if(file_exists($file)) {
144                 require_once $file;
145                 //實例化類,並調用客戶端指定的方法
146                 $obj = new $class();
147                 //如果有參數,則傳入指定參數
148                 if(!$params) {
149                     $data = $obj->$method();
150                 } else {
151                     $data = $obj->$method($params);
152                 }
153                 // 打包數據
154                 $this->packProtocol($data);
155                 //把運行後的結果返回給客戶端
156                 fwrite($client, $data);
157             }
158         } else {
159             fwrite($client, 'class or method error');
160         }
161     }
162 
163     /**
164      * User: yuzhao
165      * CreateTime: 2018/11/16 上午12:10
166      * Description: 解析協議
167      */
168     private function parseProtocol($buf, &$class, &$method, &$params) {
169         $buf = json_decode($buf, true);
170         $class = $buf['class'];
171         $method = $buf['method'];
172         $params = $buf['params'];
173     }
174 
175     /**
176      * User: yuzhao
177      * CreateTime: 2018/11/16 上午12:30
178      * @param $data
179      * Description: 打包協議
180      */
181     private function packProtocol(&$data) {
182         $data = json_encode($data, JSON_UNESCAPED_UNICODE);
183     }
184 
185 }
186 
187 RpcServer::instance([
188     'host'  => '127.0.0.1',
189     'port'  => 8888,
190     'path'  => './api'
191 ])->run();

rpc 客戶端

 1 <?php
 2 /**
 3  * User: yuzhao
 4  * CreateTime: 2018/11/16 上午12:2
 5  * Description: Rpc客戶端
 6  */
 7 class RpcClient {
 8 
 9     /**
10      * User: yuzhao
11      * CreateTime: 2018/11/16 上午12:21
12      * @var array
13      * Description: 調用的地址
14      */
15     private $urlInfo = array();
16 
17     /**
18      * RpcClient constructor.
19      */
20     public function __construct($url)
21     {
22         $this->urlInfo = parse_url($url);
23     }
24 
25     /**
26      * User: yuzhao
27      * CreateTime: 2018/11/16 上午12:2
28      * Description: 返回當前對象
29      */
30     public static function instance($url) {
31         return new RpcClient($url);
32     }
33 
34     public function __call($name, $arguments)
35     {
36         // TODO: Implement __call() method.
37         //創建一個客戶端
38         $client = stream_socket_client("tcp://{$this->urlInfo['host']}:{$this->urlInfo['port']}", $errno, $errstr);
39         if (!$client) {
40             exit("{$errno} : {$errstr} \n");
41         }
42         $data = [
43             'class'  => basename($this->urlInfo['path']),
44             'method' => $name,
45             'params' => $arguments
46         ];
47         //向服務端發送我們自定義的協議數據
48         fwrite($client, json_encode($data));
49         //讀取服務端傳來的數據
50         $data = fread($client, 2048);
51         //關閉客戶端
52         fclose($client);
53         return $data;
54     }
55 }
56 $cli = new RpcClient('http://127.0.0.1:8888/test');
57 echo $cli->tuzisir1()."\n";
58 echo $cli->tuzisir2(array('name' => 'tuzisir', 'age' => 23));

提供服務的文件

 1 <?php
 2 /**
 3  * User: yuzhao
 4  * CreateTime: 2018/11/16 上午12:28
 5  * Description:
 6  */
 7 
 8 class Test {
 9 
10     public function tuzisir1() {
11         return '我是無參方法';
12     }
13     public function tuzisir2($params) {
14         return $params;
15     }
16 }

效果

你是否有這樣的煩惱,想學習高級技術,缺乏好的高級學習資料,11年架構師授課的TP5、laravel、swoole、swoft、高併發、分散式等資料,官方群:677079770 ,大牛帶你裝比帶你飛

 

image.png

7.RPC的註意事項

性能:影響RPC性能的主要在幾個方面:
1.序列化/反序列化的框架
2.網路協議,網路模型,線程模型等

安全
RPC安全的主要在於服務介面的鑒權和訪問控制支持。

跨平臺
跨不同的操作系統,不同的編程語言和平臺。

 

你是否有這樣的煩惱,想學習高級技術,缺乏好的高級學習資料,11年架構師授課的TP5、laravel、swoole、swoft、高併發、分散式等資料,官方群:677079770 ,大牛帶你裝比帶你飛

 

推薦閱讀: 一:關於PHP在企業級開發領域的訪談 二:淺談 PHP 與手機 APP 開發(API 介面開發) 三:比RBAC更好的許可權認證方式(Auth類認證) 四:2019年PHP面試題附答案(實戰經驗)        
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 我們知道,在Eureka中,可以使用如下方法使Eureka主動下線,那麼本篇文章就來分析一下子這個下線的流程 主要做了這麼幾件事: 1. 解除狀態監聽器 2. 取消心跳、刷新線程 3. 向服務端發起下線通知 4. 停止各個監聽器 服務端接受下線消息 下線消息的處理在 類中 先看具體的下線邏輯,與租約 ...
  • 場景 喜馬拉雅電臺: https://www.ximalaya.com/ 找到一步小說音頻,這裡以下麵為例 https://www.ximalaya.com/youshengshu/16411402/ 博客:https://blog.csdn.net/badao_liumang_qizhi關註公眾號 ...
  • 7 18 輸出10個不重覆的英文字母 (50 分) 隨機輸入一個字元串,把最左邊的10個不重覆的英文字母(不區分大小寫)挑選出來。 如沒有10個英文字母,顯示信息“not found” 輸入格式: 在一行中輸入字元串 輸出格式: 在一行中輸出最左邊的10個不重覆的英文字母或顯示信息“not foun ...
  • 新聞 "F eXchange 2020——徵文通知" "FSSF在忙什麼?2019年第三季度版本" "Miguel強烈推薦使用TensorFlow.NET" "運行在ASP.NET Core 3上的SAFE BookStore" "新的Thoth.Json站點" "Rider 2019.3早期可訪問 ...
  • 1 介紹 集合類可謂是學習必知、編程必用、面試必會的,而且集合的操作十分重要;本文主要講解如何合併集合類,如合併兩個數組,合併兩個List等。通過例子講解幾種不同的方法,有JDK原生的方法,還有使用第三庫的方法。 2 第三方庫 引入十分常用的優秀的第三方庫 和`Apache Commons pom. ...
  • A. Equalize Prices Again time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output You are both a s ...
  • 當我們開始開發項目部署運行時,項目規模不大,只是在一個JVM實例中運行,對同一資源的併發訪問用JDK自帶的鎖機制就可以解決資源同時訪問的問題。而隨著項目的不斷發展,單體應用已經無法滿足日益增長的訪問需求,我們開始考慮多台部署,提高接收客戶端的連接請求,提高項目的吞吐量。一臺變多台,其中不可避免的問題 ...
  • Hello,各位小伙伴大家好,我是小棧君,昨天也就是2019年10月26日,有幸在成都參加了由阿裡舉辦的“Dubbo社區開發者日”。 本次活動匯聚了各方面的大神歡聚一堂,主要是對現有微服務狀態下的技術的痛點和執行流程的分享和解析。近距離的接觸到技術大佬們,面對面的交流,讓人獲益良多。 所以小棧君這裡 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...