日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
一文搞懂RPC,SoEasy!

什么是RPC

RPC的中文是“遠(yuǎn)程過(guò)程調(diào)用”,對(duì)應(yīng)的英文全稱是:Remote Procedure Call,可以簡(jiǎn)單理解為一個(gè)節(jié)點(diǎn)請(qǐng)求另一個(gè)節(jié)點(diǎn)提供的服務(wù)。

請(qǐng)先自行思考一下什么是“本地過(guò)程調(diào)用”,可以更好的理解“遠(yuǎn)程過(guò)程調(diào)用”。

知識(shí)點(diǎn):RPC主要依賴于客戶端與服務(wù)端建立socket鏈接;而HTTP REST實(shí)現(xiàn)通訊的代價(jià)比較高,這是RPC的一個(gè)優(yōu)勢(shì)體現(xiàn)。(gRPC使用http2.0)

為什么用RPC

就是因?yàn)闊o(wú)法在同一個(gè)進(jìn)程內(nèi),或者無(wú)法在同一個(gè)服務(wù)器上通過(guò)本地調(diào)用的方式實(shí)現(xiàn)我們的需求。

HTTP能滿足需求但是不夠高效,所以我們需要使用RPC。

知乎大神的回答[1]

RPC的優(yōu)勢(shì)

  1. RPC能夠跨多種開(kāi)發(fā)工具和平臺(tái)
  2. RPC能夠跨語(yǔ)言調(diào)用
  3. RPC能夠提高系統(tǒng)的可擴(kuò)展性,解耦,提高復(fù)用
  4. RPC相較于HTTP 1.1,傳輸效率更高,性能消耗更小,自帶負(fù)載均衡策略,自動(dòng)實(shí)現(xiàn)服務(wù)治理

RPC和HTTP對(duì)比

  • RPC主要用于公司內(nèi)部的服務(wù)調(diào)用,性能消耗低,傳輸效率高,服務(wù)治理方便。
  • HTTP主要用于對(duì)外的異構(gòu)環(huán)境,瀏覽器接口調(diào)用,APP接口調(diào)用,第三方接口調(diào)用等。
  • RPC和HTTP的詳細(xì)對(duì)別[2]可以看這篇文章,不作為本篇的重點(diǎn)

RPC的使用邊界

通過(guò)和HTTP的對(duì)比,我們可以倒推出RPC的邊界:對(duì)外的異構(gòu)環(huán)境,瀏覽器接口調(diào)用,APP接口調(diào)用,第三方接口調(diào)用。

上述這些都不適合RPC,不知道RPC不適合做什么,比知道RPC能做什么更重要。

RPC入門(mén)1:net/rpc

基本構(gòu)成

  1. RPC的基本構(gòu)成:服務(wù)端,客戶端
  2. 服務(wù)端基本構(gòu)成:結(jié)構(gòu)體,請(qǐng)求結(jié)構(gòu)體,響應(yīng)結(jié)構(gòu)體
  3. 客戶端基本構(gòu)成:請(qǐng)求結(jié)構(gòu)體,響應(yīng)結(jié)構(gòu)體

代碼示例

rpc_service.go

package main

import (
"errors"
"fmt"
"log"
"net"
"net/http"
"net/rpc"
"os"
)

type Arith struct {

}

//請(qǐng)求結(jié)構(gòu)體
type ArithRequest struct {
A int
B int
}

//響應(yīng)結(jié)構(gòu)體
type ArithResponse struct {
Pro int //乘積
Quo int //商
Rem int //余數(shù)
}

//乘積方法
func (this *Arith) Multiply(req ArithRequest,res *ArithResponse) error{
res.Pro = req.A * req.B
return nil
}

//除法運(yùn)算方法
func (this *Arith) Divide(req ArithRequest,res *ArithResponse) error{
if req.B ==0 {
return errors.New("divide by zero")
}
res.Quo = req.A / req.B
res.Rem = req.A % req.B
return nil
}

