老王学习go语言——2.1 Go Kit和Go Micro

《Go语言高并发与微服务实战》

让开发者专注于自身业务逻辑的开发 这句话放在开篇,几乎每个技术框架都声称自己可以做到这一点,以下的两个框架也不例外。

书中虽然介绍了这两个框架,但比较简单。打算综合其他社区和官网的内容,把这部分内容丰富一下,相信以后用的到。

老王学习go语言——2.1GoKit和GoMicro

Go Kit

Go-kit(gokit.io)是Go语言工具包的集合,可帮助工程师构建强大,可靠和可维护的微服务。Go-kit提供了用于实现系统监控和弹性模式组件的库,例如日志记录、跟踪、限流和熔断等,这些库协助工程师提高微服务架构的性能和稳定性

为了求甚解,建议大家可以直接去官网进行了解

老王学习go语言——2.1GoKit和GoMicro

https://gokit.io/

就喜欢这种风格的网站,一目了然,重点突出。

Go Kit并没有强调自己是个FrameWork,而是“A tookit”,轻量级,让你能够把经历聚焦在业务逻辑上。简单明了。

而为什么是Go Kit,官方给出的解释:Go 是一种很棒的通用语言,但微服务需要一定量的专门支持。RPC 安全性、系统可观察性、基础结构集成、甚至程序设计 – Go kit填补了标准库留下的空白,使 Go 成为在任何组织中编写微服务的一流语言。用现在流行的词来讲,这个tookit是以赋能Go为使命的。这样说起来好像“高大上”了许多。

网站简洁到几乎没有一句多余的废话,我是谁,为什么是我,例子,源代码就这些,我还真喜欢这种风格。所以要分享点儿东西,我又没有心思在这个时候直接进入编程示例,于是只能先去Github,看看readme和程序结构了。

Motivation

Go已经逐渐成为服务器语言,但它在Facebook、Twitter、Netflix和 SoundCloud等所谓的"现代企业"公司中仍然不足。许多这些组织都转向基于 JVM 的技术栈来处理其业务逻辑,这主要由于直接支持其微服务体系结构的库和生态系统。

为了取得更大的成功,Go 不仅仅要是一种程序设计语言,。它需要一个全面的工具包,用于大的分布式编程。Go kit是一组包和最佳实践,为任何规模的组织提供全面、可靠且可信赖的构建微服务的方法。

目标

在异构 SOA 中运行 – 期望与大多数非 Go-kit 服务进行交互

RPC 作为主要消息传递模式

可插拔的序列化和传输 – 不只是 JSON 通过 HTTP

在现有基础设施中运行 – 没有特定工具或技术的授权

非目标

支持 RPC 以外的消息传递模式(目前)– 例如 MPI、酒吧/子、CQRS 等。

通过调整现有软件来重新实现功能

对运营问题有意见:部署、配置、流程监督、编排等。

关于程序结构和其他一些介绍,可以请移步到。

https://gokit.io/faq/#introduction-mdash-understanding-go-kit-key-concepts

这里只挑重点列一下:

1.go-Kit不是MVC框架,基础结构是transport, EndPoint,Service,请求首先进入transport,然后是Endpoint,最后由Service来处理。响应则走相反的路径。transport,是进行服务转换的,可以在单一服务中同时支持多种访问方式比如http,aRPC,transport也是为了在业务逻辑和响应方式上进行解耦和统一处理。而EndPoint很像MVC中的Controller,在这里调用实际的Service,Service就很好理解了。

Requests enter the service at layer 1, flow down to layer 3, and responses take the reverse course.

老王学习go语言——2.1GoKit和GoMicro

Go-Kit分层 最上面transport,中间EndPoint,最下面Service

将所有这些概念放在一起,我们可以看到 Go kit 微服务的模型像洋葱一样,具有许多层。这些图层可以分组到我们的三个域中。最内层的服务域是一切基于您的特定服务定义,以及实现所有业务逻辑的地方。中间Endpoint是将服务的每个方法抽象到通用Endpoint域。。最后,最外层的传输域是端点绑定到具体传输(如 HTTP 或 gRPC)的地方。

通过定义服务接口并提供具体实现,实现核心业务逻辑。然后,编写服务中间件以提供其他功能,如日志记录、分析、检测等,即任何需要了解业务领域的信息。

Go 套件提供端点和传输域中间件,用于速率限制、电路中断、负载平衡和分布式跟踪等功能,所有这些功能通常与您的业务领域无关。

好吧,Go-Kit先介绍到这里吧,后续具体实现微服务的时候,再分析学习搭建开发环境,say helloworld的方法。

Go Micro

Go Micro是一个插件化的基础框架,基于此可以构建微服务。Micro的设计哲学是『可插拔』的插件化架构。在架构之外,它默认实现了consul作为服务发现,通过http进行通信,通过protobuf和json进行编解码。

这里是每个技术框架共同的追求:让开发者专注于自身业务逻辑的开发

