QoS设计


对于QoS,维基百科给出的定义是:
在数据包交换网络和计算机网络领域中,流量工程术语服务质量(英语:Quality of Service,QoS)指的是网络满足给定业务合同的概率,或在许多情况下,非正式地用来指分组在网络中两点间通过的概率。QoS是一种控制机制,它提供了针对不同用户或者不同数据流采用相应不同的优先级,或者是根据应用程序的要求,保证数据流的性能达到一定的水准。

传统的因特网是尽力而为的模式。比如我们同时在视频通话和下载电影,视频通话要求的实时性较高,当两者出现冲突时,正确的做法是优先保证视频通话的带宽。

对SaaS应用来说,我们为多个用户提供服务,如何根据SLA给用户提供不同的服务质量是一个很大的难题。试想一下:

  1. 当系统资源紧张时,我们是优先保证大V用户还是体验用户
  2. 如何保证不会因为某个用户的流量洪泛导致整个SaaS系统崩溃或者影响到其它用户
  3. 如何针对不同的用户提供不同的服务质量,比如高价值的客户、重点客户是否应该提供更高的服务质量

搜索平台针对外部接口做了对应的QoS设计。搜索平台的外部接口有两个地方:

  1. 提供RestFul接口供业务调用,目前该接口主要用于查询
  2. 数据流模块通过订阅业务的数据变更MQ消息,保证和业务数据同步,此接口主要用于数据的增删改

1. 数据流

通过如下的场景介绍MQ消息的QoS是如何工作的:

1.1 消息转发

假设系统中有两个Admin用户A01、A02,其中A01是签约用户,A02是体验用户,每个用户都有三条消息,经过Listener转发后消息队列如下图:

1.2 消息流控

MsgQoS应用就是用来对消息进行QoS处理的。MsgQos或获取每个用户的配置参数,用户的QoS配置参数获取原则如下:

  1. 该用户是否设置了QoS相关参数,如果设置了直接使用该参数,如果没有则转到2
  2. 判断该用户是否是VIP用户,如果是则使用VIP用户的QoS参数,反之则采用体验用户QoS参数

根据用户的QoS参数对用户消息队列中的消息进行处理,如果该用户的消息处理速率超过阈值,则不处理,反之将消息提交到Worker集群中进行处理。

1.3 消息处理失败重做

如果Worker处理消息失败,会将该消息提交到该用户的失败消息队列。假如用户A01的消息2处理失败,则Worker会将消息2提交到A01的失败消息队列。MsgQoS同样会对失败消息队列进行重做,根据失败原因、用户类型,每种消息的重做策略是不同的。MsgQoS处理失败消息同样是有QoS配置的,基本原理同消息流控。

1.4 最终失败消息队列

如果消息到达设置的重做策略阈值仍然失败的话,比如设定的重做策略是重做2次,2次仍然失败的话会把消息添加到最终失败消息队列,该队列中的消息需要手工处理。

2.RestFul接口服务

对于搜索平台来说,查询属于比较不消耗资源的操作,我们主要针对的是对数据的变更操作,当前大部分数据变更操作都是通过MQ消息完成的,使用RestFul接口(PUT、POST、DELETE)进行操作的情况较少,因此针对RestFul接口的QoS上,只实现了失败消息重做。

2.1 队列的选择

MQ消息中只存储用户进行的操作、用户AdminId、操作的商品或者资源ID,数据是很小的,应该可以使用Redis作为消息队列的存储载体。RestFul PUT和POST支持批量操作,且操作请求的body中可能是完整的资源,假设一条资源为1KB,那么100条资源就是100KB,这么大的数据放在Redis中是不合适的。

Kafka作为一种分布式的、基于发布/订阅的消息系统,提供了很高的吞吐量并且使用硬盘作为存储介质,还是比较适合我们的需求的。失败的RestFul请求消费的顺序搜索平台是不关心的,因此我们选用Kafka的topic作为RestFul失败操作请求队列。

2.2 时间戳的使用

假设有如下的两个PUT请求:请求1修改资源为{"id": 1, "name": "name1"},请求2修改同样的资源{"id": 1, "name": "name2"},请求1先执行,请求2后执行。请求1在执行的过程中失败了,请求2成功了,在重做请求1的时候又会把资源改成{"id": 1, "name": "name1"},这个是错误的,其实此时请求1已经不需要再重做了。

如果识别这样的场景呢?假设我们根据收到请求的时间在资源中添加一个时间戳字段,这样请求1修改资源为{"id": 1, "name": "name1", "timestamp":time1},请求2修改资源为{"id": 1, "name": "name1", "timestamp":time2}。重做请求1的时候,比较两个时间戳time1和time2,如果time1<=time2,那么请求1是不需要重做的。

2.3 请求重做

WebServer会把失败的RestFul请求放到用户的Kafkaf队列中,RestFulQoS应用Get该Topic的请求,取到请求后根据重做策略检查是否已经到重做时间,如果没有会重新添加到消息队列;如果已经符合重做策略要求,则提交给WebServer重新执行。

results matching ""

    No results matching ""