func main() {
//注冊(cè)rpc服務(wù)
rpc.Register(new(Arith))
//采用http協(xié)議作為rpc載體
rpc.HandleHTTP()

lis,err := net.Listen("tcp","127.0.0.1:8095")
if err!=nil {
log.Fatalln("fatal error:",err)
}

fmt.Fprintf(os.Stdout,"%s","start connection\n")

//常規(guī)啟動(dòng)http服務(wù)
http.Serve(lis,nil)
}

rpc_client.go

package main

import (
"fmt"
"log"
"net/rpc"
)

//算數(shù)運(yùn)算請(qǐng)求結(jié)構(gòu)體
type ArithRequest struct {
A int
B int
}

//響應(yīng)結(jié)構(gòu)體
type ArithResponse struct {
Pro int //乘
Quo int //商
Rem int //余數(shù)
}

func main() {
conn,err := rpc.DialHTTP("tcp","127.0.0.1:8095")
if err!=nil {
log.Fatalln("dialing error:",err)
}

req := ArithRequest{10,20}
var res ArithResponse

err = conn.Call("Arith.Multiply",req,&res) //乘法運(yùn)算
if err!=nil {
log.Fatalln("arith error:",err)
}
fmt.Printf("%d * %d = %d\n",req.A,req.B,res.Pro)

//除法運(yùn)算
err = conn.Call("Arith.Divide",req,&res)
if err!=nil {
log.Fatalln("arith error:",err)
}
fmt.Printf("%d / %d = %d 余數(shù)是:%d",req.A,req.B,res.Quo,res.Rem)
}

運(yùn)行結(jié)果

先啟動(dòng)服務(wù)端,再啟動(dòng)客戶端連接服務(wù)端

//服務(wù)端console
start connection

//客戶端console
10 * 20 = 200
10 / 20 = 0 余數(shù)是:10

RPC入門(mén)2:net/rpc/jsonrpc

實(shí)現(xiàn)跨語(yǔ)言調(diào)用

jsonrpc_server.go

package main

import (
"errors"
"fmt"
"log"
"net"
"net/rpc"
"net/rpc/jsonrpc"
"os"
)

type Arith struct {

}

//請(qǐng)求結(jié)構(gòu)體
type ArithRequest struct {
A int
B int
}

//響應(yīng)結(jié)構(gòu)體
type ArithResponse struct {
Pro int //乘積
Quo int //商
Rem int //余數(shù)
}

//乘積方法
func (this *Arith) Multiply(req ArithRequest,res *ArithResponse) error{
res.Pro = req.A * req.B
return nil
}

//除法運(yùn)算方法
func (this *Arith) Divide(req ArithRequest,res *ArithResponse) error{
if req.B ==0 {
return errors.New("divide by zero")
}
res.Quo = req.A / req.B
res.Rem = req.A % req.B
return nil
}

func main() {
//注冊(cè)rpc服務(wù)
rpc.Register(new(Arith))
//采用http協(xié)議作為rpc載體
rpc.HandleHTTP()

lis,err := net.Listen("tcp","127.0.0.1:8096")
if err!=nil {
log.Fatalln("fatal error:",err)
}

fmt.Fprintf(os.Stdout,"%s","start connection\n")

//接收客戶端請(qǐng)求 并發(fā)處理 jsonrpc
for {
conn,err :=lis.Accept() //接收客戶端連接請(qǐng)求
if err!=nil {
continue
}

//并發(fā)處理客戶端請(qǐng)求
go func(conn net.Conn) {
fmt.Fprintf(os.Stdout,"%s","new client in coming\n")
jsonrpc.ServeConn(conn)
}(conn)
}

//常規(guī)啟動(dòng)http服務(wù)
//http.Serve(lis,nil)
}

jsonrpc_client.go

package main

import (
"fmt"
"log"
"net/rpc/jsonrpc"
)

//算數(shù)運(yùn)算請(qǐng)求結(jié)構(gòu)體
type ArithRequest struct {
A int
B int
}

//響應(yīng)結(jié)構(gòu)體
type ArithResponse struct {
Pro int //乘
Quo int //商
Rem int //余數(shù)
}

