1. 程式人生 > 其它 >golang rpc 遠端呼叫

golang rpc 遠端呼叫

rpc

1. 面臨的問題
  a. Call 的 id 對映
  b. 序列化和反序列化  json 序列化/反序列化
  c. 網路傳輸
  
  http2.0 ==> rpc
  
### 自己實現的 demo 級別的 rpc 封裝
提供 add 方法方

# -*- coding: utf-8 -*-
# __author__: Frank Li
# 10/7/2021 11:41 AM
import json
from urllib.parse import urlparse, parse_qsl
from http.server import HTTPServer, BaseHTTPRequestHandler

host = ('', 8003)

class AddHandler(BaseHTTPRequestHandler):

    def do_GET(self):
        parsed_url = urlparse(self.path)
        qs = dict(parse_qsl(parsed_url.query))

        a = int(qs.get("a", 0))
        b = int(qs.get("b", 0))
        self.send_response(200)
        self.send_header("content-type", "application")
        self.end_headers()
        self.wfile.write(json.dumps({
            "result": a+b
        }).encode("utf-8")
        )

if __name__ == '__main__':
    server = HTTPServer(host, AddHandler)
    print("啟動 rpc 服務...")
    server.serve_forever()

遠端呼叫客戶端
# -*- coding: utf-8 -*-
# __author__: Frank Li
# 10/7/2021 11:47 AM
import requests
import json


class Client:

    def __init__(self, url):
        self.url = url

    def add(self, a, b):
        res = requests.get(f"{self.url}/?a=1&b=2")
        return json.loads(res.text).get("result")

if __name__ == '__main__':
    client = Client("http://127.0.0.1:8003")
    print(client.add(1,2))

  
# 基於 xml 的 rpc py 庫
# -*- coding: utf-8 -*-
# __author__: Frank Li
# 10/7/2021 12:33 PM
from xmlrpc.server import SimpleXMLRPCServer


class Calculate:
    def add(self, x, y):
        return x+y

    def multiply(self, x, y):
        return x*y

    def substract(self, x, y):
        return x-y

    def divide(self, x, y):
        return x/y

if __name__ == '__main__':
    cal = Calculate()
    server = SimpleXMLRPCServer(("localhost", 8014))

    # 將例項註冊給 rpc server
    server.register_instance(cal)
    print("Listening on port 8014")
    server.serve_forever()

-------=========-----------
# -*- coding: utf-8 -*-
# __author__: Frank Li
# 10/7/2021 12:37 PM
from xmlrpc import client

class RPCClient:

    def __init__(self, url):
        self.client = client.ServerProxy(url)

    def add(self, x, y):
        return self.client.add(x, y)

if __name__ == '__main__':
    rpc_client = RPCClient("http://localhost:8014")
    ret = rpc_client.add(1, 2)
    print(ret)


json-rpc   ==》 jsonrpclib  支援併發, 支援 HTTPS

zeromq  這個 rpc 框架 是否支援 多語言?
zerorpc == zeroMQ + msgpack(訊息序列化二進位制)來實現 類似 grpc 的 功能
通訊模式 ROUTER-DEALER  模擬 grpc 的請求-響應式 和 應答流式
此外他還支援 PUB-SUB 通訊模式的遠端呼叫
zerorpc 實際上依賴 msgpack-python, pyzmq, future, greenlet, gevent
支援 python + nodejs

// go 的 rpc 入門級 demo
package main

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

type HelloService struct {
	
}

// 固定格式如下
func(service *HelloService) Hello(request string, reply *string) error{
	// 返回值是通過修改 reply 的值
	*reply = "hello, "+request
	return nil
}

func main(){
	//1. 例項化 server
	listen, err := net.Listen("tcp", ":1234")
	if err != nil{
		fmt.Println("")
	}

	//2. 註冊處理邏輯 handler
	_ = rpc.RegisterName("HelloService", &HelloService{})


	//3. 啟動服務
	accept, err := listen.Accept()
	rpc.ServeConn(accept)

}



package main

import (
	"fmt"
	"net/rpc"
)

func main(){
	client, err := rpc.Dial("tcp", "localhost:1234")
	if err != nil{
		fmt.Println("連線失敗...", err)
	}
	var reply string
	client.Call("HelloService.Hello", "frank", &reply)
	fmt.Println("reply: ", reply)

}
    
如果有來生,一個人去遠行,看不同的風景,感受生命的活力。。。