公司使用阿里的云主机部署计算型的服务,就是特别耗cpu的那种。使用过程中有一件事情很苦恼,那就是云主机的性能是不一致的,机器间的性能可相差30%,更严重的是由于是共享云主机,经常在晚上8点钟左右(各大网站的高峰期)有某些机器的系统cpu突然飙高(原因是一次系统调用消耗突然增加,系统cpu能飙到90%,机器基本不可用)。这个问题其实很好解释:阿里云在同一个物理机上虚拟好多云主机,并且云主机之间隔离做的不好,一台云主机可能会影响同一物理机上的另一台云主机,导致你的云主机性能有问题的可能是另外一家公司使用的云主机。多次向阿里提出这个问题,阿里并没给啥解释,就是推荐我们换一台云主机试试(这是玩我呢么?)。而我要在这么不靠谱的机器上要做到服务稳定,最需要解决的问题就是如何动态的根据机器的性能变化调整分配给每台机器的流量。
阿里的slb提供了几种流量调度算法:轮询调度、加权轮询调度、最小连接数优先调度。
所以,最终我放弃了。看来必须自己解决这个问题,那么就顺手写个流量调度算法吧。
首先要明确我们想要解决的问题是根据机器的性能分配流量,面对的第一个难题就是如何实时的获取机器性能信息呢?大多数小伙伴的思路是实时获取机器的cpu信息,但是我认为这太复杂,还需要开发一套实时收集cpu信息的辅助系统,不划算。我只利用一个信息:某段时间内调用某个机器上服务的失败次数。
第二个问题就是客户端自适应算法不是全局感知。我说的全局感知是:由统一的服务收集并记录客户端调用每个服务的失败次数,客户端根据这个集中统计数据来分配流量。我们不采用全局感知,就意味着每个客户端根据自己当前得到的信息进行局部的流量分配,这可行吗?可行!如果客户端数量足够多,根据统计学意义,所有局部感知的结果汇总和整体感知的效果基本相当。当客户端数目不够多的时候呢?反证法:如果存在一个服务接收过量的请求,那么推测肯定有某一客户端调用该服务会失败,那么该客户端就会主动减少对这台后端的服务的调用,从而减少这个有问题服务接收的请求数。接下来说说说算法设计思路:初始时设置每台后端机器的权重w=10,当超时10次的时间间隔(最后一次超时的时间戳与第一次超时的时间戳相差)小于10s时,则对这台机器的权重减1,从而减少10%的流量。
但是现在这个调度算法并不完善,有如下几个问题要解决。
如何使用我们的算法呢,实例如下:
- Address addr;
- Algorithm *algorithm = new WeightSelectAlgorithm(...);
- algorithm->next(addr); //选择一个服务
- int ret = request(addr);
- if(ret != 0) {
- algorithm->failed(addr.host, addr.port); //请求失败
- } else {
- algorithm->succeed(addr.host, addr.port); //请求成功
- }
我这里只给大家提供了这个设计思路,具体代码实现我相信难不倒各位小伙伴,这里就不贴了。算法初始化时需接受一些配置参数,一定要保证这些参数可以手动调整,直到达到满意的效果位置。这个算法上线后的效果还是挺好的,请求失败的次数能够降一个量级,由于客户端有重试策略,最终失败的调用次数可以忽略不计。
来源: http://www.cnblogs.com/haolujun/p/7574220.html