page contents

Golang框架之rpc框架rpcx

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

attachments-2021-06-eqVyFN0V60d960c4061b6.png

前言

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

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

功能

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

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);
?>

结果:

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

server.go 输出

C= 200

这样就实现跨语言了。

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

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

更多相关技术内容咨询欢迎前往并持续关注六星社区了解详情。

程序员编程交流QQ群:805358732

如果你想用Python开辟副业赚钱,但不熟悉爬虫与反爬虫技术,没有接单途径,也缺乏兼职经验
关注下方微信公众号:Python编程学习圈,获取价值999元全套Python入门到进阶的学习资料以及教程,还有Python技术交流群一起交流学习哦。

attachments-2022-06-r5TYSRkv62ad2acb2746c.jpeg

  • 发表于 2021-06-28 13:40
  • 阅读 ( 560 )
  • 分类:Golang

0 条评论

请先 登录 后评论
轩辕小不懂
轩辕小不懂

2403 篇文章

作家榜 »

  1. 轩辕小不懂 2403 文章
  2. 小柒 1324 文章
  3. Pack 1135 文章
  4. Nen 576 文章
  5. 王昭君 209 文章
  6. 文双 71 文章
  7. 小威 64 文章
  8. Cara 36 文章