go-micro的主要功能

  • 服务发现:自动服务注册和名称解析。服务发现是微服务开发的核心。当服务A需要与服务B通话时,它需要该服务的位置。默认发现机制是多播DNS(mdns),一种零配置系统。您可以选择使用SWIM协议为p2p网络设置八卦,或者为弹性云原生设置设置consul
  • 负载均衡:基于服务发现构建的客户端负载均衡。一旦我们获得了服务的任意数量实例的地址,我们现在需要一种方法来决定要路由到哪个节点。我们使用随机散列负载均衡来提供跨服务的均匀分布,并在出现问题时重试不同的节点
  • 消息编码:基于内容类型的动态消息编码。客户端和服务器将使用编解码器和内容类型为您无缝编码和解码Go类型。可以编码任何种类的消息并从不同的客户端发送。客户端和服务器默认处理此问题。这包括默认的protobuf和json
  • 请求/响应:基于RPC的请求/响应,支持双向流。我们提供了同步通信的抽象。对服务的请求将自动解决,负载平衡,拨号和流式传输。启用tls时,默认传输为http / 1.1或http2
  • Async Messaging:PubSub是异步通信和事件驱动架构的一流公民。事件通知是微服务开发的核心模式。启用tls时,默认消息传递是点对点http / 1.1或http2
  • 可插拔接口:Go Micro为每个分布式系统抽象使用Go接口,因此,这些接口是可插拔的,并允许Go Micro与运行时无关,可以插入任何基础技术
  • go-micro之所以可以高度订制和他的框架结构是分不开的,go-micro由8个关键的interface组成,每一个interface都可以根据自己的需求重新实现,这8个主要的inteface也构成了go-micro的框架结构

老王学习go语言——2.1GoKit和GoMicro

图片来源于网络

  • Server监听客户端的调用,和Brocker推送过来的信息进行处理。并且Server端需要向Register注册自己的存在或消亡,这样Client才能知道自己的状态
  • Register服务的注册的发现,Client端从Register中得到Server的信息,然后每次调用都根据算法选择一个的Server进行通信,当然通信是要经过编码/解码,选择传输协议等一系列过程的
  • 如果有需要通知所有的Server端可以使用Brocker进行信息的推送,Brocker 信息队列进行信息的接收和发布。

Go -kit 于Go Mirco区别: Go-Kit为多数业务场景下实施微服务软件架构提供指导和解决方案。

而Go Micro则是一个面向微服务的可插拔RPC框架,他是只在特殊细分领域上努力的框架。他尝试简化分布式系统之间的通信。

微服务设计的六大原则:

1.高内聚,低耦合

紧密关联的事务应该放在一起,每个服务针对一个单一职责的业务能力封装。服务间通过轻量级的通讯方式进行通信,服务间相对独立。低耦合。

2.高度自治

1)服务独立部署运行和扩展。而提使得代码组织,发布节奏,快速交付和快速应对变化等有各大的灵活性。

2)独立开发和演进。服务和服务之间采取语言无关的网络通信进行交互。不受遗留系统技术栈的约束。

3)独立的团队。工作在独立的上下文中

3.以业务为中心

每个服务代表了特定的业务逻辑,有明显的边界上下文。

4.弹性设计

容错设计,防止级联的服务雪崩。

5.日志与监控

微服务架构天生在定位错误和进行追踪的过程中相对繁琐,所以对于日志和监控的能力要求也就交到。结构化的日志和服务依赖关心,方便快速发现问题及时修复。

6.自动化

微服务架构的复杂性,要求运维及管理能够实现自动化,要不然服务和节点大到一定程度,维护和管理工作将具有非常大的难度。

领域驱动设计(DDD Domain Drive Design)

DDD不是语言,不是框架,也不是架构,而是一种思想,一种方*论法**,主要用于合理地划分业务系统以及保持业务架构和系统架构的一致性这两个领域。

DDD其实2003年就出现了,但是由于自身的问题,导致一直不温不火,而这次被提起,就是借着微服务的东风。因为DDD的界限上下文可以很好的判定微服务划分的粒度。

而无论是微服务还是SOA一直在服务划分粒度上没有统一标准,更多的凭团队经验,划分打了不符合服务化的初衷,充分发挥架构的优势,而划分的过于小,无端增加复杂度,还使得系统过于凌乱,增大管理成本。

但DDD理解起来容易,实际落地到真正实践中却仍然十分困难。

DDD中根据问题域,将问题划分为领域/子域,通用语言,限界上下文和架构风格等概念

大家只要记住DDD可以被用来指导进行微服务粒度的划分,但DDD其实也有很大的工程量,个人并不知道是先跟着感觉走,遇到问题再调整力度是最合适的实践方*论法**,还是先学习DDD,然后投入很多的经历试图找出最合适的划分方法。见仁见智吧,但是DDD并不影响我们学习Go,先放一放吧。关于DDD就不发散了。

把上下文相关的和不相关的总算结束了。明天正式进入Go语言本身。

最后还是抽出一个题来扩展一下,那就是RPC,dubbo是RPC框架,Go Micro也是RPC,那么RPC是什么呢

RPC(Remote Procedure Call)远程过程调用

进程间通信(IPC)是在多任务操作系统或联网的计算机之间运行的程序和进程所用的通信技术。有两种类型的进程间通信(IPC)。

