Go语言微服务开发框架实践-go chassis(上篇)

Go chassis是一个go语言微服务开发框架

通过这篇文章中,我将从设计思路到源码剖析来深度分析Go Chassis。并且介绍自己在实践过程中的go语言性能调优和最佳实践,最后将使用go chassis编写一个http服务,此为上篇,将主要介绍go chassis的运行机制

项目地址:https://github.com/go-chassis/go-chassis/

为什么我们要用go语言来开发微服务?

go依然是一门新兴的语言,和java比它还非常年轻,不过随着kubenetes和docker等项目的成功,可以说go语言已经成为了非常好的中间层开发语言,并且逐渐流行起来。

编译速度快,支持多平台,内存占用低,轻量级协程等。

他的协程设计降低了开发者门槛,让更多人可以轻松地编写支持高并发的后台服务

为什么使用Go chassis

当你要解决微服务模式带来的新问题的时候你要实现多少代码来处理分布式带来的复杂度?

我相信一个成熟的开发框架需要2万行以上的代码。而go chassis正是这样一个框架

- go chassis集成了很多的功能,提供了一站式服务,能够让用户在一个方案中,获得路由管理,注册发现,负载均衡,限流,指标监控,分布式追踪等大量功能。

- go chassis是一个协议中立的开发框架,它不仅支持http,也支持rpc协议,甚至可以集成mysql等中间件的协议。并将它们纳入统一的治理。

- go chasis支持Istio控制面板,也就是说你可以将它与envoy进行混合使用,但只需要使用istio即可,它支持原生的istio配置管理。以此使服务吞吐提升,CPU占用降低。

- go chassis是插件化设计,支持用户开发定制模块,并接入到框架中

go chassis特性

主要有以下几点:

● 插件化注册中心: 默认支持Service Center,kubernetes,istio

● 动态治理框架: 通过此框架,开发者可实现进程运行时配置热加载

● 插件化协议: 开发者可实现自己的RPC协议,默认实现了 http 和highway(RPC)以及原生grpc

● 熔断降级: 支持根据超时,并发,错误率等进行服务的熔断

● 容错:支持重试次数等配置,并支持backoff退让重试,

● 路由管理: 可根据流量权重和Header匹配等配置规则,轻松实现金丝雀发布

● 客户端负载均衡: 支持定制策略

● 限流: 支持客户端和服务端限流

● 插件化Cipher: 支持开发者自定义加解密工具,并应用于AKSK和TLS 证书

● 处理链: 可支持在通信的过程中加入定制的业务逻辑

● Metrics: 支持自动导出Prometheus格式的运行时监控数据

● Tracing: 使用opentracing,支持用户快速对接不同分布式追踪系统

● Logger: 日志工具支持扩展并下沉到不同存储中

● 治理: 可通过动态治理框架,在运行时热加载,熔断,负载均衡,路由等配置信息

设计目标

● 最大的灵活性和扩展性

协议是允许开发者灵活扩展的,在通信管道中任意的插入自己的特殊业务逻辑。

● 易用性

开发者可以用最小化的配置和代码来启动框架,并且框架内部提供友好的API供用户使用,每个模块甚至可以拆开使用,功能任意剪裁。

● 服务可治理

提供客户端负载均衡,熔断降级,容错,限流,路由管理等功能使分布式系统可治理,同时提供错误注入功能,来提前模拟分布式系统中的错误,以使自己的系统更加强壮。

● 服务可视化

微服务运行时产生的监控数据能够导出到监控系统,使数据可视化。

● 运行时配置热加载

分布式环境中,存在大量进程,如果因为更改配置就要发布新的软件包,会有一定成本,如果登陆到机器上去改配置再重启,更是费时费力。go chassis提供动态配置框架来帮开发者解决配置热加载问题。这也是服务动态治理的基础。

架构概述

如下图所示:

● 架构思路

解耦的编程接口、运行模型、传输层

● 编程接口:拥有RPC和Rest 2种编程模型

● 运行模型:使用Handler Chain与Invocation概念统一了不同协议

● 传输层:一个进程拥有多种协议。同协议可运行多个协议服务实例,运行在不同端口,使用端口进行API隔离

基于Handler chain模式的插件化架构

● Handler chain可任意插入业务逻辑

基于运行时动态配置的服务治理

相同的运行模型和统一的治理能力

相同的运维支撑方式

● Http服务可支持自动挂载 Promethues数据到指定的API路径。

● 日志可支持扩展,比如输出到kafka等服务中

注册中心拆分为Registrator和Service Discovery2个接口分别负责注册和发现,可以支持平台发现和客户端注册

● 请求处理过程

不同协议请求进入到对应的Server,Server将具体的协议请求转换为Invocation统一抽象模型,并传入Handler chain,在这里Chassis已经默认实现了很多的Handler,比如熔断,限流,路由管理,客户端负载均衡,Metrics收集,分布式追踪,错误注入等,由于handler根据统一模型Invocation进行处理,不必每个协议开发出来都自己开发一套治理。处理链可通过配置任意剪裁。最终再进入Transport handler,使用目标微服务的协议客户端传输到目标。

这里提到的几个关键对象在后面会详细介绍。

实现详解

基本概念

● 处理链与Invocation

这个概念是从Java chassis引入的, 框架的编程接口层、运行模型层和传输层就是通过这个对象进行解耦,它是多协议支持的基础。可以参考它的代码:

https://github.com/ServiceComb/go-chassis/blob/master/core/invocation/invocation.go

Invocation为一个结构体,它将各个协议的内容抽象了,运行不同协议的request都能够统一对应到一次Invocation中,比如request的Payload,以及框架的治理相关信息。

