重庆分公司,新征程启航
为企业提供网站建设、域名注册、服务器等服务
现在微服务很流行,很多的语言都有自己的rpc框架,在同一框架内的微服务之间通信很方便,笔者工作时用到的框架是hyperf,自带jsonrpc、grpc组件,grpc用起来略感繁琐,调试起来也不方便,因此选用jsonrpc-http,损失些许通信成本在可接受范围之内,能用postman调试实在是太方便了。
创新互联凭借专业的设计团队扎实的技术支持、优质高效的服务意识和丰厚的资源优势,提供专业的网站策划、成都网站设计、成都网站建设、网站优化、软件开发、网站改版等服务,在成都10余年的网站建设设计经验,为成都上千家中小型企业策划设计了网站。
随着业务和团队的不断发展,开始有多语言开发需求,我们的另一个项目是用go搭建的,hyperf与go之间也打算用jsonrpc,go自带jsonrpc包,但是是jsonrpc1.0的,与hyperf不兼容,经过努力,找到一个jsonrpc2.0的包( go-jsonrpc ),与hyperf完美兼容。
近几年诞生了很多微服务框架,比如JAVA的Spring Cloud、Dubbo;Golang的GoKit和GoMicro以及NodeJs的Seneca。几乎每种主流语言都有其对应的微服务框架。
Go在微服务框架中有其独特的优势,至于优势在哪,自行google。
1、GoKit框架
这是一个工具包的集合,可以帮助攻城狮构建强大、可靠和可维护的微服务。提供了用于实现系统监控和弹性模式组件的库,例如日志、跟踪、限流、熔断等。
基于这个框架的应用程序架构由三个主要的部分组成:
传输层:用于网络通信,服务通常使用HTTP或者gRPC等网络传输协议,或者使用NATS等发布订阅系统相互通信。
接口层:是服务器和客户端的基本构建块。每个对外提供的接口方法都会定义为一个Endpoint,一遍在服务器和客户端之间进行网络通信,每个端点使用传输层通过HTTP或gRPC等具体通信模式对外提供服务
服务成:具体的业务逻辑实现
2、GoMicro框架
这是一个基于Go语言实现的插件化RPC微服务框架。提供了服务发现、负载均衡、同步传输、异步通信以及事件驱动等机制,尝试简化分布式系统之间的通信,让开发者更专注于自身业务逻辑的开发。
GoMicro的设计哲学是可插拔的架构理念,提供了可快速构建系统的组件,并且可以根据自身的需求对GoMicro提供的默认实现进行定制。所有插件都可在仓库github.com/micro/go-plugins 中找到。
Kitex为 字节跳动 内部的 Golang 微服务 RPC 框架,具有 高性能 、 强可扩展 的特点,在字节内部已广泛使用。如果对微服务性能有要求,又希望定制扩展融入自己的治理体系,Kitex 会是一个不错的选择。
这次我们可以从 官方示例 中的 easy_note 这个demo 开始分析,因为它基本展示了 Kitex 的基本使用方法。
下面图例为官方在 demo 中展示的架构图,通过简单的分析可得, note , user 通过 注册中心 (Etcd) 进行注册 , api 通过 注册中心 来发现 note , user 两个 rpc 服务, 并进行业务处理。
从 kitex-examples/hello 这个最简单示例分析,从 cloudwego/kitex 的快速上手可知,这里用了最简单的 直链 来链接 server 和 client。而这次的 easy_note 中使用了 注册中心 来作为 服务之间的 桥梁 (middleware), 为什么不使用之前的方式而是使用了注册中心?
我们搜索一下注册中心的作用,可知: 服务注册中心的主要作用就是「服务的注册」和「服务的发现」
我们将服务交给注册中心管理,虽然可以避免处理复杂的手动管理,我们也许需要还要考虑更多问题,例如:
这次目标之一就是来解析解析服务是如何在服务启动时进行 注册 ( Register ) 这个操作的, 这次我们从 easy_note/cmd/user 这个服务开始分析, 因为它是被 注册 进入 Etcd 的服务之一。
我们从其中的 main.go 开始下手,以下的内容是经过简化后的文件,是实现配置服务,启动服务的文件
由注释可知 WithRegister() 为配置 注册信息 的函数 ,那为什么直接就看这个函数呢?
一是因为主要配置注册的主要逻辑在其中,二是因为 With... 的函数结构都是大同小异,十分相似的。
再然后我们进入 kitex/server/option.go ,先看看 di.Push(fmt.Sprintf("WithRegistry(%T)", r)) 这一行,
这个 *util.Slice 是什么 ?进去看看?
进入 kitex/pkg/utils/slice.go , 我发现它很简短。但是它好眼熟,它好像是一个非常常见的数据结构 —— Stack (栈) !
在这个文件之下有它的 slice__test.go 文件 ,看到这里的朋友可以去试验一下是否这个 Slice 和我的想法是否一致,大家看文章是要思考的嘛!最好可以动动手!
我们再进入 o.Registry = r 这一行,可以得知 Options 用于初始化 server, Option 用于配置 Options (我觉得这种命名方式很巧妙,我感觉基本达到了 见名知意 的作用),里面东西很多,我们今天只看 Register 部分
到了这里我们可以暂停思考一下,到达这一步是怎么个过程呢?是通过 main.go/user.NewServer() 的方法进来的。
那 NewServer() 的作用是什么?是用于配置初始化服务器的 可选参数 ,
配置完了参数什么时候生效呢 ( Register 是什么时候发生的呢) ?其实配置的实现就在 main.go NewServer() 的下一句, Run() !
进入Run方法的实现,可以得知 register 是发生在 server 启动成功后 的,停止也是会向 Etcd 进行注销操作的 (大家可以在同文件的 Stop() 中查看)
至此 服务完成了向 Etcd 的注册,我忽略了许多其他细节,这些细节也很有意思,希望大家可以自己试着探索
这次文章其实向大家分析了如何配置服务,以及向注册中心进行注册的方法和时机。
虽然省略了许多细节,但是通过这篇文章可以学到什么呢?
在 gRPC 里客户端应用可以像调用本地对象一样直接调用另一台不同的机器上服务端 应用的方法,使得您能够更容易地创建分布式应用和服务。与许多 RPC 系统类似,gRPC 也是基于以下理念:定义一个服务,指定其能够被远程调用的方法(包含参数和返回类型)。在服务端实现这个接口,并运行一个 gRPC 服务器来处理客户端调用。在客户端拥有一个存根能够像服务端一样的方法。
gRPC 客户端和服务端可以在多种环境中运行和交互 - 从 google 内部的服务器到你自己的笔记本,并且可以用任何 gRPC 支持的语言来编写。所以,你可以很容易地用 Java 创建一个 gRPC 服务端,用 Go、Python、Ruby 来创建客户端。此外,Google 最新 API 将有 gRPC 版本的接口,使你很容易地将 Google 的功能集成到你的应用里。
gRPC 默认使用 protocol buffers,这是 Google 开源的一套成熟的结构数据序列化机制(当然也可以使用其他数据格式如 JSON)。名叫 proto3 的新风格的 protocol buffers,它拥有轻量简化的语法、一些有用的新功能,并且支持更多新语言。当前针对 Java 和 C++ 发布了 beta 版本,针对 JavaNano(即 Android Java)发布 alpha 版本,在protocol buffers Github 源码库里有 Ruby 支持, 在golang/protobuf Github 源码库里还有针对 Go 语言的生成器, 对更多语言的支持正在开发中。
有了 gRPC, 我们可以一次性的在一个 .proto 文件中定义服务并使用任何支持它的语言去实现客户端和服务器,反过来,它们可以在各种环境中,从Google的服务器到你自己的平板电脑—— gRPC 帮你解决了不同语言及环境间通信的复杂性.使用 protocol buffers 还能获得其他好处,包括高效的序列号,简单的 IDL 以及容易进行接口更新。
现在让我们来仔细了解一下当 gRPC 客户端调用 gRPC 服务端的方法时到底发生了什么。我们不究其实现细节,关于实现细节的部分,你可以在我们的特定语言页面里找到更为详尽的内容。
首先我们来了解一下最简单的 RPC 形式:客户端发出单个请求,获得单个响应。
服务端流式 RPC 除了在得到客户端请求信息后发送回一个应答流之外,与我们的简单例子一样。在发送完所有应答后,服务端的状态详情(状态码和可选的状态信息)和可选的跟踪元数据被发送回客户端,以此来完成服务端的工作。客户端在接收到所有服务端的应答后也完成了工作。
客户端流式 RPC 也基本与我们的简单例子一样,区别在于客户端通过发送一个请求流给服务端,取代了原先发送的单个请求。服务端通常(但并不必须)会在接收到客户端所有的请求后发送回一个应答,其中附带有它的状态详情和可选的跟踪数据。
双向流式 RPC ,调用由客户端调用方法来初始化,而服务端则接收到客户端的元数据,方法名和截止时间。服务端可以选择发送回它的初始元数据或等待客户端发送请求。 下一步怎样发展取决于应用,因为客户端和服务端能在任意顺序上读写 - 这些流的操作是完全独立的。例如服务端可以一直等直到它接收到所有客户端的消息才写应答,或者服务端和客户端可以像"乒乓球"一样:服务端后得到一个请求就回送一个应答,接着客户端根据应答来发送另一个请求,以此类推。
通过运行下面的命令克隆并安装grpc-go代码库:
下载protobuf源码包
安装golang-protobuf
第一步使用 protocol buffers去定义 gRPC service 和方法 request 以及 response 的类型。
要定义一个服务,必须在.proto 文件中指定 service:
然后在服务中定义 rpc 方法,指定请求的和响应类型,gRPC 允许定义4种类型的 service 方法。
服务.proto文件如下所示: