基于Go技术栈的微服务构建

在大型系统的微服务化构建中,一个系统会被拆分成许多模块。这些模块负责不同的功能,组合成系统,最终可以提供丰富的功能。在这种构建形式中,开发者一般会聚焦于最大程度解耦模块的功能以减少模块间耦合带来的额外开发成本。同时,微服务面临着如何部署这些大量的服务系统、如何运维这些系统等新问题。

本文的素材来源于我们在开发中的一些最佳实践案例,从开发、监控、日志等角度介绍了一些我们基于Go技术栈的微服务构建经验。

开  发

微服务的开发过程中,不同模块由不同的开发者负责,明确定义的接口有助于确定开发者的工作任务。最终的系统中,一个业务请求可能会涉及到多次接口调用,如何准确清晰的调用远端接口,这也是一大挑战。对于这些问题,我们使用了gRPC来负责协议的制订和调用。

传统的微服务通常基于http协议来进行模块间的调用,而在我们的微服务构建中,选用了Google推出的gRPC框架来进行调用。下面这张简表比较了http rpc框架与gRPC的特性:

gRPC的接口需要使用Protobuf3定义,通过静态编译后才能成功调用。这一特性减少了由于接口改变带来的沟通成本。如果使用http rpc,接口改变就需要先改接口文档,然后周知到调用者,如果调用者没有及时修改,很可能会到服务运行时才能发现错误。而gRPC的这种模式,接口变动引起的错误保证在编译时期就能消除。

在性能方面,gRPC相比传统的http rpc协议有非常大的改善(根据这个评测,gRPC要快10倍)。gRPC使用http 2协议进行传输,相比较http 1.1, http 2复用tcp连接,减少了每次请求建立tcp连接的开销。需要指出的是,如果单纯追求性能,之前业界一般会选用构建在tcp协议上的rpc协议(thrift等),但四层协议无法方便的做一些传输控制。相比而言,gRPC可以在http header中放入控制字段,配合nginx等代理服务器,可以很方便的实现转发/灰度等功能。

接下来着重谈谈我们在实践中如何使用gRPC的一些特性来简化相关开发流程。

1. 使用context来控制请求的生命周期

在gRPC的go语言实现中,每个rpc请求的第一个参数都是context。http2协议会将context放在HEADER中,随着链路传递下去,因此可以为每个请求设置过期时间,一旦遇到超时的情况,发起方就会结束等待,返回错误。

ctx := context.Background()     // blank context

ctx, cancel = context.WithTimeout(ctx, 5*time.Second)

defer cancel( )

grpc.CallServiveX(ctx, arg1)

上述这段代码,发起方设置了大约5s的等待时间,只要远端的调用在5s内没有返回,发起方就会报错。

除了能加入超时时间,context还能加入其他内容,下文我们还会见到context的另一个妙用。

2.使用TLS实现访问权限控制

gRPC集成了TLS证书功能,为我们提供了很完善的权限控制方案。在实践中,假设我们的系统中存在服务A,由于它负责操作用户的敏感内容,因此需要保证A不被系统内的其他服务滥用。为了避免滥用,我们设计了一套自签名的二级证书系统,服务A掌握了自签名的根证书,同时为每个调用A的服务颁发一个二级证书。这样,所有调用A的服务必须经过A的授权,A也可以鉴别每个请求的调用方,这样可以很方便的做一些记录日志、流量控制等操作。

3. 使用trace在线追踪请求

gRPC内置了一套追踪请求的trace系统,既可以追踪最近10个请求的详细日志信息,也可以记录所有请求的统计信息。

当我们为请求加入了trace日志后,trace系统会为我们记录下最近10个请求的日志,下图中所示的例子就是在trace日志中加入了对业务数据的追踪。

在宏观上,trace系统为我们记录下请求的统计信息,比如请求数目、按照不同请求时间统计的分布等。

