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
Livid
V2EX  ›  Python

最近的攻击让我想到的一些事情

  •  
  •   Livid · 2013-08-22 03:00:37 +08:00 · 15434 次点击
    这是一个创建于 4104 天前的主题,其中的信息可能已经有所发展或是发生改变。
    或许这些你都已经经历过了,那么你就把下面的列表当作是小朋友的学习心得吧。

    1. 下一个项目,能不用 MySQL 就尽量不用,尤其不要用任何的 ORM。虽然方便,但是性能损耗太大了。

    2. 所有页面的生成时间,目标应该是 10ms 以下。如果缓存设计得足够好的话,5ms 以下。目前我们的很多页面的生成时间接近甚至超过 100ms,这样的话,网站太脆弱了,会需要加入太多其他的应用层的防御措施。

    3. Tornado 是一个经得住考验的框架。本身性能非常好。

    4. 如果在 supervisor 中同时启动太多 Tornado process,那么在每次代码更改的时候,新代码的部署过程可能会造成短暂的 CPU 压力。

    5. 根据频次计算的防攻击规则,可能会和 CDN 及某些终端加速机制(比如 Opera Mini 的代理)不兼容,除非你能够把这些根据频次计算的防攻击规则,也部署到 CDN 的边缘节点上,并且有足够灵活的 UI 和部署机制让你能够试验不同的规则。

    6. 所有的防攻击规则都会造成误伤,并且可能会影响搜索引擎的收录,因为各种 bot 很容易中枪。

    如果你最近的访问因为我们的某些防攻击规则受到影响,请给我邮件 livid at v2ex.com 并附上你的 IP(前三段即可)。

    大力感谢 @ptcracker 在最近这段时间给予的帮助。
    67 条回复    1970-01-01 08:00:00 +08:00
    msg7086
        1
    msg7086  
       2013-08-22 04:42:25 +08:00
    菊部缓存技术呢?帖子内容之类的可以很轻松的缓存起来减少压力吧
    Sokos
        2
    Sokos  
       2013-08-22 05:02:42 +08:00
    1、“能不用 MySQL 就尽量不用”,为啥,同步阻塞?
    2、如一楼所说,局部缓存可以解决?
    3、V2EX是否遇到后端服务运行缓慢导致Tornado阻塞问题,是如何解决的?是否如 https://www.v2ex.com/t/46600 所说用HAProxy ?
    virushuo
        3
    virushuo  
       2013-08-22 05:23:35 +08:00
    说到1,记得上次咱们在浦东嘉里聊天讨论的那个话题?就是这个了。
    hitigon
        4
    hitigon  
       2013-08-22 06:41:39 +08:00
    关于1,能不能简单解释一下
    javaluo
        5
    javaluo  
       2013-08-22 07:17:29 +08:00 via Android
    对于v2ex可以做冷热分离,比如20页以后的帖子几乎无人再回复,那么就做成静态文件好了,下次直接读取(不知道是不是已经在实现了),如果有人继续回复,则穿透缓存直接更新,然后再次缓存下来
    GTim
        6
    GTim  
       2013-08-22 08:12:39 +08:00   ❤️ 1
    @javaluo 做静态文件是虚耗硬盘资源...这个可以直接查库..挖坟是可耻的要怎么保障??
    @Livid 很多同感

    orm开发时的确比写sql语句舒服多了,但要求高性能和多表关联查询时,性能代价还是太高...看起来微不足道的3-10ms多余损耗,有时,看起来就是不爽,另外,ORM想要改变一些东西,很复杂很厌烦,然后,就没有然后了

    mysql 只能说能不用就不用,看到多次往返io开销和多表关联查询,有时候不爽,但是没办法,嗨,mysql的并发限制,也是一大小伤

    攻击方面,感触最深的还是木桶原理..有些高手就专门挑耗时的给你来几下,完蛋了...

    缓存方面,NND的是很多人把数据扔上去了事,也不看是啥数据,更新频率和更新策略...最大的悲剧就是从来没想过要优化。redis虽然大于 memcached太多..但memcached也是有好处的..就是简单,单一,没有那么多数据结构

    总的来说:如果不考虑性能,想咋整就咋整吧...反正高手的最大骄傲就是:步步精修
    est
        7
    est  
       2013-08-22 08:17:19 +08:00
    1. 我没记错的话,我觉得这个可能是 @livid 一开始选择 storm 这个ORM有问题。这玩意慢不说,到处都是坑
    Livid
        8
    Livid  
    MOD
    OP
       2013-08-22 08:26:40 +08:00
    @est 去年四月时,和 @Kai 的目标是,我们需要在不到一个月的时间内,把网站从 GAE 上移植出来。在 GAE 上每多停留一周,就是额外的 $$$。

    所以当时在技术选型时,需要找的是在用法上尽可能接近 GAE 的技术。Storm 和 datastore 非常像。

    现在想想,还真是怀念那一个月啊。
    jjx
        9
    jjx  
       2013-08-22 08:29:23 +08:00
    sqlalchemy 需要性能和复杂查询的地方用sql expression, 其它用sqlalchemy orm。 我觉的是不错的选择
    arzusyume
        10
    arzusyume  
       2013-08-22 09:14:14 +08:00
    貌似这边把Google+的插入链接提取描述内容的功能误伤了
    Numbcoder
        11
    Numbcoder  
       2013-08-22 09:15:36 +08:00   ❤️ 1
    @virushuo
    @Livid
    能分享一下,如果不用 MySql 的话,用什么比较好呢?
    MongoDB ? 我感觉这个更不靠谱啊?
    Livid
        12
    Livid  
    MOD
    OP
       2013-08-22 09:17:02 +08:00
    @Numbcoder 可能会完全只用 Redis。
    buru
        13
    buru  
       2013-08-22 09:17:33 +08:00
    缓存设计可以参考一下reddit,everything get and update in cache.
    ipconfiger
        14
    ipconfiger  
       2013-08-22 09:18:58 +08:00
    @Numbcoder postgresql相当靠谱
    Mutoo
        15
    Mutoo  
       2013-08-22 09:28:45 +08:00
    @Livid 用 Redis 的话,有什么比较好的持久化方案?
    solo7net
        16
    solo7net  
       2013-08-22 09:31:17 +08:00
    我家里的IP好像被干掉了-0-
    lambdaq
        17
    lambdaq  
       2013-08-22 09:34:18 +08:00
    @Livid 这个算poor choice。

    你没遇到过撑爆内存那种无奈感。persistence和recover一直是redis很大的问题。大型系统AOF一旦损坏就等着哭。

    redis 只能作为简单 k-v 数据库,遇到 bbs/forum这种需要通过index去scan的东西,redis立刻跪。

    48G redis服管理员路过~~~
    whtsky
        18
    whtsky  
       2013-08-22 09:45:10 +08:00 via iPhone
    纯 Redis 当论坛数据库的话内存压力非常大吧
    Python 社区貌似没有性能比较好的 MySQL 库,开发的时候还是选 PostgreSQL 比较好一点
    bobopu
        19
    bobopu  
       2013-08-22 09:46:55 +08:00
    看了一下,还是incapsula的299刀套餐靠谱啊,每月300G+的抗d流量。。
    Numbcoder
        20
    Numbcoder  
       2013-08-22 09:47:53 +08:00
    @Mutoo 可以试试 levelDB
    @ipconfiger pg 性能不一定比 mysql 好把?
    Numbcoder
        21
    Numbcoder  
       2013-08-22 09:57:36 +08:00
    @Livid Tornado 异步非阻塞的。或许是你用的 ORM 库的同步阻塞的,这样的话,你的性能瓶颈肯定是在读写数据 I/O 这一块。
    个人认为如果要用异步非阻塞的模型,那么最好所有的 I/O 库都用非阻塞的,这样才能把性能发挥到极致。
    ps: 我不太懂 python,只是凭个人经验说的。
    est
        22
    est  
       2013-08-22 10:04:25 +08:00
    @whtsky Mysql性能不好主要是

    1. 没有connection pool
    2. 没有prepared statement
    xing393939
        23
    xing393939  
       2013-08-22 10:06:05 +08:00
    菜鸟问下:对方是穷攻击,对策不是应该放在“堵”上吗,难道要靠提升性能来硬抗?
    xing393939
        24
    xing393939  
       2013-08-22 10:07:05 +08:00
    打错字,硬扛,不是硬抗
    est
        25
    est  
       2013-08-22 10:10:33 +08:00
    为了避免误会,我上边所说的是python的mysql 库一些常见问题。比如django自带的mysql backend的问题。


    我也觉得leveldb比redis可能更加适合作为mysql的替代。不过需要外边去包装一个网络层,比如国人开发的ssdb之类的。或者用ejdb,轻量级的mongodb。

    其实mysql 也可以当k-v store或者nosql用。参考handlersocket
    Keyes
        26
    Keyes  
       2013-08-22 10:24:02 +08:00
    @Livid 不过Redis、MONGODB吃内存吃的比较狠,我个人暂时还是比较推荐局部memcached
    ipconfiger
        27
    ipconfiger  
       2013-08-22 10:25:38 +08:00
    @Numbcoder 很多时候并非跑得快就是好,死快死快,死得也快。postgresql的稳定性是杠杠的。

    @est leveldb我用过超过大半年了,业务场景也很简单,就是短链接生成,老实说,量大了也不行。

    tornado没有解决db同步的问题,所以在耗时访问多的时候被堵在数据库IO上,再快也是百搭。

    有个解决的办法就是,通过redis把请求异步到后端的队列里处理,完成渲染页面或者生成json后再输出,这样数据库的压力是平滑的,即使遇到个别慢查询也不会影响其他访问
    dreampuf
        28
    dreampuf  
       2013-08-22 10:35:49 +08:00
    仔细点用ORM
    session.Query(User).BlahBlahBlah.all() 这样的查询,改成 session.Query(User.id, User.name).BlahBlahBlah.all()

    10ms 内只能靠缓存

    Redis 作为缓存解决DB问题也会代入其他问题,同步,导入,开发时效率

    尝试Varnish?缓存分层,除了Entity,页面,页面元素都可以缓存住
    sdjl
        29
    sdjl  
       2013-08-22 10:39:36 +08:00
    楼主试一下使用安全宝, 然后换一个ip?
    Keyes
        30
    Keyes  
       2013-08-22 10:44:48 +08:00   ❤️ 1
    我的框架里,所有查询的东西全自己native sql+memcached,写入操作全部丢入rabbitmq,后台使用基于sqlalchemy的“写入层”一个一个去处理写操作,在写入时移除会影响到结果的缓存
    est
        31
    est  
       2013-08-22 10:50:00 +08:00
    @ipconfiger

    1. leveldb这么不堪么。。汗。。。qps有多少?
    2. 还有这一出啊。是不是说db的socket卡主,整个tornado实例就卡主了?tornado不能把mysql的socket做到ioloop里边去么?
    3. redis这里是用pub/sub么?感觉效率也不行啊。为啥用redis分发一下db压力就平滑了?

    我猜想 @livid 遇到的问题应该是慢查询导致mysql 连接池撑爆。然后其他db查询就blocking 30秒自动超时了。
    pubby
        32
    pubby  
       2013-08-22 10:57:36 +08:00
    @Livid 10ms以下,难度不是一般的高,表示怀疑
    davepkxxx
        33
    davepkxxx  
       2013-08-22 11:02:04 +08:00
    100ms的确太慢了,有使用数据库连接池么?数据库引擎用的哪个?如果放弃MySQL你准备用什么?Postgres?
    jjx
        34
    jjx  
       2013-08-22 11:02:32 +08:00
    用tornado ,我觉的大型的就应该是这种模式

    tornado <- > proxy <-> 可扩展多个工作进程, 典型的就是
    tornado <-> zmq request <- > zmq router/dealar <-> zmq response worker *

    不过 我现在嫌弃这个部署麻烦 ,还是 gevent干净,但如果 要分布式扩展,还是要回到上面的模式
    siw
        35
    siw  
       2013-08-22 11:07:40 +08:00
    @Keyes
    ++1

    把缓存做好吧
    est
        36
    est  
       2013-08-22 11:15:27 +08:00
    @jjx 其实可以考虑用uWSGI。支持fastrouter。可以动态增删worker。基本就是干你的zmp的活。

    如果一个worker超时了,可以自动回收。不用人工干预。

    也原生支持gevent核心。
    msg7086
        37
    msg7086  
       2013-08-22 11:25:36 +08:00
    如果这东西我来设计的话,大致是这样:

    帖子数据可以整块html缓存,热点放memcache,非热点的持久在硬盘上,反正不更改就不会过期也没什么不好。「5分钟前」这种html tag改用js实现也可以,正则滤一下改掉也可以。对帖子的任何操作,包括回复或者感谢什么的都会触发缓存刷新。隐藏功能就给正则或者xpath滤掉吧。

    帖子列表嘛,有回复或者发新贴的时候重建缓存就行了,在缓存上分页。

    节点框架嘛,整个框架缓存起来好了,长期有效。

    这样的话还有啥地方是短板 ·_·
    ipconfiger
        38
    ipconfiger  
       2013-08-22 11:29:08 +08:00
    @est 这里是典型的生产消费模式,不用pubsub都可以,直接blpop就可以了。而且访问redis都可以是异步的。具体的方式是比如16个tornado进程负责接收请求发送输出内容,然后启动N个工作进程来处理业务逻辑和渲染页面输出json什么的,blpop到一个队列,tornado进程rpush到这个队列,然后工作进程就去处理业务逻辑就行了,有些慢查询难优化的可以放到独立的队列中去,这样mysql的负载是一个恒定的,连接数是恒定,前端的tornado完全异步化了,如果遇到个别耗时很长的操作也不会堵塞其他请求。

    当然缓存啊数据库优化啊什么的还是照做,这只是我觉得比较合理使用tornado的一个方式而已。
    pubby
        39
    pubby  
       2013-08-22 11:51:51 +08:00
    @ipconfiger 这么一套下来,啥事不干10ms就过去了吧
    saharabear
        40
    saharabear  
       2013-08-22 12:11:15 +08:00
    真心受教了,以心醉状态看这个帖子,我把帖子复制到知识库存着。 ORM我的做法大多是直接查询用ORM,保存之类的也用ORM,复杂查询从ORM中拿远始Connection再处理。

    这个帖子受教了。
    SamRaper
        41
    SamRaper  
       2013-08-22 12:17:48 +08:00
    @livid 可以考虑用 AJAX 了,可以减少不必要的开销
    ipconfiger
        42
    ipconfiger  
       2013-08-22 12:26:19 +08:00
    @pubby rpush是纳秒级别的操作,且,每个请求慢1ms,但是总体的处理能力上了一个数量级的台阶,还是划算的。你不能单独看一个请求的得失而忽略了总体的吞吐量
    lj0014
        43
    lj0014  
       2013-08-22 12:39:12 +08:00
    总得来说就是让应用本身可以扛更多量
    另外MySQL现在怎么这么不让人待见了。。
    ywencn
        44
    ywencn  
       2013-08-22 12:40:34 +08:00
    哪有靠提高性能来抗攻击的
    ipconfiger
        45
    ipconfiger  
       2013-08-22 12:43:51 +08:00
    @SamRaper 这个情况是上了ajax反而会增加更多的请求,雪上加霜,ajax并不能解决性能问题
    ptcracker
        46
    ptcracker  
       2013-08-22 12:48:23 +08:00
    如果时间允许,防攻击应该可以做到更好。
    Attacker 和 Defender 其实比的就是个 idea,是脑力的较量。
    ptcracker
        47
    ptcracker  
       2013-08-22 12:49:24 +08:00
    @ywencn 提高性能是减少被 DoS 可能的一个途径,严格意义上来说是“防攻击”的一种技巧,在一定程度上是会起到作用的。
    ipconfiger
        48
    ipconfiger  
       2013-08-22 12:50:30 +08:00
    @ywencn 主要是性能问题造成的可攻击的入口,比如找准一个慢查询,也就是LZ说的200ms那个,很轻松的就能让一个网站失去响应。
    nichan
        49
    nichan  
       2013-08-22 12:56:51 +08:00   ❤️ 1
    目测用户设置页面是那个慢查询?
    luikore
        50
    luikore  
       2013-08-22 13:18:07 +08:00
    @ipconfiger redis cache 住瓶颈就好了... 扔掉 ORM 200ms 最多也就变成 50ms 吧, 没有擦车的效果好.

    另外伪造瓶颈页面也是一种防御手段 -_-

    找到根源效果更治本, 例如发这个帖把攻击者钓出来...
    ipconfiger
        51
    ipconfiger  
       2013-08-22 14:12:38 +08:00
    @est gevent的数据库访问也还是阻塞的
    ipconfiger
        52
    ipconfiger  
       2013-08-22 14:13:43 +08:00
    @est 起码是对mysql的访问,要非阻塞就只能换纯python的mysql库了
    est
        53
    est  
       2013-08-22 14:17:41 +08:00
    @ipconfiger MySQLdb (mysql-python) 阻塞,用纯python实现的好一点。是什么原因没有选择后者呢?
    ipconfiger
        54
    ipconfiger  
       2013-08-22 14:20:58 +08:00   ❤️ 1
    @est 慢啊。总之gevent不是银弹。Node.js也不是,拿个异步回调的写个orm得有多纠结
    gamexg
        55
    gamexg  
       2013-08-22 14:42:29 +08:00
    这个靠谱吗?

    ORM对象缓存探讨
    http://robbinfan.com/blog/3/orm-cache
    phuslu
        56
    phuslu  
       2013-08-22 14:44:25 +08:00
    ipconfiger
        57
    ipconfiger  
       2013-08-22 14:45:56 +08:00
    @phuslu 有人在生产环境使用过么?
    phuslu
        58
    phuslu  
       2013-08-22 14:46:50 +08:00
    phuslu
        59
    phuslu  
       2013-08-22 14:47:45 +08:00
    @ipconfiger 而且至少 esn.me 在生产环境下用过啊。
    est
        60
    est  
       2013-08-22 14:50:53 +08:00
    @phuslu 我大概知道 @ipconfiger 想说啥了。如果db是瓶颈,每秒只能处理那么多请求,web逻辑再异步也没有用。无论是同步去连还是异步去连。

    猜想 @ipconfiger 用多进程跑tornado然后redis自己做调度就是为了避免一个mysql查询卡死整个tornado进程的情况。
    ipconfiger
        61
    ipconfiger  
       2013-08-22 14:52:47 +08:00
    @est 对的

    @phuslu 如此甚好,我把以前一个用gevent的东西换换mysql连接库就能提高性能了,tks
    est
        62
    est  
       2013-08-22 14:59:07 +08:00
    @ipconfiger 哈哈, 豆瓣也撸的是这个 https://github.com/esnme/ultramysql/issues/10 最后回复

    ultramysql 的问题是。不兼容 db api。导致很多东西很蛋痛
    ipconfiger
        63
    ipconfiger  
       2013-08-22 15:04:05 +08:00
    @est 妈蛋啊,幸亏我反射弧比较长
    notedit
        64
    notedit  
       2013-08-22 15:55:51 +08:00
    有些问题是你使用上的问题

    比如storm本身就有问题,已经有多个人吐槽过了,甚至不支持连接池. 作者跑去搞go了.
    python上用的最多的那个mysql驱动不是异步的 跟tornado配合的话 异步就没有优势了.

    可以尝试下postgres
    hunk
        65
    hunk  
       2013-08-22 23:28:44 +08:00
    基础数据还是用mysql靠谱,以保存为主,前端KV数据库是没有疑问的。
    fire5
        66
    fire5  
       2014-03-24 17:50:11 +08:00
    我直接使用tornadb,裸写sql倒是犀利,但是CURD费体力,我就写了一个根据course分析表结构,自动生成curd代码的工具。 总体来说,一般场景我还是支持orm的,毕竟一堆的sql string 维护也很蛋疼的。重构下表结构,需要修改一堆sql。。。。
    fire5
        67
    fire5  
       2014-03-24 17:52:31 +08:00
    另外性能问题绝对不是MySQL本身的问题,比如淘宝95%都是mysql,分表,分库,主从,索引优化下,加上cache,一般论坛随便搞搞没啥问题的。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2780 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 12:41 · PVG 20:41 · LAX 04:41 · JFK 07:41
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.