Go RPC (ft. Node.js)

tags: Go Node.js RPC
category: Back-End
description: Go RPC Node.js
created_at: 2021/07/16 12:00:00

cover image


要開始前進分散式系統啦!!

RPC

遠端程序呼叫(Remote Procedure Call),詳細說明跟架構自己查,資料很多

簡單來說就是有一個 Server 上面有一些 function 釋放出來可以讓 client 透過一些通訊協定去連線去呼叫到你要的 function

server.go

package main

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

type Root struct {
    Count int
}

func (r *Root) Sum(ns []int, sum *int) error {
    val := 0
    for _, n := range ns {
        val += n
    }
    *sum = val
    return nil
}

func (r *Root) GetCount(_, val *int) error {
    *val = r.Count
    return nil
}

func (r *Root) CountPlus(n int, val *int) error {
    r.Count += n
    return r.GetCount(nil, val)
}

func main() {
    rpc.Register(new(Root)) // 註冊 Root

    tcpAddr, err := net.ResolveTCPAddr("tcp", ":8085")  // 開放在 8085 port
    if err != nil {
        fmt.Println("ResolveTCPAddr err = ", err)
    }

    listener, err := net.ListenTCP("tcp", tcpAddr)
    if err != nil {
        fmt.Println("ListenTCP err = ", err)
    }

    for {
        conn, err := listener.Accept()
        if err != nil {
            continue
        }
        jsonrpc.ServeConn(conn)
    }
}

client.go

package main

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

func main() {
    client, err := jsonrpc.Dial("tcp", "localhost:8085") // 連到本地 8085 port

    if err != nil {
        fmt.Println("Dial err = ", err)
    }

    var sum int
    err = client.Call("Root.Sum", []int{1, 2, 3}, &sum) // 去 call Root.Sum function,帶入[1, 2, 3],並把結果存到 sum 變數
    if err != nil {
        fmt.Println("Call err = ", err)
    }
    fmt.Println(sum)

    var count int
    err = client.Call("Root.GetCount", nil, &count) // call Root.GetCount 不帶參數,結果存 count 變數
    if err != nil {
        fmt.Println("Call err = ", err)
    }

    fmt.Println(count)

    err = client.Call("Root.CountPlus", 10, &count) // call Root.CountPlus
    if err != nil {
        fmt.Println("Call err = ", err)
    }

    fmt.Println(count)
}

執行第1次 輸出

6
0
10

執行第2次 輸出

6
10
20

...

補充說明

rpc.Register(new(Root)) 相當於

var root Root
rpc.Register(&root)

使用 Node.js call

安裝套件

npm install node-go-jsonrpc

這個套件相當單純,原始碼大約40行,以 Socket 實現。

const JSONRPC  = require('node-go-jsonrpc');

const client = new JSONRPC("localhost", "8085");

(async () => {
    const sum = await client.call('Root.Sum', [[1, 2, 3, 4]]);
    const count = await client.call('Root.CountPlus', [10]);
    console.log(sum, count);
})();

輸出

{ id: 0, result: 10, error: null } { id: 1, result: 10, error: null }
{ id: 0, result: 10, error: null } { id: 1, result: 20, error: null }
{ id: 0, result: 10, error: null } { id: 1, result: 30, error: null }
....



最後更新時間: 2021年07月16日.