31

Golang之rpc框架rpcx

 4 years ago
source link: https://studygolang.com/articles/29967
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

前言

远程过程调用(Remote Procedure Call,缩写为 RPC)是一个计算机通信协议。通过该协议程序员可以实现像调取本地函数一样,调取远程服务的函数。这里介绍一个高效的rpc库(rpcx)。

rpcx 是一个分布式的Go语言的 RPC 框架,支持Zookepper、etcd、consul多种服务发现方式,多种服务路由方式, 是目前性能最好的 RPC 框架之一。

官方资料: https://books.studygolang.com...

项目: https://github.com/smallnest/...

功能

  • 支持原始Go功能。无需定义原型文件。
  • 可插拔 可以扩展功能,例如服务发现,跟踪。
  • 支持TCP,HTTP, QUICKCP
  • 支持多种编解码器,例如JSON,Protobuf, MessagePack 和原始字节。
  • 服务发现。支持peer2peer,已配置的peer, zookeeperetcdconsulmDNS
  • 容错:故障转移,故障转移,故障转移。
  • 负载平衡:支持随机,轮循,一致哈希,加权,网络质量和地理位置。
  • 支持压缩。
  • 支持传递元数据。
  • 支持授权。
  • 支持心跳和单向请求。
  • 其他功能:指标,日志,超时,别名,断路器。
  • 支持双向通讯。
  • 支持通过HTTP访问,因此您可以使用任何编程语言编写客户端。
  • 支持API网关。
  • 支持备份请求,分叉和广播。

rpcx使用二进制协议且与平台无关,这意味着您可以使用其他语言(例如Java,Python,nodejs)开发服务,还可以使用其他编程语言来调用Go中开发的服务。

性能

测试结果表明,除了标准rpc库之外,rpcx的性能要优于其他rpc框架。

快速开始

基本安装

go get -v github.com/smallnest/rpcx/...

服务端

新建server.go

package main

import (
    "context"
    "flag"
    "fmt"

    example "github.com/rpcxio/rpcx-examples"
    "github.com/smallnest/rpcx/server"
)

var (
    addr = flag.String("addr", "localhost:8972", "server address")
)

type Arith struct{}

// the second parameter is not a pointer
func (t *Arith) Mul(ctx context.Context, args example.Args, reply *example.Reply) error {
    reply.C = args.A * args.B
    fmt.Println("C=", reply.C)
    return nil
}

func main() {
    flag.Parse()

    s := server.NewServer()
    //s.Register(new(Arith), "")
    s.RegisterName("Arith", new(Arith), "")
    err := s.Serve("tcp", *addr)
    if err != nil {
        panic(err)
    }
}

客户端

client.go

package main

import (
    "context"
    "flag"
    "fmt"

    "log"

    "github.com/smallnest/rpcx/protocol"

    example "github.com/rpcxio/rpcx-examples"
    "github.com/smallnest/rpcx/client"
)

var (
    addr = flag.String("addr", "localhost:8972", "server address")
)

func main() {
    flag.Parse()
    d := client.NewPeer2PeerDiscovery("tcp@"+*addr, "")
    opt := client.DefaultOption
    opt.SerializeType = protocol.JSON

    xclient := client.NewXClient("Arith", client.Failtry, client.RandomSelect, d, opt)
    defer xclient.Close()

    args := example.Args{
        A: 10,
        B: 20,
    }

    reply := &example.Reply{}
    err := xclient.Call(context.Background(), "Mul", args, reply)
    if err != nil {
        log.Fatalf("failed to call: %v", err)
    }

    log.Printf("%d * %d = %d", args.A, args.B, reply.C)

}

运行

服务端

go  run server.go

客户端

go run client.go

这时服务端输出:

C= 200
2020/07/21 15:19:02 server.go:358: INFO : client has closed this connection: 127.0.0.1:50186

客户端输出:

2020/07/21 15:19:02 10 * 20 = 200

跨语言

rpcx还提供了 rpcx-gateway ,您可以使用任何编程语言编写客户端,以通过 rpcx-gateway 调用rpcx服务。

安装rpcx-gateway

go  get  github.com/rpcxio/rpcx-gateway

示例

新建gateway.go文件,代码如下:

package main

import (
    "errors"
    "flag"
    "fmt"
    "log"
    "strings"
    "time"

    gateway "github.com/rpcxio/rpcx-gateway"
    "github.com/rpcxio/rpcx-gateway/gin"
    "github.com/smallnest/rpcx/client"
)

var (
    addr       = flag.String("addr", ":9981", "http server address")
    registry   = flag.String("registry", "peer2peer://127.0.0.1:8972", "registry address")
    basePath   = flag.String("basepath", "/rpcx", "basepath for zookeeper, etcd and consul")
    failmode   = flag.Int("failmode", int(client.Failover), "failMode, Failover in default")
    selectMode = flag.Int("selectmode", int(client.RoundRobin), "selectMode, RoundRobin in default")
)

func main() {
    flag.Parse()

    d, err := createServiceDiscovery(*registry)
    if err != nil {
        log.Fatal(err)
    }

    httpServer := gin.New(*addr)
    gw := gateway.NewGateway("/", httpServer, d, client.FailMode(*failmode), client.SelectMode(*selectMode), client.DefaultOption)

    gw.Serve()
}

