发主题的时候主要想法是局限在 python 的异步框架,不过也很好奇其他语言的框架都用什么解决方案,所以标题里没有写明是 python 。
问题简单来说,我们都知道 python 的 IO 流,例如常见的 print,是一个同步阻塞操作。而目前网络端的解决方案在向异步非阻塞转移,比如 fastapi/aiohttp 这类框架,转移的同时,日志又是很重要的一个功能,总不可能一个服务没有日志。这是否意味着框架转发性能将被严重降低,有什么解决方案吗?
1
lishunan246 2021-06-16 23:23:54 +08:00 via Android
日志可以用 syslog 或者 http 方式输出给专门的 agent 收集。
特别在意性能可以考虑换其他语言实现。 |
2
catcn 2021-06-16 23:25:46 +08:00
放内存,慢慢落磁盘,落得慢直接扔掉
|
3
binux 2021-06-16 23:28:22 +08:00 via Android
我们都知道 python 的 IO 流,例如常见的 print,是一个同步阻塞操作
不一定,看往哪写 |
4
joApioVVx4M4X6Rf 2021-06-16 23:39:02 +08:00
同问
|
5
LeeReamond OP @lishunan246 不是很在意性能,业务不会在这里达到瓶颈,只是好奇通常是怎么处理的
|
6
nightwitch 2021-06-16 23:42:06 +08:00
单独起一个线程负责 IO,其他要写日志的往一个 queue 里写,这个线程从 queue 里拿到日志就往硬盘里写就好了。
|
7
falcon05 2021-06-16 23:42:36 +08:00 via iPhone 1
openresty 就提供了非阻塞日志函数 ngx.log
|
8
ikas 2021-06-17 00:19:43 +08:00 1
参考 java 平台,先有 slf4j 通用日志接口,然后有各种不同日志框架实现.比如 log4j2,logback. 他们都支持配置 Appender,根据不同 Appender 你可以实现写入文件,db,console,或者其他服务.他们也都支持配置为异步,减少对业务影响,提高性能.
同时,编写业务日志也要注意日志粒度,如果是 debug 日志也要先判断 debug level,减少日志拼接损耗 |
9
est 2021-06-17 00:28:07 +08:00
我就用的 udp 打日志到 es 。
|
10
abersheeran 2021-06-17 00:44:28 +08:00 via Android
我一般多线程+队列进行异步落盘。因为一般不用分析、追溯日志。
如果有单独的日志存放服务,比如楼上说的 es,那么就走 Unix Socket 、UDP 、TCP 之类的。 |
11
3dwelcome 2021-06-17 03:43:58 +08:00
"我们都知道 python 的 IO 流,例如常见的 print,是一个同步阻塞操作。"
先写在大片纯内存里,满了再刷到磁盘上。 过程就只是一个拷贝内存的开销,理论上能做到很快吧。 |
12
LeeReamond OP @3dwelcome 没有这么单纯,物理上落盘虽然只有一次,但是你还是要先写回内核里,这个过程是同步阻塞的
|
13
neoblackcap 2021-06-17 04:53:39 +08:00
日志是走网络用 UDP 发到别的机器不就可以解决这些性能问题么?你的网络 IO 是同步非堵塞,性能只取决于你的发送。
|
14
xuanbg 2021-06-17 06:57:52 +08:00
@ikas 我们一般情况下不允许打日志。因为所有异常都统一捕获并输出日志了,网关也输出了接口调用参数、响应时间和返回数据的日志,业务里面也就不需要打日志了。偶尔遇到莫名其妙的问题,也是临时加点日志看一下帮助定位问题,用过后也是要删除才能上线的。
|
15
zjqzxc 2021-06-17 08:05:23 +08:00
python 的 logging 模块提供了多种 handler,看起来 DatagramHandler ( UDP 发送日志),MemoryHandler,QueueHandler 这几个也许能好点,可以试试看?
|
16
codehz 2021-06-17 08:18:07 +08:00 via Android
@LeeReamond 首先可以开线程写,即使 py,做系统调用的时候也会释放 gil 不会阻塞别的线程
其次,这不是还有 io-uring 异步读写方法吗( |
17
myCupOfTea 2021-06-17 08:52:05 +08:00
确实影响效率.10%-20%左右
|
18
ScepterZ 2021-06-17 10:14:19 +08:00 2
测 echo 性能没有意义,得看你的业务运行要多久,比如直接 echo 0.01ms,log 0.1ms ,但是业务要 10ms,对于业务就没影响,但是你测 echo 性能就下降了 90%
|
19
LeeReamond OP @ScepterZ 意义党可以退散了,我的绝大多数业务离框架瓶颈都很远,按照你的理论可以说大部分性能测试都没意义。我只是发个帖问问有没有人清楚 common practice
|
20
rockyliang 2021-06-17 11:18:56 +08:00 via iPhone
@xuanbg 网关把接口参数和返回数据都记录下来,请求量大的话,日志文件体积岂不是巨大?
|
21
statement 2021-06-17 11:45:44 +08:00
日志等级可以用开关控制。完全可以关掉大多数日志。 需要的时候再打开必要的日志等级
|
22
ScepterZ 2021-06-17 11:56:12 +08:00
@LeeReamond 你是看不懂“测 echo 性能没有意义”么,测性能当然有意义,但是用 echo 测试说这个对性能影响很大是不准确的
|
23
Digitalzz 2021-06-17 11:57:42 +08:00
python 不太清除,Java 可以参考一下,java 中使用 log4j2 等日志框架,在打印的位置信息的时候会进行加锁操作,导致大量线程处于 block 状态,可以导致性能下降 50%甚至 100%,解决办法就是不打印位置信息,按需自己编写代码时可以手动添加。就 IO 流的问题我个人感觉影响不大,可以使用日志框架的一些缓存打印,问题是可能会出现日志丢失
|
24
ospider 2021-06-17 15:59:28 +08:00
首先,正经代码没人用 print 写日志的。。
|
25
LeeReamond OP @ScepterZ 你是看不懂我想问实现,而所谓性能下降比率是完全是无关紧要的事么? block 了
|
26
LeeReamond OP @Digitalzz 丢失问题具体怎么解决呢,按目前的回复,工业级应该就是靠消息队列解决,确实有可靠性的问题,比如一些涉及到金钱往来的业务如果出现纠纷且恰好日志丢失了某行,岂不是很蛋疼?
|
27
myCupOfTea 2021-06-18 10:11:16 +08:00
命令行不打印,或者减少打印(并且换 loguru 拦截打印),发送数据到 logstash 想办法异步发送丢 ensure_future 里执行
|