func main() {
// 只有這里不一樣
conn,err := jsonrpc.Dial("tcp","127.0.0.1:8096")
if err!=nil {
log.Fatalln("dialing error:",err)
}

req := ArithRequest{9,2}
var res ArithResponse

err = conn.Call("Arith.Multiply",req,&res) //乘法運(yùn)算
if err!=nil {
log.Fatalln("arith error:",err)
}
fmt.Printf("%d * %d = %d\n",req.A,req.B,res.Pro)

//除法運(yùn)算
err = conn.Call("Arith.Divide",req,&res)
if err!=nil {
log.Fatalln("arith error:",err)
}
fmt.Printf("%d / %d = %d 余數(shù)是:%d",req.A,req.B,res.Quo,res.Rem)
}

運(yùn)行結(jié)果

先啟動(dòng)服務(wù)端,再啟動(dòng)客戶端連接服務(wù)端

//服務(wù)端console
start connection

//客戶端console
9 * 2 = 18
9 / 2 = 4 余數(shù)是:1

//服務(wù)端console
new client in coming

RPC入門(mén)3:go php跨語(yǔ)言調(diào)用

Go作為服務(wù)端,PHP作為客戶端

jsonrpc_server.go:和入門(mén)2服務(wù)端的代碼一樣

下面是PHP代碼

jsonrpc_client.php

class JsonRPC
{

private $conn;

function __construct($host, $port)
{
$this->conn = fsockopen($host, $port, $errno, $errstr, 3);
if (!$this->conn) {
return false;
}
}

public function Call($method, $params)
{
if (!$this->conn) {
return false;
}
$err = fwrite($this->conn, json_encode(array(
'method' => $method,
'params' => array($params),
'id' => 0,
)) . "\n");
if ($err === false) {
return false;
}
stream_set_timeout($this->conn, 0, 3000);
$line = fgets($this->conn);
if ($line === false) {
return NULL;
}
return json_decode($line, true);
}
}

$client = new JsonRPC("127.0.0.1", 8096);
$args = array('A' => 9, 'B' => 2);
$r = $client->Call("Arith.Multiply", $args);
printf("%d * %d = %d\n", $args['A'], $args['B'], $r['result']['Pro']);
$r = $client->Call("Arith.Divide", array('A' => 9, 'B' => 2));
printf("%d / %d, Quo is %d, Rem is %d\n", $args['A'], $args['B'], $r['result']['Quo'], $r['result']['Rem']);

如何在本地啟動(dòng)PHP[3] 不作為本文重點(diǎn),可以看這篇文章。

運(yùn)行結(jié)果

本地啟動(dòng)PHP服務(wù):

??http://127.0.0.1/jsonrpc_client.php??

運(yùn)行結(jié)果如下:

9 * 2 = 18 9 / 2, Quo is 4, Rem is 1

總結(jié)

一文入門(mén)RPC,就是如此絲滑,So Easy!

歡迎還在用單體架構(gòu),沒(méi)有使用RPC的同學(xué)們操練起來(lái),尤其是PHP的小伙伴們,卷起來(lái)吧。該學(xué)學(xué)Go語(yǔ)言啦~

相關(guān)資料

[1]知乎大神的回答: https://www.zhihu.com/question/25536695

[2]RPC和HTTP的詳細(xì)對(duì)別: http://www.ccutu.com/244407.html

[3]如何在本地啟動(dòng)PHP: ??https://blog.csdn.net/resilient/article/details/80770531??

本文轉(zhuǎn)載自微信公眾號(hào)「 程序員升級(jí)打怪之旅」,作者「王中陽(yáng)Go」,可以通過(guò)以下二維碼關(guān)注。

轉(zhuǎn)載本文請(qǐng)聯(lián)系「 程序員升級(jí)打怪之旅」公眾號(hào)。


分享題目:一文搞懂RPC,SoEasy!
轉(zhuǎn)載注明:http://m.5511xx.com/article/cdhheij.html