写在前面
最近一年来,我都在做公司的RTB广告系统,包括SSP曝光服务,ADX服务和DSP系统。因为是第一次在公司用Go语言实现这么一个大的系统,中间因为各种原因造了很多轮子。现在稍微有点时间,觉着有必要总结这一年来用Go造轮子的经验和不足。
集群中遇到的配置文件管理问题
RTB广告系统中涉及到的服务程序并不算很多,但是因为RTB系统会面临很多的流量,而且为了确保可用性,最基本的就是多实例组成集群,同时考虑到后续业务增长,集群的扩缩容也是要做的。我们在设计的时候,基于ZoooKeeper做了服务发现,而我们的服务接入依靠Nginx集群,然后通过反向代理把请求负载均衡到不同的服务实例中。这里就存在以下问题:
当我们升级某个服务时,如何通知Nginx集群自动的摘除或者添加该服务实例,保证我们的升级不会影响到业务和用户体验
进一步,任意一个服务集群内的配置数据该如何自动更新和应用?
业界方案
业界其实有很多成熟的方案解决这类问题:
比如开源项目consul-template,但是这个工具只支持后端consul,而我们用的是ZooKeeper
再比如confd,可以支持多种后端,比如etcd或者zookeeper,但是它用的ZooKeeper客户端不支持在故障时对业务请求进行重试,比如发起了一个GetW请求,而Session变成超时状态,这个时候GetW返回的Channel就不可用了,只能重新发起请求,但是重试多少次请求其实是不知道的,针对这个情况,我还在项目一开始的时候实现了新的包,加入了对业务层透明的重试机制。
整体工作流程
解析模版,获取要动态查询的节点
向指定的服务器,比如ZooKeeper发起查询请求,并观察指定节点的变化
当第一次或者节点发生变更后,查询最新数据
把最新数据应用到模版中生成新的配置文件数据
保存最新的配置文件数据到目标路径,并调用指定的命令应用最新的配置文件
实现
模版机制
Go官方标准库提供了Template包,支持if, range等控制语句,也支持用户自定义方法。模版机制的方便之处在于,它本身是一种DSL,也算是一种支持计算的超级printf。举例如下:
延伸阅读
- ssh框架 2016-09-30
- 阿里移动安全 [无线安全]玩转无线电——不安全的蓝牙锁 2017-07-26
- 消息队列NetMQ 原理分析4-Socket、Session、Option和Pipe 2024-03-26
- Selective Search for Object Recognition 论文笔记【图片目标分割】 2017-07-26
- 词向量-LRWE模型-更好地识别反义词同义词 2017-07-26
- 从栈不平衡问题 理解 calling convention 2017-07-26
- php imagemagick 处理 图片剪切、压缩、合并、插入文本、背景色透明 2017-07-26
- Swift实现JSON转Model - HandyJSON使用讲解 2017-07-26
- 阿里移动安全 Android端恶意锁屏勒索应用分析 2017-07-26
- 集合结合数据结构来看看(二) 2017-07-26