ConcurrentMap和graceful quit

重读ConcurrentMap时,对于作者采用分片的方式有些疑惑,我的思路是:

既然是通过缩小lock控制的快大小来提升map在并发情况下的性能,那为什么不将粒度拆分到最小,即一个kv一个lock,这样性能岂不是最好。

上述思路错误的原因在于,没有考虑到使用ConncurrentMap的上下文,如果lock控制的粒度最小,这样会增加构建map的时间,导致不能频繁创建map。

作者内置了分片数量(32),这可能是在构建map时间和操作map时间上做的一个权衡,不过如果该map用于存储服务整体的配置,配置数量固定(常数),且经常变动,那么锁粒度尽量小,能减少上写锁时对于程序的影响。

之前做的网关项目的配置更新频率低,配置数量也是固定的(随着api数量增长会有所增加),因为各map仅在程序启动时加载,所以拆分粒度可以更小。

重读manners,纠结的点是什么样的交互才算是graceful,不打断用户请求,通过明确的response告知用户服务器将要停止,让停止过程可以控制。

下面按步骤描述manners控制http.Server退出服务的过程:

  • 拒绝掉新进入请求gracefulHandler.Close(),通过atomic原子变量实现,如果还有server请求该服务,Status Code返回200,Body为空,这部分请求客户端还是会失败,但不会因为直接退出进程导致客户端和server端的conn被关闭,客户端收到connect被关闭异常,通常情况客户端直接会把异常抛出给用户,manners把这种情况包装一下,可以根据实际情况进行定制。
  • 关闭listener.Close()listener包含一个无限for循环,不断接受请求,并启动goroutine,让handler去处理。注意正在处理请求的conn不会被关闭,conn会在处理完请求后把自己状态标记为stateidle,然后由hook方法处理。
  • sync.WaitGroup阻塞进程,等待请求处理完毕。
ConcurrentMap和graceful quit
Share this