● Handler

Handler是微服务在运行过程中在框架层面里的一个最小处理单元。go chassis通过handler和handler的组装实现组件化的运行模型架构。其基本的使用方式就是实现接口、注册逻辑:

实现基本接口

need-to-insert-img

2. 开发者实现该接口后可通过API注册进框架

need-to-insert-img

● Handler Chain

用于加载一系列Handler并处理消息,目前支持负载均衡,路由管理,监控等功能,用户可以通过配置文件定义加载多种handler。请求调用时,会按照配置文件中的定义的顺序进入handler进行处理

need-to-insert-img

Handler的设计可以保证每一个handler都能得到后面的handler的执行结果。比如:熔断和网络穿的功能就在chain当中,每当传输失败,都会被熔断拿到错误结果,并计算,当达到一定阈值,便会出发熔断。

● Invoker

由于RPC和Http的编程风格不同,go chassis使用2种不同的Invoker来解决调用,无论哪种Invoker都会初始化一个Invocation并最终进入处理链中进行处理,最终进入各协议的Client实现并传输到目标服务中,这一切对用户都是透明的。

RPC

为了降低用户学习成本,使用了go语言标准库中net/rpc的调用风格

need-to-insert-img

Http

为了降低用户学习成本,支持了go语言通用的http调用方式,允许用户任意操控原生http request 与 response,并且没有任何限制

need-to-insert-img

接下来,用一个微服务调用过程中最基本的Consumer到Provider的业务请求流程来看一下前面的那些关键对象是如何协同工作的.

● 客户端发送请求

need-to-insert-img

开发者使用Invoker来发起请求,Invoker创建统一Invocation对象

Invocation进入处理链进行处理,比如熔断,限流等

进入Load Balancing后,会根据Strategy和目标协议选择一个IP:port

将协议和IP port继续传送到Transport 后,根据协议选择具体的Client实现,并传入IP port进行发送

● 服务端接收请求

need-to-insert-img

接收到协议请求后,由各协议Server转为统一的Invocation模型

Invocation进入处理链处理,比如限流,分布式追踪

处理结束后,进入具体的业务处理逻辑

插件化机制

go的动态能力相对有限,go 1.8提供了插件能力,但是会给build带来复杂度,我们先来看看Java怎么解决插件化的

Class<?> act = Class.forName("com.bla.TestActivity");

基于这个能力也出现了Spring这样的项目,开发者可以轻松地解决插件化的问题

可是go语言该怎么做呢?

下面以Go chassis的实践为例

提供接口与Map定义

开发者需要实现接口,并实现NewFunc返回具体实现

注册插件

通过调用API进行插件安装

need-to-insert-img

使用插件

考虑到易用性贴近Spring的风格,chassis使用yaml格式的配置文件来管理插件。

以下为实现思路

启动和初始化机制如下:

need-to-insert-img

通过文件指定加载的插件,在Server之上我们封装Server manager管理所有协议的Server,并负责注册到注册中心,,收到系统终止信号时,负责反注册

使用了Client manager与https://github.com/ServiceComb/go-chassis/blob/master/core/handler/transport_handler.go 对client进行封装,按协议,微服务,实例的唯独进行client初始化,即每个实例都有专属client。

支持的插件

chassis框架支持以下插件,具体请参考gitbook文档https://go-chassis.readthedocs.io/en/latest/。

Handler

Provider

Cipher

Bootstrap

Logger

Config Source

Registry

InjectFault

Server

Client

Strategy

Tracing

客户端负载均衡

客户端负载均衡器负责使用本地的注册中心缓存来进行服务发现。

go chassis 封装了很多的高级特性

融合了Backoff算法,以使网络流量稳定。

容错支持在请求错误后以怎样的策略进行重试

会话粘滞与延迟感知Strategy实现

动态治理,支持运行时热加载以上配置

支持目标服务级别的细粒度负载均衡策略配置(即一进程针对访问不同微服务,可控制负载均衡策略)

错误注入

为了能让用户轻松地制造系统混乱,在Consumer侧,实现了错误注入机制,可以根据配置定义错误或者故意制造调用延迟,来测试分布式系统遇到问题时的容错能力,同样支持运行时动态加载配置。目前只支持简单的错误和延迟以及发生百分比

开发者甚至可以通过此接口为一个协议安装错误注入插件,可完全替代目前的错误注入实现

与其他微服务开发框架的对比

go micro架构

图片来自go micro官网https://micro.mu/docs/images/go-micro.png

这里我引用micro.mu的关于go micro与go kit对比

Go micro是一个插件化RPC分布式开发框架,可以开箱即用,也可以任意定制自己的RPC协议中的每个模块。他是一个eco system,现在已经有大量的插件实现,并在go-micro基础之上有了很多的新框架,Micro组织下有许多围绕go-micro建立的子项目。

Go kit是一个用来构建微服务的的工具包,每个包都是独立的,开发者自己选择需要的工具组装自己的微服务,包含了丰富的治理功能,熔断,监控,限流等,且拥有丰富的插件化协议和注册中心。

Go chassis是插件化框架,与Go micro的不同在于,go chassis提供的能力是插件化协议,你可以将http或RPC,甚至是Mysql,Redis等协议接入到框架中,并且提供一站式功能,将熔断,限流,监控等功能全部集成到框架中,开发者无需自己寻找这些方案。拥有3者中最丰富的治理功能。同样拥有开放的定制能力,但是作为一个新的框架,生态尚需完善。

开发者可以通过开发体验和特性支持对框架进行选型。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容