func createServiceDiscovery(regAddr string) (client.ServiceDiscovery, error) {
    i := strings.Index(regAddr, "://")
    if i < 0 {
        return nil, errors.New("wrong format registry address. The right fotmat is [registry_type://address]")
    }

    regType := regAddr[:i]
    regAddr = regAddr[i+3:]

    switch regType {
    case "peer2peer": //peer2peer://127.0.0.1:8972
        return client.NewPeer2PeerDiscovery("tcp@"+regAddr, ""), nil
    case "multiple":
        var pairs []*client.KVPair
        pp := strings.Split(regAddr, ",")
        for _, v := range pp {
            pairs = append(pairs, &client.KVPair{Key: v})
        }
        return client.NewMultipleServersDiscovery(pairs), nil
    case "zookeeper":
        return client.NewZookeeperDiscoveryTemplate(*basePath, []string{regAddr}, nil), nil
    case "etcd":
        return client.NewEtcdDiscoveryTemplate(*basePath, []string{regAddr}, nil), nil
    case "etcdv3":
        return client.NewEtcdV3DiscoveryTemplate(*basePath, []string{regAddr}, nil), nil
    case "consul":
        return client.NewConsulDiscoveryTemplate(*basePath, []string{regAddr}, nil), nil
    case "redis":
        return client.NewRedisDiscoveryTemplate(*basePath, []string{regAddr}, nil), nil
    case "mdns":
        return client.NewMDNSDiscoveryTemplate(10*time.Second, 10*time.Second, ""), nil
    default:
        return nil, fmt.Errorf("wrong registry type %s. only support peer2peer,multiple, zookeeper, etcd, consul and mdns", regType)
    }
}

运行 gateway.go

go run  gateway.go

注意:运行网关前,要保证rpcx服务端(server.go)启动,这里以php客户端为例

新建client.php

代码如下:

<?php
$url = 'http://localhost:9981/';
$data = '{"A":10, "B":20}';

// use key 'http' even if you send the request to https://...
$options = array(
    'http' => array(
        'header'  => "Content-type: application/rpcx\r\n" .
            // "X-RPCX-MessageID: 12345678\r\n" .
            // "X-RPCX-MesssageType: 0\r\n" .
            "X-RPCX-SerializeType: 1\r\n" .
            "X-RPCX-ServicePath: Arith\r\n" .
            "X-RPCX-ServiceMethod: Mul\r\n",
        'method'  => 'POST',
        'content' => $data
    )
);
$context  = stream_context_create($options);
$result = file_get_contents($url, false, $context);
if ($result === FALSE) { /* Handle error */ }

var_dump($result);
?>

访问 http://localhost/client.php

结果:

string(9) "{"C":200}"

server.go 输出

C= 200

这样就实现跨语言了。

其他语言示例

https://github.com/rpcxio/rpc...

rpcx 3.0已针对以下目标进行了重构:

  1. 简单 :易于学习,易于开发,易于交互和易于部署
  2. 性能 :高性能(> = grpc-go)
  3. 跨平台 :支持 字节JSONProtobufMessagePack的 原始切片 。从理论上讲,它可以与java,php,python,c / c ++,node.js,c#和其他平台一起使用
  4. 服务发现和服务治理 :支持zookeeper,etcd和consul。

相关资料

https://github.com/rpcxio/rpc...

https://github.com/smallnest/...

links

  • 目录
  • 上一节:
  • 下一节:

有疑问加站长微信联系

iiUfA3j.png!web

Recommend

  • 60

    想搞定微服务,先搞定 RPC 框架?

  • 54
    • www.infoq.cn 6 years ago
    • Cache

    RPC 框架的可靠性设计

    1. 背景 1.1 分布式调用引入的故障 在传统的单体架构中,业务服务调用都是本地方法调用,不会涉及到网络通信、协议栈、消息序列化和反序列化等,当使用 RPC 框架将业务由单体架构改造成分布式系统之后,本地方法调...

  • 77
    • segmentfault.com 6 years ago
    • Cache

    Go 实现简易 RPC 框架

    本文旨在讲述 RPC 框架设计中的几个核心问题及其解决方法,并基于 Golang 反射技术,构建了一个简易的 RPC 框架。 项目地址: Tiny-RPC RPC ...

  • 39
    • segmentfault.com 6 years ago
    • Cache

    RPC框架是啥?

    本博客 猫叔的博客 ,转载请申明出处 在我刚刚了解分布式的时候,经常对RPC和分布式有些混淆,甚至一直以为两者对等,所以我们先看看他们有什么 区别 ? ...

  • 32
    • doc.rpcx.site 5 years ago
    • Cache

    Introduction · rpcx programming

  • 53
    • studygolang.com 4 years ago
    • Cache

    Go 每日一库之 rpcx

    简介 在之前的两篇文章 rpc 和 json-rpc 中,我...

  • 3
    • colobu.com 4 years ago
    • Cache

    rpcx支持websocket协议了!

    rpcx支持websocket协议了! 当前, rpcx支持tcp、kcp、quic、unix domain、http、jsonrpc 2.0等传输协议,并没有考虑websocket的支持,原因在于考虑到微服务更多的是企...

  • 8
    • segmentfault.com 3 years ago
    • Cache

    RPCX源码学习-server端

    认识RPCRPC是什么东西? RPC: Remote Procedure Call(远程过程调用),是一个计算机通信协议。协议的主要内容是什么? 该协议允许运行于一台计算机中的程序调用另一个地址空间(通常为...

  • 8
    • colobu.com 2 years ago
    • Cache

    使用ebpf跟踪rpcx微服务

    使用ebpf跟踪rpcx微服务 ebpf是一种创新的革命性技术,它能在内核中运行沙箱程序,...

  • 10

    最近在做2022 Go生态圈 rpc 框架 Benchmark之前,专门花了一星期时间,对rpcx进行了重点的优化,这篇文章专门记录一下几个重要的优化点,供大家参考。

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK