Golang实践:RPC

发布于 2019-08-13 · 本文总共 3304 字 · 阅读大约需要 10 分钟

Remote Procedure Call,远程过程调用,即通过网络从远程计算机上请求服务而不需要了解底层网络技术的协议; 该协议允许运行于一台计算机的程序调用另一台计算机的子程序,而程序员无需额外地为这个交互作用编程;

常用于分布式系统中不同系统之间的远程通信和调用;

helloworld

RPC框架

产品级的RPC框架除了点对点的RPC协议的具体实现外,还应包括服务的发现与注销、提供服务的多台Server的负载均衡、服务的高可用等更多的功能;

目前的RPC框架大致有两种不同的侧重方向,一种偏重于服务治理,另一种偏重于跨语言调用。

服务治理型:

dubbo、dubbox、motan

多语言型:

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

gRPC:gRPC是Google开发的高性能、通用的开源RPC框架
由Google主要面向移动应用开发并基于HTTP/2协议标准而设计,基于ProtoBuf(Protocol Buffers)序列化协议开发,且支持众多开发语言; 它的目标是跨语言开发,支持多种语言,服务治理方面需要自己去实现,所以要实现一个综合的产品级的分布式RPC平台还需要扩展开发; Google内部使用的也不是gRPC,而是Stubby;

thrift:Apache跨语言的高性能的服务框架
thrift是Apache的一个跨语言的高性能的服务框架,也得到了广泛的应用; 它的功能类似gRPC, 支持跨语言,不支持服务治理;

RPC与RESTful

特性 RPC REST
耦合性 强耦合 松散耦合
消息协议 二进制thrift、protobuf、avro XML、JSON
通讯协议 TCP为主 HTTP/HTTP2
性能 一般低于RPC
接口契约IDL thrift、protobuf idl swagger
Client 强类型客户端 http client
案例 dubbo、gRPC、thrift spring boot/MVC
开发者友好 二进制消息 文本消息、浏览器可以直接访问
对外开放 需转成REST/文本协议 直接对外开放

REST:

Representational State-transfer表述性状态转移

具象状态传输

是一种架构风格;

REST特点:

1.资源由URI指定;

2.对资源的操作包括get、post、put、delete

3.通过资源的表现形式来操作资源;

4.资源的表现形式是XML或HTML、JSON

优点:

1.可更高效利用缓存来提高响应速度;

2.提高服务可扩展性(通讯本身无状态);

3.浏览器可作为Client;

4.依赖更小;

5.不需要额外发现机制;

thrift安装

Linux

wget http://www-us.apache.org/dist/thrift/0.13.0/thrift-0.13.0.tar.gz tar -xzvf thrift-0.13.tar.gz cd thrift-0.13.0 ./configure –prefix=/usr make -j8 make install

Mac

brew install thrift

查看版本:

thrift -version

Thrift version 0.13.0

生成Python代码

thrift -r –gen py helloworld.thrift

生成Golang代码

thrift -r –gen go helloworld.thrift

服务端示例

package main

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

const HelloServiceName = "HelloService"

type HelloServicer = interface {
	HelloWorld(request string, reply *string) error
}

func RegisterHelloService(svc HelloServicer) error {
	return rpc.RegisterName(HelloServiceName, svc)

}

type HelloService struct {
}

func (h *HelloService) HelloWorld(request string, reply *string) error {
	*reply = fmt.Sprintf("hello: %s.", request)
	fmt.Println("reply: ", *reply)
	return nil
}

func RPCServer() {
	RegisterHelloService(new(HelloService))

	listener, err := net.Listen("tcp", ":9090")
	if err != nil {
		log.Fatal("Listen TCP error: ", err)
	}
	for {
		conn, err := listener.Accept()
		if err != nil {
			log.Fatal("Accept error: ", err)
		}
		fmt.Println("accept.")
		go rpc.ServeConn(conn)
	}
}

func main() {
	RPCServer()
}

数据传输方式(TTransport)

	if useHttp {
		trans, err = thrift.NewTHttpClient(parsedUrl.String())
	}else{
		trans, err = thrift.NewTSocket(net.JoinHostPort(host, portStr))
	}
	defer trans.Close()

传输协议(TProtocol):

TBinaryProtocol:二进制编码格式 TCompactProtocol:高效率密集的二进制编码格式 TJSONProtocol:JSON数据编码 TDebugProtocol:可读文本格式,可以debug

	case "compact":
		protocolFactory = thrift.NewTCompactProtocolFactory()
		break
	case "simplejson":
		protocolFactory = thrift.NewTSimpleJSONProtocolFactory()
		break
	case "json":
		protocolFactory = thrift.NewTJSONProtocolFactory()
		break
	case "binary", "":
		protocolFactory = thrift.NewTBinaryProtocolFactoryDefault()
		break

客户端示例

func RPCClient() {

	conn, err := net.DialTimeout("tcp", "127.0.0.1:9090", time.Second*10)
	if err != nil {
		log.Fatal("net.Dial:", err)
	}

	client := rpc.NewClient(conn)
	fmt.Println("rpc client.")

	var reply string
	err = client.Call("HelloService.HelloWorld", "hello", &reply)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(reply)
}

注册中心

插件

网关

refs

http://books.studygolang.com/go-rpc-programming-guide/

https://juejin.im/post/6844903938706112520

https://ops.tips/gists/example-go-rpc-client-and-server/

https://medium.com/rungo/building-rpc-remote-procedure-call-network-in-go-5bfebe90f7e9




本博客所有文章采用的授权方式为 自由转载-非商用-非衍生-保持署名 ,转载请务必注明出处,谢谢。
声明:
本博客欢迎转发,但请保留原作者信息!
博客地址:邱文奇(qiuwenqi)的博客;
内容系本人学习、研究和总结,如有雷同,实属荣幸!
阅读次数:

文章评论

comments powered by Disqus


章节列表