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

2013-08-22 03:00:37 +08:00
 Livid
或许这些你都已经经历过了,那么你就把下面的列表当作是小朋友的学习心得吧。

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 在最近这段时间给予的帮助。
15269 次点击
所在节点    Python
67 条回复
Numbcoder
2013-08-22 09:57:36 +08:00
@Livid Tornado 异步非阻塞的。或许是你用的 ORM 库的同步阻塞的,这样的话,你的性能瓶颈肯定是在读写数据 I/O 这一块。
个人认为如果要用异步非阻塞的模型,那么最好所有的 I/O 库都用非阻塞的,这样才能把性能发挥到极致。
ps: 我不太懂 python,只是凭个人经验说的。
est
2013-08-22 10:04:25 +08:00
@whtsky Mysql性能不好主要是

1. 没有connection pool
2. 没有prepared statement
xing393939
2013-08-22 10:06:05 +08:00
菜鸟问下:对方是穷攻击,对策不是应该放在“堵”上吗,难道要靠提升性能来硬抗?
xing393939
2013-08-22 10:07:05 +08:00
打错字,硬扛,不是硬抗
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
2013-08-22 10:24:02 +08:00
@Livid 不过Redis、MONGODB吃内存吃的比较狠,我个人暂时还是比较推荐局部memcached
ipconfiger
2013-08-22 10:25:38 +08:00
@Numbcoder 很多时候并非跑得快就是好,死快死快,死得也快。postgresql的稳定性是杠杠的。

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

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

有个解决的办法就是,通过redis把请求异步到后端的队列里处理,完成渲染页面或者生成json后再输出,这样数据库的压力是平滑的,即使遇到个别慢查询也不会影响其他访问
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
2013-08-22 10:39:36 +08:00
楼主试一下使用安全宝, 然后换一个ip?
Keyes
2013-08-22 10:44:48 +08:00
我的框架里,所有查询的东西全自己native sql+memcached,写入操作全部丢入rabbitmq,后台使用基于sqlalchemy的“写入层”一个一个去处理写操作,在写入时移除会影响到结果的缓存
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
2013-08-22 10:57:36 +08:00
@Livid 10ms以下,难度不是一般的高,表示怀疑
davepkxxx
2013-08-22 11:02:04 +08:00
100ms的确太慢了,有使用数据库连接池么?数据库引擎用的哪个?如果放弃MySQL你准备用什么?Postgres?
jjx
2013-08-22 11:02:32 +08:00
用tornado ,我觉的大型的就应该是这种模式

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

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

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

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

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

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

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

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

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

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

这个帖子受教了。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/79819

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX