背景
公司在重度使用aws的ECS 功能。 ECS 简单来说就是亚马逊版本的docker服务。最近aws默认的cloudwatch free-tier已经超过限制了。 所以就想自己搭建日志平台。
大致平台如下:
因为公司的使用了各种语言python nodejs java和各种开源软件服务比如airflow而我们需要解决的就是:对各种服务的日志如何快速统一的收集到我们的平台之中。
调查发现后, aws实际上提供了一个服务:aws firelens 可以用于快速的将日志转发到其他地方, 比如splunk。 一个典型的配置如下:(在ecs的task definition的container 定义中)
这里24223是loki对外服务的端口地址。
问题
发现收集到的日志并没有正确的解析, 上报的数据是一个json格式的比如:
{
"container_id": "82b1fdfa1ca4d69cf8f19.....6c857c",
"container_name": "/ecs-sxxxxx00",
"source": "stdout",
"log": "08-20 02:12:57.023.+0000 [INFO ][http-nio-7070-exec-1][c.f.i.w.c.MetricController.scrape:20]Metrics received 16247",
"ec2_instance_id": "i-xxxxxxx",
"ecs_cluster": "xxxx-stage-cluster",
"ecs_task_arn": "arn:aws:ecs:us-west-2:zzzzzz",
"ecs_task_definition": "task-definition:5"
}
因为aws的firelens实际上是基于fluentbit/fluentd, 包含有ecs_xxx的信息。 会有点影响使用和查询。
解决办法
java语言
对于java最直接的办法就是找一个loki-appender, 比如我使用的这个:
lokiappender-Tjahzi
参考:所有clients
后面这样把java的相关模块弄完后
其他
看了下因为还是用到了python, 看看是不是有这样类似的方式, 结果发现python好像不多, 而且这样有2个缺点:(1) 要改代码。 (2)还有些三方组件比如airflow根本没机会改。
一次性解决的办法
所以后面想到了是否可以实现一个代理, 将收到的ecs日志, 处理后, 比如删除掉不用的tag然后再转发给loki, 这样岂不是很好?
所以我就实现了一个:基于springboot + Tjahzi 将log处理转发的proxy功能, 代码库在这里:aws-firelens-logrewriter
性能优化?
项目运行一段时间后, 我也在将更多的模块迁移到新的日志收集平台。 但是发现有些日志总是会丢失, 结果发现 我写的这个proxy oom了。 用top看了下, 发现用了600M内存, 然后整个机器就2G。因为在ec2 还在创业期就比较抠,在这个机器上同时安装了上述所有组件-prometheus+loki+grafana+proxy。想来oom也就正常了。
Idea? Quarkus
之前了解过, graalvm和quarkus, 想来这个proxy很简单, 所以正好拿来练练手。 所以就撸了一天,实现了一个native版本的proxy。
简单来说
遇到的问题
- 迁移项目中的第三方库。比如fastjson无法使用, log4j 无法工作
- native-image编译问题。 需要使用第三方docker-image编译。
- 启动后遇到有内存泄漏问题, 而要支持内存dump需要graalvm 企业版。 – 使用我提交的这个docker: https://hub.docker.com/repository/docker/edwardg/graalvm
- 代码中使用环境变量的地方要小心。 会被优化掉, 需要使用配置属性来解决。 比如:
https://github.com/gaoxingliang/aws-firelens-logrewriter/blob/main/aws-firelens-logrewriter-native/src/main/java/gaoxingliang/logrewriter/LokiController.java
- LOG4J的pattern format无法工作。
- LOKI4J的AtomicBuffer对齐错误。-- 解决办法是我自己拷贝了其中的部分类出来。
效果
最终, 生成文件从100M的jar到20MB的native文件。 还可以优化。内存降低300M。 启动关闭时间降低至0.01s.
源码库
aws-firelens-logrewriter-native
使用体验总结
使用起来来说,
好的地方:
(1) quarkus框架集成非常方便 很适合快速上手的脚手架项目。
(2)优良的启动时间。
(3) 更低的内存占用。
不好的地方:
(1)native image构建速度很慢。 消耗内存巨大。
(2)native image调试困难,社区版的graalvm无法dump内存。
(3)很多库使用上有限制或者无法正常工作。
结论: 玩玩可以 不适合在大 复杂项目中使用。