本地过程调用(LPC)LPC用在多任务操作系统中,使得同时运行的任务能互相会话。这些任务共享内存空间使任务同步和互相发送信息。RPC调用的模型远程过程调用(RPC)RPC类似于LPC,只是在网上工作。RPC开始是出现在Sun微系统公司和HP公司的运行UNⅨ操作系统的计算机中。

RPC的概念与技术早在1981年由Nelson提出。1984年,Birrell和Nelson把其用于支持异构型分布式系统间的通讯。Birrell的RPC 模型引入存根进程( stub) 作为远程的本地代理,调用RPC运行时库来传输网络中的调用。Stub和RPC runtime屏蔽了网络调用所涉及的许多细节,特别是,参数的编码/译码及网络通讯是由stub和RPC runtime完成的,因此这一模式被各类RPC所采用。由于分布式系统的异构性及分布式计算模式与计算任务的多样性,RPC作为网络通讯与委托计算的实现机制,在方法、协议、语义、实现上不断发展,种类繁多,其中SUN公司和开放软件基金会在其分布式产品中所建立和实用的RPC较为典型。 [1]

在SUN公司的网络文件系统NFS及开放网络计算环境ONC中,RPC是基本实现技术。OSF酝酿和发展的另一个重要的分布式计算软件环境DCE也是基于RPC的。在这两个系统中,RPC既是其自身的实现机制,又是提供给用户设计分布式应用程序的高级工具。由于对分布式计算的广泛需求,ONC和DCE成为Client/Server模式分布式计算环境的主流产品,而RPC也成为实现分布式计算的事实标准之一。

以上内容是不是特别清楚,他来源于百科百科,囧。

RPC 是一种技术思想而非一种规范或协议,常见 RPC 技术和框架有:

应用级的服务框架:阿里的 Dubbo/Dubbox、Google gRPC、Spring Boot/Spring Cloud。

远程通信协议:RMI、Socket、SOAP(HTTP XML)、REST(HTTP JSON)。

通信框架:MINA 和 Netty。

目前流行的开源 RPC 框架还是比较多的,有阿里巴巴的 Dubbo、Facebook 的 Thrift、Google 的 gRPC、Twitter 的 Finagle 等。

下面重点介绍三种:

gRPC:是 Google 公布的开源软件,基于***的 HTTP 2.0 协议,并支持常见的众多编程语言。RPC 框架是基于 HTTP 协议实现的,底层使用到了 Netty 框架的支持。

Thrift:是 Facebook 的开源 RPC 框架,主要是一个跨语言的服务开发框架。

用户只要在其之上进行二次开发就行,应用对于底层的 RPC 通讯等都是透明的。不过这个对于用户来说需要学习特定领域语言这个特性,还是有一定成本的。

Dubbo:是阿里集团开源的一个极为出名的 RPC 框架,在很多互联网公司和企业应用中广泛使用。协议和序列化框架都可以插拔是极其鲜明的特色。

在一个典型 RPC 的使用场景中,包含了服务发现、负载、容错、网络传输、序列化等组件,其中“RPC 协议”就指明了程序如何进行网络传输和序列化。

老王学习go语言——2.1GoKit和GoMicro

RPC 的核心功能是指实现一个 RPC 最重要的功能模块,就是上图中的”RPC 协议”部分

一个 RPC 的核心功能主要有 5 个部分组成,分别是:客户端、客户端 Stub、网络传输模块、服务端 Stub、服务端等。

老王学习go语言——2.1GoKit和GoMicro

图 4:RPC 核心功能图

下面分别介绍核心 RPC 框架的重要组成:

  • 客户端(Client):服务调用方。
  • 客户端存根(Client Stub):存放服务端地址信息,将客户端的请求参数数据信息打包成网络消息,再通过网络传输发送给服务端。
  • 服务端存根(Server Stub):接收客户端发送过来的请求消息并进行解包,然后再调用本地服务进行处理。
  • 服务端(Server):服务的真正提供者。
  • Network Service:底层传输,可以是 TCP 或 HTTP。

一次 RPC 调用流程如下:

  • 服务消费者(Client 客户端)通过本地调用的方式调用服务。
  • 客户端存根(Client Stub)接收到调用请求后负责将方法、入参等信息序列化(组装)成能够进行网络传输的消息体。
  • 客户端存根(Client Stub)找到远程的服务地址,并且将消息通过网络发送给服务端。
  • 服务端存根(Server Stub)收到消息后进行解码(反序列化操作)。
  • 服务端存根(Server Stub)根据解码结果调用本地的服务进行相关处理
  • 服务端(Server)本地服务业务处理。
  • 处理结果返回给服务端存根(Server Stub)。
  • 服务端存根(Server Stub)序列化结果。
  • 服务端存根(Server Stub)将结果通过网络发送至消费方。
  • 客户端存根(Client Stub)接收到消息,并进行解码(反序列化)。
  • 服务消费方得到最终结果。

懒得一个字一个字的打了,内容来源于网络,说的比我清楚,我就不用重复劳动了,介绍了RPC的主流框架和技术。我们说的比较多的是dubbo,gRPC.