前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Golang中的RPC(转载)

Golang中的RPC(转载)

作者头像
lin_zone
发布2020-06-23 16:20:26
5670
发布2020-06-23 16:20:26
举报
文章被收录于专栏:LIN_ZONE
  1. RPC 简介
    1. 远程过程调用(Remote Procedure Call,缩写为 RPC)
    2. 可以将一些比较通用的场景抽象成微服务,然后供其他系统远程调用
    3. RPC 可以基于HTTP协议 也可以基于TCP协议,基于HTTP协议的RPC像是我们访问网页一样(GET/POST/PUT/DELETE/UPDATE),大部分的RPC都是基于TPC协议的(因为基于传输层,效率稍高一些)
    4. 基于TCP 的 RPC 工作过程
      1. 客户端对请求的对象序列化
      2. 客户端连接服务端,并将序列化的对象通过socket 传输给服务端,并等待接收服务端的响应
      3. 服务端收到请求对象后将其反序列化还原客户端的对象
      4. 服务端从请求对象中获取到请求的参数,然后执行对应的方法,得到返回结果
      5. 服务端将其结果序列化并传给客户端,客户端得到响应结果对象后将其反序列化,得到响应结果
  2. Golang中的RPC 注:例子参考 golang实现RPC的几种方式
    1. net/rpc库 注:没办法在其他语言中调用上面例子实现的RPC方法
      1. 服务端 rpc_server.go
代码语言:javascript
复制
package main
import (
  "errors"
  "fmt"
  "log"
  "net"
  "net/http"
  "net/rpc"
  "os"
)
// 算数运算结构体
type Arith struct {
}

type AirthRequest struct {
  A int
  B int
}

// 算数运算请求结构体
type AirthResponse struct {
  Pro int // 成绩
  Quo int // 商
  Rem int // 余数
}

// 乘法运算方法
func (this *Arith) Multiply(req AirthRequest, res *AirthResponse) error {
  res.Pro = req.A * req.B
  return nil
}

// 除法运算
func (this *Arith) Divide(req AirthRequest, res *AirthResponse) 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() {
  rpc.Register(new(Arith))	// 注册rpc服务
  rpc.HandleHTTP()				//采用http协议作为rpc载体
  lis, err := net.Listen("tcp", "127.0.0.1:8905")
  if err != nil {
    log.Fatalln("fatal error:", err)
  }
  fmt.Println(os.Stdout, "%s", "start connect\n")
  http.Serve(lis, nil)
}


 
代码语言:javascript
复制
package main

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

// 运算请求结构体
type AirthRequest struct {
	A int
	B int
}

// 运算响应结构体
type AirthResponse struct {
	Pro int // 乘积
	Quo int // 商
	Rem int // 余数
}

func main() {
	conn, err := rpc.DialHTTP("tcp", "127.0.0.1:8905")
	if err != nil {
		log.Fatalln("dialing error:", err)
	}
	req := AirthRequest{10, 2}
	var res AirthResponse
	err = conn.Call("Arith.Multiply", req, &res)

	if err != nil {
		log.Fatalln("arith error:", err)
	}
	fmt.Println("%d * %d = %d\n", req.A, req.B, res.Pro)
	err = conn.Call("Arith.Divide", req, &res)
	if err != nil {
		log.Fatal("arith error:", err)
	}
	fmt.Printf("%d / %d, quo is %d, rem is %d\n", req.A, req.B, res.Quo, res.Rem)

 
代码语言:javascript
复制

 package main

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

// 算数运算结构体
type Arith struct {
}

// 算数运算请求结构体
type ArithRequest struct {
    A int
    B int
}

// 算数运算响应结构体
type ArithResponse struct {
    Pro int // 乘积
    Quo int // 商
    Rem int // 余数
}

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

// 除法运算方法
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() {
    rpc.Register(new(Arith)) // 注册rpc服务

    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")

    for {
        conn, err := lis.Accept() // 接收客户端连接请求
        if err != nil {
            continue
        }

        go func(conn net.Conn) { // 并发处理客户端请求
            fmt.Fprintf(os.Stdout, "%s", "new client in coming\n")
            jsonrpc.ServeConn(conn)
        }(conn)
    }
}
代码语言:javascript
复制
package main

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

// 算数运算请求结构体
type ArithRequest struct {
    A int
    B int
}

// 算数运算响应结构体
type ArithResponse struct {
    Pro int // 乘积
    Quo int // 商
    Rem int // 余数
}

func main() {
    conn, err := jsonrpc.Dial("tcp", "127.0.0.1:8096")
    if err != nil {
        log.Fatalln("dailing error: ", err)
    }

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

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

    err = conn.Call("Arith.Divide", req, &res)
    if err != nil {
        log.Fatalln("arith error: ", err)
    }
    fmt.Printf("%d / %d, quo is %d, rem is %d\n", req.A, req.B, res.Quo, res.Rem)
}
 

GitHub: https://github.com/zhuchenglin/gorpc

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020-06-21 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
文件存储
文件存储(Cloud File Storage,CFS)为您提供安全可靠、可扩展的共享文件存储服务。文件存储可与腾讯云服务器、容器服务、批量计算等服务搭配使用,为多个计算节点提供容量和性能可弹性扩展的高性能共享存储。腾讯云文件存储的管理界面简单、易使用,可实现对现有应用的无缝集成;按实际用量付费,为您节约成本,简化 IT 运维工作。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档