毛剑:Bilibili 的 Go 服务实践(上篇)


本文摘自网络,作者,侵删。

前言

在微服务流行的当下,bilibili(B站)也在业务快速增长的压力下,对历史系统进行了不断的优化,在所谓“大系统小做”的背后付出了挺多的努力,尤其是 Go 作为开发语言的整体运维的支撑相对比较薄弱,例如开发、部署、测试、集成、监控,调试等。在 GopherChina 2017大会上,B 站技术总监毛剑分享了微服务化道路上踩的“坑”以及最终演进后对整个微服务框架的思考。

本次演讲的内容会包含以下几块:1.B站微服务的演进过程;2.高可用;3.中间件;4.持续集成和交付;5.运维体系。

作者介绍

2015年起,在 bilibili(B站)负责 UGC平台和基础架构,开发了直播弹幕开源推送服务 goim ,B站分布式存储 BFS ,引导开发了B站 cache proxy,bili twemproxy 等,对历史主站架构进行迭代和重构,之前六年在猎豹移动工作,当过MySQL DBA,做过C开发,其中开发了gopush-cluster用于猎豹移动的推送体系。喜欢应用服务性能诊断,内核研究,稳定的服务端架构演变。

微服务的演进

原始框架

在刚进入 B站时,面临着技术架构上的一些挑战:首先是部署非常不方便,我们要在没有任何东西依赖的情况下把整套主站搭起来;然后代码方面有两个仓库,要部署的时候全部打包一块往上面扔,结果经常起不来;另外测试的成本也非常高。这样导致的后果是整个开发效率也比较低,因为职责不清晰,整个代码是一坨,不知道哪一个模块是谁负责,甚至有一些是公共的部分是很多人在负责。如图1所示。

毛剑:Bilibili 的 Go 服务实践(上篇)

图1

升级理念

首先要梳理业务的边界。因为整个B站的业务非常繁杂,我们先从全貌去看到底应该怎么拆分。所以我做了一个图,如图2所示。

毛剑:Bilibili 的 Go 服务实践(上篇)

图2

最顶层从我的视角看,一个是用户纬度,还有一个帐号,你从中间的服务看,它有会员、投稿、用户财产信息,还有关系链、动态推荐等。从底层的一些辅助服务看,有验证码、IP的查找、推送、配置中心,包括protobuffer的一些服务管理。

为什么要强调这个事情呢?就是起步做微服务的时候,一定要搞清楚整个业务的责权或者叫边界。我们一开始的打法就是农村包围城市,跟所有核心有关的业务逐步拆了。比如用户的播放历史、收藏夹、评论等,这些是跟我们主线没有直接关系的周边业务。先把这些做了。在升级的过程中一定要考虑一个兼容,不能做了一个api跟所有的不兼容。直到现在,我们涉及到最底层的帐号重构的时候,都是非常痛苦的,因为牵扯的部门非常多。

第二个就是资源隔离。怎么隔离呢?就是先买服务器,尽量不要跟不可靠的程序员写代码放在一块,先隔离出来。因为旧代码肯定有很多黑科技的,你先买一个新机器放在那里,你新重构的往这里面塞,老的就不要折腾了。而且在没有文档、什么都没有的时候,旧代码是很难复用的,最好买一个干净的新机器重新部署。

第三个是内外网服务隔离。之前B站在15年的时候也遇到一些安全事故,我们的APP KEY从客户端逆向被泄露,有人去请求了内网的一些接口。这是一个安全事故,也是一个安全风险。为什么出现这个问题呢?因为我们之前没有做内网的隔离,导致内网API就暴露在公网。因为我们当时就决定要把整个服务的职责梳理清楚。

如图3所示,我们从最顶层开始看,首先是SLB入口,进来以后回到 Gateway。举个例子,像我们的移动端对外的一些API,因为有些业务要在一个页面有很多聚合,所以我们封装成一个API。还有就是用户评论,是平台属性的可以直接对外提供API。但是有一些服务是不能对外的,比如像我们内部的服务和面向运营平台的运营审核操作。例如我们的运营平台要给某个帐号进行操作,这个时候一定不能对外的,不然如果有人发现这个接口,无论你用什么手段,他一定有办法来搞你。所以一定要做内外网的隔离,这几个角色定义完以后,Service这一层,其实我们看到微服务的最核心的一块,就是直接面对面的,就是业务的一个模块单元。

毛剑:Bilibili 的 Go 服务实践(上篇)

图3

