业务背景
设计一个消费,存储,和查询log的service。目标用户是百万级别的运行在AWS上的application。
系统需求
功能需求
1. application可以向log service发送写入log的请求
2. 支持log query
3. retention policy:用户可以选择7天,30天,90天,1年,永远
4. 支持产生log stream,可以被Lambda消费
非功能需求
1. scale:1000万的AWS 用户
2. 100 million的服务器
3. 每天10PB的数据
4. 99.99% availability
5. query时延:最新log - <2seconds; 历史log - <10seconds
API设计
向log service发送写入log请求:
POST /query
request body: {
"timestamp": "1782442276",
"content": "success: impl is done",
"level": "WARN",
"application": "APP"
}
log query:
GET /query?timestamp=1782442276&keyword=success&app=APP
系统架构设计
系统架构图如下所示:
下面描述整个系统架构图:
通过API Gateway我们将请求分别转发给ingestion agent和Log-Query-Service,实现microservice的架构。
1. Ingestion数据流:
1)ingestion agent将log ingest到kinesis数据流;
2)FLINK consume kinesis,同时FLINK通过meda-DB获得每一个log的retention policy;
3)FLINK将数据batch的写入到S3。这里我们可以为每一个application建立属于它的log group。在log group内,我们按照时间将同一个application的log分成多个log stream进行保存;
4)S3的每一个log file create和update通过CDC(同时这里应该有一个CDC的consumer,在图中省略)将log的内容保存进OpenSearch。OpenSearch对log file建立了revert index,可以支持各种查询条件;
5)Log-Query-Service通过open-search查询到相关log随对应的log file,然后log-query-service可以读取log file获得完整的返回信息。
讨论
1. 如何实现高频log保存:当大量的log persist请求发送到service端,首先ingestion-agent因为是无状态的,可以实现无限扩张。Kinesis内部基于shard。如果一个application的log非常大,我们必须通过多个shard来支持它的log,否则会有hot partition的问题。根据application log的具体业务要求,如果我们可以将log分发到多个shard就可以实现scale out的要求。这样我们将只在同一个shard内部保留时间的绝对顺序,shard与shard之间的顺序是eventual consistency。如果application的业务要求所有的log要整体保持有序,如果我们仍然必须使用多个shard来支持流量要求,我们可以考虑产生一个sequence number。这样log仍然可以分发到多个shard上,但是我们需要在consume的时候做merge。
2. 如何处理query的scale问题:如果query数量很大,我们可以通过open-search的data nodes配置来解决。将数据分发到多个data node可以减少访问一个data node时带来的数据量的压力和时延压力,但是我们需要merge最后的结果,所以这也是一个trade-off的问题。一般对于大量的数据我们倾向于将data-node设置为3到6个。另外,open-search本身有cache,如果query集中于几个热门学校,cache将有很大帮助。
3. 怎样处理service端crash的情况:service如果crash我们需要考虑在client端设有本地存储。log先保存在本地,直到service恢复了再将log保存到service。


1372

被折叠的 条评论
为什么被折叠?



