《Go 语言并发之道》读后感-第五章

《Go 语言并发之道》读后感目录

大规模并发

这一章我或许没有办法写出一些实例代码,因为经验有限。我会结合以往运维的一些系统举出部分例子共读者参考,详情力荐阅读原文。

异常传递

异常时什么,什么时候发生,提供哪些好处?我们需要明确以下信息:

  • 发生了什么,例如:磁盘已满,证书过期,链接超时,不存在的路径
  • 发生在什么时间,什么位置,优秀的 Golang 第三方日志库可以帮助到我们
  • 对用于友好的信息,例如:给与类似的提示信息,参考 linux 命令行提示
  • 告诉用户如何获得更多的信息,例如:man 手册

异常通常被我们分为两类:

  • Bug 未知,未发现的错误
  • 已知信息。例如:用户传入错误参数,网络断开,证书过期

正如上一章错误处理中所说我们需要将错误视为一等公民存在,个人认为 Golang 错误处理机制的特立独行,让我重新审视系统中可能存在的错误。

超时和取消

超时:对于创建一个已于理解的系统是至关重要的,例如:TCP 链接中,我们可以利用超时避免链接占用过久;etcd 中利用超时,规避全局时钟一致性问题

我们为什么希望并发程序支持超时呢?这里有几个原因:

  • 系统饱和
    • 请求在超时时不太可能重复
    • 没有资源来存储请求,例如:内存队列的内存;持久队列的磁盘空间;消息队列阻塞
    • 如果对系统响应或请求发送数据有时效性要求,例如:访问网页
  • 陈旧数据
    • Kafka log 清理机制,默认2小时前的数据被清理
    • Redis 中的缓存
  • 试图防止死锁
    • 在关键的并发操作中增加超时处理

并发进程可能被取消的原因有很多:

  • 超时,隐式取消
  • 用户干预,例如:正在执行某个命令,等了太久,你按了 Ctr + c
  • 父进程取消,例如:ppid 被 kill ,那么所属 pid 也会被 kill
  • 复制请求,例如:同时有多个请求,哪个最先返回用哪个的

心跳

在分布式系统中非常常见的,心跳是并发进程向外界发出信号的一种方式。书中讨论了两种心跳:

  • 在一段时间间隔内发出的心跳,例如:Server 和 Agent 之间的通信;分布式系统中个节点的心跳,确保领导者存活的心跳;
  • 在工作单元开始时发出的心跳,例如:分布式计算任务,确认计算单元是否完成任务,或宕机

复制请求

当一个请求到达我们的服务,我们可以使用 Nginx ,HAproxy 等分发到多个节点上,但这会消耗过多的计算资源,空间资源(服务器机柜),维护成本。如果我们都在进程内,或进程间通信,我们仅仅多消耗了一部分内存资源。最为典型的案例就是利用 Golang 重写了负载层的中间件,例如:

速率限制

笔者最近刚刚到一家网络安全公司就职运维工程师,了解到很多关于网络攻击的信息,最为明显的就是 DDoS,CC攻击。DDoS 的攻击可能是利用 udp服务反射, 或残缺报文造成流量洪峰,可能比较已于识别。但是 CC 攻击,就是正常的访问,大量的正常访问,导致网站不可用。对于这样的场景我们不单单需要在负载层添加速率限制,在后台内部调用层也需要添加。

特别是在容器化的环境中,弹性扩缩虽然美好。但是有一句至理名言,一样东西有多光鲜,背后就有多阴暗。我曾经经历过,服务疯狂扩容导致运行在小机上的 Oracle 数据库不堪重负的场景。在访问 Oracke 也需要速率限制。

治愈异常的 goroutine

作者最后又再次强调了,治愈异常的 goroutine ,看来并发安全一直是一个非常值得关注的问题。

结束语

本次连载到此就要画上句号了。至于原书的最后一章 goroutine 和 Go 语言进行时,我相信中文集里面没有人比刘丹冰讲的更加透彻,希望各位给与作者三连支持。附上 B 站链接 GPM 模型

2021 让我们共同启航,在十四五开局之年,金牛聚福,身体健康,驱疫避害。

1赞