需要说明的是,这套系统暴露了一个http服务,我们可以通过debug开关在运行时按需打开或者关闭,以减少资源消耗。

监控

1.确定监控指标

在接到为整个系统搭建监控系统这个任务时,我们面对的第一个问题是要监控什么内容。针对这个问题,GoogleSRE这本书提供了很详细的回答,我们可以监控四大黄金指标,分别是延时、流量、错误和饱和度。

延时衡量了请求花费的时间。需要注意的,考虑到长尾效应,使用平均延时作为延时方面的单一指标是远远不够的。相应的,我们需要延时的中位数90%、95%、99%值来帮助我们了解延时的分布,有一种更好的办法是使用直方图来统计延时分布。

流量衡量了服务面临的请求压力。针对每个API的流量统计能让我们知道系统的热点路径,帮助优化。

错误监控是指对错误的请求结果的统计。同样的,每个请求有不同的错误码,我们需要针对不同的错误码进行统计。配合上告警系统,这类监控能让我们尽早感知错误,进行干预。

饱和度主要指对系统CPU和内存的负载监控。这类监控能为我们的扩容决策提供依据。

2.监控选型

选择监控方案时,我们面临的选择主要有两个,一是公司自建的监控系统,二是使用开源Prometheus系统搭建。这两个系统的区别列在下表中。

考虑到我们的整个系统大约有100个容器分布在30台虚拟机上,Prometheus的单机存储对我们并不是瓶颈。我们不需要完整保留历史数据,自建系统的最大优势也不足以吸引我们使用。相反,由于希望能够统计四大黄金指标延生出的诸多指标,Prometheus方便的DSL能够很大程度上简化我们的指标设计。

最终,我们选择了Prometheus搭建监控系统。整个监控系统的框架如下图所示。

各服务将自己的地址注册到consul中,Prometheus会自动从consul中拉取需要监控的目标地址,然后从这些服务中拉取监控数据,存放到本地存储中。在Prometheus自带的Web UI中可以快捷的使用PromQL查询语句获取统计信息,同时,还可以将查询语句输入grafana,固定监控指标用于监控。

此外,配合插件AlertManager,我们能够编写告警规则,当系统出现异常时,将告警发送到手机/邮件/信箱。

日志

1.日志格式

一个经常被忽略的问题是如何选择日志记录的格式。良好的日志格式有利于后续工具对日志内容的切割,便于日志存储的索引。我们使用logrus来打印日志到文件,logrus工具支持的日志格式包裹以空格分隔的单行文本格式、json格式等等。

文本格式

time=”2015-03-26T01:27:38-04:00″ level=debug g=”Started observing beach” animal=walrus number=8

time=”2015-03-26T01:27:38-04:00″ level=info msg=”A group of walrus emerges from the ocean” animal=walrus size=10

Json格式

{“animal”:”walrus”,”level”:”info”,”msg”:”A group of walrus emerges from theocean”,”size”:10,”time”:”2014-03-10 19:57:38.562264131 -0400 EDT”}

{“level”:”warning”,”msg”:”The group’s number increased tremendously!”,”number”:122,”omg”:true,”time”:”2014-03-10 19:57:38.562471297 -0400 EDT”}

2.端到端链路上的调用日志收集

在微服务架构中,一个业务请求会经历多个服务,收集端到端链路上的日志能够帮助我们判断错误发生的具体位置。在这个系统中,我们在请求入口处,生成了全局ID,通过gRPC中的context将ID在链路中传递。将不同服务的日志收集到graylog中,查询时就能通过一个ID,将整个链路上的日志查询出来。

上图中,使用session-id来作为整个调用链的ID可以进行全链路检索。

小结

微服务构建的系统中,在部署、调度、服务发现、一致性等其他方面都有挑战,Go技术栈在这些方面都有最佳实践(docker,k8s,consul,etcd等等)。具体内容在网上已经有很完善的教程,在此不用班门弄斧,有需要的可以自行查阅。

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

推荐阅读更多精彩内容