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


当前第2页 返回上一页

不是可以隔离出来,这样不要因为压力大的服务影响应该小的,然后稳定性高的影响稳定性。

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

图5

早期没有服务器时,其实都是统一布在一台机器上,有可能AB两个服务,A出问题了,B跟着遭殃。其实经历过一段时间没有容器,就是用物理机的阶段是非常糟糕的,真的要用手动 cgroup ,然后限定每一个资源。那么物理隔离就是买机器。轻重隔离的话,像我们有一些队列可能东西非常多,有一些队列可能东西非常少,如果你都放在一个里面 Topic ,还是有影响的。举个例子,像我们视频转码的时候,它会有分超长和超短的文件。如果超短和超长的放在一种队列里面,它其实就是一种轻重隔离。像我们的集群,甚至有不同的部署,也是腾讯经常提的按集群部署。

第二个要提的就是超时。因为RPCE里面,最重要的就是超时,超时有很多种,如连接超时、读取超时、写入超时等,如图6所示。我当时用 Go 1.3 开始用 Go 写代码,当时发现很多地方是没有的,导致我们有一次出现了一个故障,就是某一个机房的业务连了一台 DB ,当时那个线断了,导致进程全部堵住了。具体是怎么排查的呢,因为我们发现CPU不高,然后数据库报了一下错,之后请求也进不来,后来还是用 GDB 去调,看它正在运行的 gorutnine 的对帐到底卡在哪里,当时还有一些其他的方法。后续的引进,我希望对我们采集到的数据,不断的对我们的服务去调整这个超时。

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

图6

第三个就是限流。限流也非常多,如图7所示。举一个例子,我们在去年应该说有一个业务夯住了,具体什么问题呢,挂的是上层 Nginx 的 upstream ,因为它没有设置 upstream 的一个 timeout,导致我们的交换机对着三四百个连接,然后交换机挂掉了。发现之前说好的交换机有在备,结果也全部挂掉了。所以我们后来总结了一下,还是要有限流保护的,限流就是避免一波CC***就直接把你打挂了。所以我们在这上面做了分布式的限流,类似的方案都有。我们的连接限流,这些都是重要的资源,一定要注意。像 Go 的话,有一个指标里面就有一个限流连接数的,这些都可以使用,避免一下子拖了太多的连接进来把你打死。像请求限流,当发现情况的时候立马调整它的流量,把你打的 CC 的那个流量给去掉。

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

图7

然后提一下降级。也是非常多,如图8所示。我们早期的话,第一步做UI降级,我们每次发生故障时,发现如果你的移动端打不开,用户会疯狂的刷,可能刷一会就打开了,其实这时候请求数会越来越多。后来我们在客户端做降级,比如你连续刷的话,我会下达一个 TTL ,这些可以在客户端做一些调整,如果实在扛不住的时候可以发一个10秒钟,甚至30秒钟的超长的 TTL 告诉客户端这时候不要请求。我记得支付宝不是收到一个好像太忙了不让你支付还是什么,其实就是有客户端的一个限流,这个是终极手段。

还有功能降级。也比较简单,比如我们某个页面上面有一些大数据,或者人工智能的推荐的数据,这个模块可能会导致某一个实验导致数据的崩溃了,所以这时候就有一些空窗,或者整个页面都打不开,这个体验就不好。那这时候就有很多的方法,比如可以把另一块 UR 返回一个灾备的推荐池,至少避免整个页面打不开。所以你的接口吐出去的时候,如果有一个依赖的业务方挂掉,你一定要考虑你有没有一些手段可以降级,或者是返回一些默认的、甚至返回静态的数据。

我记得京东有一篇分享就讲过,他们如果出现非常严重的故障,商品的详细页是可以返回一个静态的。因为我们商品的很多东西是不可能实时变更它的内容的,我觉得这也是一种方式吧。那还有一些自动的降级,我们其实做的比较多的是像统计失败的降级。比如我请求某一个接口,它如果错误率比较高,或者超时比较多,我是不是可以不调它了。虽然你依赖了很多业务方,你可以降级,但是如果它超时,其实你最终的延时也会增加,所以这时候要把它踢掉。

还有一些情况,比如我们核心业务,或者是一些关键的业务不能做自动降级的时候,这时候你拿捏不准,你一定要做一些功能开关,在适当的时候可以把它打开,不再返回那个数据,或者不请求它。

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

图8

最后就是容错。如图9所示。容错我们做的比较多的就是熔断,其实也有参考一个 Java 框架,把它改成了 Go 的版本,然后做了一个熔断。其实它的核心思路非常简单,就是当我的请求数量达到多少以后,我的错误率到达多少以后,我是不是可以不调它,不调就可以快速返回,叫 fail-fast。fail-fast 这个阶段一过,我是不是要放一些流量进去试探它有没有恢复。这时候比如100毫秒放一个流量进去,如果成功了,我认为服务器稳定了,再把开关打开,把整个流量放进去,再看如果还不行,会重复这样的过程。

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

图9

还有一些重要业务,像我们依赖队列的一些业务,它可能会做努力送达模型。这种情况下,我们可能会无限重试,直到它成功,否则就是一直等待。一秒钟加一个随机数,不断的去重试。


本文来自:51CTO博客

感谢作者:mob604756f0bbf4

查看原文:毛剑:Bilibili 的 Go 服务实践(上篇)

返回前面的内容

相关阅读 >>

模块二 Go语言进阶技术-panic函数、recover函数以及defer语句(下)

Go设计模式之策略模式浅谈

Golang官方嵌入文件到可执行程序

Golang有什么用途?

手撸Golang Go与微服务 聚合模式之1

Golang能否替代php

Golang不适合开发web吗

堆排序

Golang实现二叉树路径遍历

Go 内存模型 并发可见性

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




打赏

取消

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

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

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

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

评论

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