V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
LeeReamond
V2EX  ›  Python

有关日志功能是否严重影响 web 框架效率?

  •  
  •   LeeReamond · 2021-06-16 23:13:31 +08:00 · 4116 次点击
    这是一个创建于 1037 天前的主题,其中的信息可能已经有所发展或是发生改变。

    发主题的时候主要想法是局限在 python 的异步框架,不过也很好奇其他语言的框架都用什么解决方案,所以标题里没有写明是 python 。

    问题简单来说,我们都知道 python 的 IO 流,例如常见的 print,是一个同步阻塞操作。而目前网络端的解决方案在向异步非阻塞转移,比如 fastapi/aiohttp 这类框架,转移的同时,日志又是很重要的一个功能,总不可能一个服务没有日志。这是否意味着框架转发性能将被严重降低,有什么解决方案吗?

    第 1 条附言  ·  2021-06-17 02:52:26 +08:00
    贴个条,确实有这个问题,fastapi 默认 logger 在 echo 测试中大概会让响应能力下降几十倍。我试了试把 logger 替换成 loguru,异步写入日志,理论上来说应该有产生日志-》异步写入文件描述符-》系统实际落盘,这几个过程,echo 性能大概也不超过 5000,总的来说还是慢了不少。
    27 条回复    2021-06-18 10:11:16 +08:00
    lishunan246
        1
    lishunan246  
       2021-06-16 23:23:54 +08:00 via Android
    日志可以用 syslog 或者 http 方式输出给专门的 agent 收集。
    特别在意性能可以考虑换其他语言实现。
    catcn
        2
    catcn  
       2021-06-16 23:25:46 +08:00
    放内存,慢慢落磁盘,落得慢直接扔掉
    binux
        3
    binux  
       2021-06-16 23:28:22 +08:00 via Android
    我们都知道 python 的 IO 流,例如常见的 print,是一个同步阻塞操作

    不一定,看往哪写
    0x0208v0
        4
    0x0208v0  
       2021-06-16 23:39:02 +08:00
    同问
    LeeReamond
        5
    LeeReamond  
    OP
       2021-06-16 23:39:31 +08:00
    @lishunan246 不是很在意性能,业务不会在这里达到瓶颈,只是好奇通常是怎么处理的
    nightwitch
        6
    nightwitch  
       2021-06-16 23:42:06 +08:00
    单独起一个线程负责 IO,其他要写日志的往一个 queue 里写,这个线程从 queue 里拿到日志就往硬盘里写就好了。
    falcon05
        7
    falcon05  
       2021-06-16 23:42:36 +08:00 via iPhone   ❤️ 1
    openresty 就提供了非阻塞日志函数 ngx.log
    ikas
        8
    ikas  
       2021-06-17 00:19:43 +08:00   ❤️ 1
    参考 java 平台,先有 slf4j 通用日志接口,然后有各种不同日志框架实现.比如 log4j2,logback. 他们都支持配置 Appender,根据不同 Appender 你可以实现写入文件,db,console,或者其他服务.他们也都支持配置为异步,减少对业务影响,提高性能.
    同时,编写业务日志也要注意日志粒度,如果是 debug 日志也要先判断 debug level,减少日志拼接损耗
    est
        9
    est  
       2021-06-17 00:28:07 +08:00
    我就用的 udp 打日志到 es 。
    abersheeran
        10
    abersheeran  
       2021-06-17 00:44:28 +08:00 via Android
    我一般多线程+队列进行异步落盘。因为一般不用分析、追溯日志。

    如果有单独的日志存放服务,比如楼上说的 es,那么就走 Unix Socket 、UDP 、TCP 之类的。
    3dwelcome
        11
    3dwelcome  
       2021-06-17 03:43:58 +08:00
    "我们都知道 python 的 IO 流,例如常见的 print,是一个同步阻塞操作。"

    先写在大片纯内存里,满了再刷到磁盘上。

    过程就只是一个拷贝内存的开销,理论上能做到很快吧。
    LeeReamond
        12
    LeeReamond  
    OP
       2021-06-17 03:49:20 +08:00
    @3dwelcome 没有这么单纯,物理上落盘虽然只有一次,但是你还是要先写回内核里,这个过程是同步阻塞的
    neoblackcap
        13
    neoblackcap  
       2021-06-17 04:53:39 +08:00
    日志是走网络用 UDP 发到别的机器不就可以解决这些性能问题么?你的网络 IO 是同步非堵塞,性能只取决于你的发送。
    xuanbg
        14
    xuanbg  
       2021-06-17 06:57:52 +08:00
    @ikas 我们一般情况下不允许打日志。因为所有异常都统一捕获并输出日志了,网关也输出了接口调用参数、响应时间和返回数据的日志,业务里面也就不需要打日志了。偶尔遇到莫名其妙的问题,也是临时加点日志看一下帮助定位问题,用过后也是要删除才能上线的。
    zjqzxc
        15
    zjqzxc  
       2021-06-17 08:05:23 +08:00
    python 的 logging 模块提供了多种 handler,看起来 DatagramHandler ( UDP 发送日志),MemoryHandler,QueueHandler 这几个也许能好点,可以试试看?
    codehz
        16
    codehz  
       2021-06-17 08:18:07 +08:00 via Android
    @LeeReamond 首先可以开线程写,即使 py,做系统调用的时候也会释放 gil 不会阻塞别的线程
    其次,这不是还有 io-uring 异步读写方法吗(
    myCupOfTea
        17
    myCupOfTea  
       2021-06-17 08:52:05 +08:00
    确实影响效率.10%-20%左右
    ScepterZ
        18
    ScepterZ  
       2021-06-17 10:14:19 +08:00   ❤️ 2
    测 echo 性能没有意义,得看你的业务运行要多久,比如直接 echo 0.01ms,log 0.1ms ,但是业务要 10ms,对于业务就没影响,但是你测 echo 性能就下降了 90%
    LeeReamond
        19
    LeeReamond  
    OP
       2021-06-17 10:59:36 +08:00 via Android
    @ScepterZ 意义党可以退散了,我的绝大多数业务离框架瓶颈都很远,按照你的理论可以说大部分性能测试都没意义。我只是发个帖问问有没有人清楚 common practice
    rockyliang
        20
    rockyliang  
       2021-06-17 11:18:56 +08:00 via iPhone
    @xuanbg 网关把接口参数和返回数据都记录下来,请求量大的话,日志文件体积岂不是巨大?
    statement
        21
    statement  
       2021-06-17 11:45:44 +08:00
    日志等级可以用开关控制。完全可以关掉大多数日志。 需要的时候再打开必要的日志等级
    ScepterZ
        22
    ScepterZ  
       2021-06-17 11:56:12 +08:00
    @LeeReamond 你是看不懂“测 echo 性能没有意义”么,测性能当然有意义,但是用 echo 测试说这个对性能影响很大是不准确的
    Digitalzz
        23
    Digitalzz  
       2021-06-17 11:57:42 +08:00
    python 不太清除,Java 可以参考一下,java 中使用 log4j2 等日志框架,在打印的位置信息的时候会进行加锁操作,导致大量线程处于 block 状态,可以导致性能下降 50%甚至 100%,解决办法就是不打印位置信息,按需自己编写代码时可以手动添加。就 IO 流的问题我个人感觉影响不大,可以使用日志框架的一些缓存打印,问题是可能会出现日志丢失
    ospider
        24
    ospider  
       2021-06-17 15:59:28 +08:00
    首先,正经代码没人用 print 写日志的。。
    LeeReamond
        25
    LeeReamond  
    OP
       2021-06-17 22:47:30 +08:00
    @ScepterZ 你是看不懂我想问实现,而所谓性能下降比率是完全是无关紧要的事么? block 了
    LeeReamond
        26
    LeeReamond  
    OP
       2021-06-17 22:50:25 +08:00
    @Digitalzz 丢失问题具体怎么解决呢,按目前的回复,工业级应该就是靠消息队列解决,确实有可靠性的问题,比如一些涉及到金钱往来的业务如果出现纠纷且恰好日志丢失了某行,岂不是很蛋疼?
    myCupOfTea
        27
    myCupOfTea  
       2021-06-18 10:11:16 +08:00
    命令行不打印,或者减少打印(并且换 loguru 拦截打印),发送数据到 logstash 想办法异步发送丢 ensure_future 里执行
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   990 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 19:42 · PVG 03:42 · LAX 12:42 · JFK 15:42
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.