接下来讲一个RPC框架。那RPC需要哪些特性呢?首先需要序列化,第一就是使用GOB,我第一个想法就是语言统一,尽可能多的是用Go来写。因为当你出现一个业务短版或者瓶颈的时候,发现这个人不会写Go,会很困难。Go统一之后,我们想用GOB是最方便,因为它什么内置类型都支持。第二个就是超时控制。因为一堵就挂了。假设你有一个提供者,他后面堵了,你越积越多,就挂了。所以要有一个超时控制,包括一些上下文的东西传递。像刚才说的APM的问题就可以通过上下文来控制。第三是要做一些拦截器,所以内网也要做一定的健全机制,包括权限控制、统计、限流等。第四是服务注册,我们当时对比了很多,最终选择的是 zookeeper,这块也在逐步改进去ZK,做一个AP系统。最后是负载均衡,这个地方也考虑了很久,像早期我其实使用像 LVS ,或者 DNS 来做这种调度的,但是这样从性能来说它并不是最好,因为假设你要用LVS,你要经过你的网络多传输几次,其实直点效果是最好的。但是因为当时成本的问题,所以我们用客户端负载直接实现的。

代码级实现

刚才说到用GOB,用GOB以后我们最合适的RPC是用标准库的net rpc,并对它做了一些改造。

首先是支持context,再一个是做了一个超时控制,这是两个测试的demo。如图4-1。

毛剑:Bilibili 的 Go 服务实践(上篇)

图4-1

有人问我这个东西改造是不是很困难,其实我们看了 net rpc的源码,整个实现非常简单,所以我们只要改极少的代码,风险比较小。

首先加了一个 context 对象,第一个参数必须具体实现一个 context 接口,就做了一步这样的改造就搞定了。我们所有的rpc方法首参数都是 context 。如图4-2所示。

毛剑:Bilibili 的 Go 服务实践(上篇)

图4-2

图 4-3 一开始也是一个 context 的注入,我们在里面放了比较多的东西,像方法、名字等等。我们对外的 context 其实内部有一个 rpc 的小的 context,放了我们可能会用到的一些东西。拦截器其实也比较简单,首先我定义一个抽象,有限流、有统计、有健全,然后我们在 rpc 库里面 server 端加入几行简单代码。

毛剑:Bilibili 的 Go 服务实践(上篇)

图4-3

然后我们还做了一些改进。首先如果大家压测过 net rpc,就会发现 get request 和 free request 是有全局锁征用的,所以我们把它改成一个 request scope 级别的一个优化。如图4-4右边,我们在 codec 里面把 response 和 request 放进去了。而且我们为了减少对象,不是用的指针,而是直接用的 struct 包含来做的,这样压力也会小一些。

毛剑:Bilibili 的 Go 服务实践(上篇)

图4-4

然后看一下握手。如图4-5所示。

毛剑:Bilibili 的 Go 服务实践(上篇)
图4-5

调度是怎么做的呢?也就是负载均衡。其实也比较简单,我们定义了一个接口,然后可能会实现这几个方法,比如广播、call、设置超时,并且设置某一个方法的超时。第四个其实是全局默认的一个超时,做了这个以后,我们配置的文件上面有地址、协议、分组和权重。我们第一版做的是 wrr 的策略,就是我有一堆client,你告诉我权重是什么,我按权重轮询调度,因为我所有的节点信息都在 zookeeper 上面,只要定期去根据事件拿取它的所有的节点变更,做一个客户端的配合,我觉得这个代码写起来也是比较简单的。

Group其实是后面一版加入的,等下我讲高可用的时候会重点来介绍。

毛剑:Bilibili 的 Go 服务实践(上篇)

图4-6

刚才我们是服务层搞定了,现在看一下网关层。网关要做聚合,回到刚才的场景,移动端的某个页面调了4、5个业务方,这不可能让移动端的同学直接对接。我们会从 Gateway 层统一做一个 API 给它,这样成本会非常低。协议的统一也在 gateway 层做的。

第二步我们做了并行优化,因为我们依赖的业务方非常多,有4-6个,所以要用 errgroup 做一个并行调用。Gateway 的话有两种做法,我们早期所有出口只有一个Gateway,后来发现不行,一个不小心的 bug 可能导致这个进程崩溃,然后它不断崩溃,其实非常危险。所以我们根据一些业务形态重要或非重要等做了一些隔离。它可能叫 APP Gateway,会员 Gateway,我们还是做了一些隔离的。最后的话就是我们在 Gateway上做的一些熔断、降级、限流、高可用等等。接下来就重点讲一下高可用的做法。

高可用

第一个是做隔离。我们看图5,首先是按业务的压力情况,有一些服务压力特别大,有一些服务压力特别小,它是

阅读剩余部分

相关阅读 >>

24 Goroutine channel实现并发和并行(一)

Go语言从入门到实战,带你拿下Golang的高效编程法

leetcode354 俄罗斯套娃信封问题 Golang

[Go] Go语言实战-为博客园增加Gofly在线客服功能

Go语言入门-1 环境搭建

[译]Go语言最佳实战[一]

Golang实现京东支付v2版本

Go语言实现定时器的方法是什么

Go 获取 html 标签中的文本_关于html中progress标签的定义及用法汇总!

Golang 如何并发

更多相关阅读请进入《Go》频道 >>




打赏

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码打赏,您说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

分享从这里开始,精彩与您同在

评论

管理员已关闭评论功能...