http://segmentfault.com/a/1190000000304859

每个萝卜下都隐藏一个坑。

前段时间955短网址日重定向次数最高达400万,主要开销是重定向请求的用户数据储存与分析。分别经历了内存瓶颈、IO 瓶颈后,高峰期达到 CPU 上限,几乎榨干了机器,下文是经验总结分享。

前置条件

由于短网址很难盈利,硬件特别寒碜,带着镣铐跳舞反而别有风味,当然,人力投入,技术方面也不能和其他大网站比,所以如果要拍砖请轻下手——哎哟。

我们采用的硬件:盛大云微型,1G内存,单核共享型 CPU。后期追加了一个同等配置的内网机器做 MongoDB replSet。

Startup 硬件成本:

既然项目本身基本没法带来收益,要生存就只能充分压榨硬件,大胆使用新技术。根据国内云的计费方式,一般收费的维度是

  • 内存:使用异步模式代替同步多进程。
  • 带宽:2M双线,301并不需要太多的带宽开销
  • 硬盘:云硬盘,按容量收费
  • CPU:单核

由此我们做了对应的技术选型:

  • Nginx:无需多说了吧?
  • Tornado:Facebook 开源的 python 异步微框架
  • MongoDB:性能好,热数据少内存开销也少
  • Redis:事实上 MongoDB 写入的 IO 开销太大
  • nodejs(with coffeescript):后期新增,node.js 是天生的异步
  • supervisord:监控进程

来照张相——咔嚓

开发与运维

既然目前项目投入的开发和运维都只有我一个人,那就可以美其名曰:DevOps 啦。听上去是不是很高端大气国际化。

用户特点

二八法则基本适用:20% 的 URL 占用了 80% 的资源(尤其是我们默认为所有短网址开启了统计之后)。

监控先行

很多小团队犯的第一个毛病就是不做监控,等到用户来告诉你网站无法打开的时候就太晚了。为了省事我们用了监控宝和阿里云监控(主要阿里云监控有免费短信)。

每次出现无法打开网站的状态时,都应该定位此次问题的原因。如果频次增加,就要考虑应对策略了。loadavg 很好地反应了系统的负载,可以判断是否硬件出现瓶颈。

如果是在事发时间,我们可以借助这些工具查看系统状态:htop(定位哪个进程的问题)、iftop(是否有异常的流量和ip)、iotop(定位 io 瓶颈)。此外就是看日志。

如果事发时在睡觉,那么就看监控历史记录。

惨痛教训一:硬盘容量——为将来留下后路

MongoDB在硬盘容量不够的时候会拒绝启动。而如果之前没有使用 lvm 这类工具,将无法快速扩展容量,而国内的云不像 Linode 那么智能地在后台提供容量的一键 resize(虽然这个功能曾把文件系统搞出错了)。后果很可能是停机几个小时。

惨痛教训二:最大打开文件描述符

异步模式下不可避免遇到新问题——最大打开文件描述符。我们先后遇上了 tornado 和 nginx 的最大打开文件描述符问题。 tornado 的表现为:CPU 100%,日志里出现500;Nginx 则在日志里报错,打开缓慢。

要避免此类问题,要做相应 ulimit 的设置。

ulimit -n显示的只是当前会话的(!important)。正确做法是查看进程的 limits: cat /proc/{$pid}/limits

Nginx 的配置文件里还需要设置两个参数:

worker_connections  9999; #根据自己的情况设置
worker_rlimit_nofile 60000; #根据自己的情况设置

下图是 nginx 达到上限的监控图,很明显被卡在1000左右了 —— Linux 默认限制为 1024。

惨痛教训三:Python 不是天生异步的语言

说实话,用 Python 来设计的过程可不是一个愉快的过程。为了避免潜在编码问题,我们使用了 python3。下面的问题是:

缺乏异步的支持:

  • Redis 异步驱动只支持 Python2(当然,等了大约半年后 tornado-redis 的作者终于更新了对 python3 的支持)。
  • 不少组件仍然无法支持 python3, pip install 后直接报错的感觉就是:傻眼了。
  • Bitly 的 asyncmongo 简直是没有文档,最后只能选了 Motor。
  • Tornado 本身的文档也不够详尽

后来一部分组件使用 nodejs 开发后,简直是相见恨晚,CoffeeScript 语法糖的表现也很出色。

惨痛教训四:谨慎选用数据库

数据库几乎是web应用里最关键的一部分,越是有大局观的技术人员越会谨慎选型。事实上我们把所有压力都放 MongoDB 的做法还是过于激进了。

MongoDB 的范式化与反范式化。

几乎所有对 MongoDB一知半解的人都会告诉你不要用 SQL 的思维来思考 MongoDB,要使用内嵌文档来实现需求。但是他们忘记告诉你,不断增长的内嵌文档将导致 IO 瓶颈(参考《深入学习 MongoDB》73页)。

事实上范式化和反范式化(内嵌文档)还有很多要考虑的因素。

复杂查询时 MongoDB 的无力

在面对需要计算的查询时,MongoDB 的 map-reduce 很慢;复杂情况下对内嵌文档处理有难度;Documents 比 MySQL 更少。年轻人,不要在 mysql 遇到问题时第一时间想到替换数据库。

就这个项目而言,统计部分要快速出多样报表时明显有难度。

不要等到着火了才想起 MongoDB replSet

  1. 如果 MongoDB 写入压力大,并且没有做分片,那么单纯加机器不会缓解写入压力。如果是读取压力倒有所帮助。
  2. 从单机到 replSet 起码需要锁住数据库。程序代码也需要修改。打算切换到 replSet 的话,需要提前做准备。
  3. 最后我们的做法是将频繁更新的数据放 redis,定时刷入数据库,效果很明显。

正确使用 Redis

控制内存,控制起步成本

如果你打算省钱的,就不要把所有东西都放 Redis 里,哪怕看上去数据量不大——时间久了也占了不少内存。而在 MongoDB 里只有热数据占内存。 二八法则也适用这种情况:热数据只占20%。

当然如果你是土豪请你走开!

不要用 pub/sub 做队列

如果不想丢失数据就不要用 pub/sub 做队列。进程重启时将丢失订阅管道的信息。你可以用 lpush 和 brpop 来实现队列。

受够盛大云了

  • 内网主机完全不能访问外网。你想 apt-get update 下?临时买带宽吧。
  • 被 DDOS 攻击?直接断网,没有任何通知,你还百思不得其解。
  • io性能太差,读写大约 5-6M/s 的时候就要挂了。当然阿里云的好像更差。

最后的忠告

「年轻人啊,要多读书多看报,多思考多学习」——万峰

看到这里肯定有不少人想喷我了,来吧,我的微博是: @dai-jie ,有错我改,我改……

一个萝卜一个坑:短网址开发运维经验总结分享相关推荐

  1. Linux学习总结(77)—— Shell 开发运维经验总结

    前言 无论是系统运维,还是应用运维,均可分为"纯手工"-> "脚本化"-> "自动化"->"智能化"几 ...

  2. 为什么数据科学家需要承担开发运维的工作?

    作者 | Caleb Kaiser 译者 | 弯月,责编 | 夕颜 头图 | CSDN下载自视觉中国 出品 | CSDN(ID:CSDNnews) 以下为译文: 如果你需要创建一个生产环境下的机器学习 ...

  3. DevOps 开发运维一体化~EXIN

    当我们谈到DevOps时,可能讨论的是:流程和管理,运维和自动化,架构和服务,以及文化和组织等等概念.那么,到底什么是'DevOps'呢? 随着软件发布迭代的频率越来越高,传统的「瀑布型」(开发一 测 ...

  4. devops开发运维训练营_嗨,网络开发人员训练营的毕业生:这是您第一份工作需要了解的内容。...

    devops开发运维训练营 by Rachel Bird 雷切尔·伯德(Rachel Bird) 嗨,网络开发人员训练营的毕业生:这是您第一份工作需要了解的内容. (Hey web dev bootc ...

  5. php 运维系统开发,PHP开发运维管理系统笔记

    开发运维管理系统采用ThinkPHP框架+mysql进行开发.框架配置return array( //'配置项'=>'配置值' 'SHOW_PAGE_TRACE' => true, //允 ...

  6. 开发运维效率提升 80%,计算成本下降 50%,分众传媒的 Serverless 实践

    作者:吴松 本文总结于分众传媒研发总监吴松在阿里云云原生实战峰会上的分享,从三个方面讲述了对 Serverless 技术的探索. 分众传媒的业务现状 分众传媒的业务场景很简单,就是广告主买量,然后进行 ...

  7. Redis开发运维实践问题处理只内存检查

    8.3.1 系统内存查看 script/下的memstat.sh或者ps_mem.py都可以查看系统的内存情况,两个工具都需要root权限. 8.3.2 系统swap内存查看 #!/bin/bash ...

  8. visual studio 设计器不显示_面向国际市场的装置开发运维软件设计与实现

    南京南瑞继保电气有限公司的研究人员陈宏君.张磊.徐睿.曾凯.刘坤,在2019年第3期<电气技术>上撰文,分析了面向国际市场的用户软件现状与问题,介绍了新一代控制保护平台PCS-S系列装置配 ...

  9. 什么是devops开发运维_为什么假设驱动的开发是DevOps的关键

    什么是devops开发运维 DevOps的定义,由Donovan Brown提供 是" 人员 , 流程和产品的结合,以实现向客户不断交付价值 . "它强调了持续交付价值的重要性. ...

最新文章

  1. 测试驱动开发 测试前移_测试驱动的开发可能看起来是工作的两倍-但无论如何您都应该这样做...
  2. 如何做一次有效的绩效考核面谈?
  3. 数据备份_「Cassandra实战」Cassandra数据备份
  4. idea本地跑如何看gc日志_不可思议,竟然还有人不会查看GC垃圾回收日志?
  5. (转)Windows重启延迟删除,重命名技术原理
  6. python输入ip地址_python批量生成本地ip地址的方法
  7. 微信小程序把玩(十八)picker组件
  8. typec扩展坞hdmi没反应_typec扩展坞转hdmi/vga多功能网口usb转换器苹果华为电脑matebook6元优惠券券后价26.8元...
  9. 《linux操作系统》第06章在线测试,Linux系统管理一测试题-附答案.doc
  10. python tkinter画笑脸_tkinter绘制红绿灯图案
  11. 《人件》(Peopleware)文摘
  12. 基于51单片机的GPS公交自动报站系统
  13. vue导入pdf插件报错
  14. 电脑硬盘分区太多?如何合并分区?
  15. 计算机取代人脑的英语作文,关于电脑和人脑差别的英语作文
  16. 3、太阳能电池板参数解析
  17. NetInside网络攻击分析帮您轻松发现可疑主机
  18. LeetCode买卖股票的最佳时机系列总结
  19. Hadoop安装搭建伪分布式教程(全面)吐血整理
  20. 放假期间网站被挂马的解决办法

热门文章

  1. IOS开发callkit(call directory extension)勘误
  2. java swing GUI 模拟写字板项目源码,适合初级小白
  3. java *** 制作圣诞贺卡
  4. 【系统收藏】黑白美女xp主题
  5. 程序媛在互联网公司会遭遇哪些性别歧视?
  6. 运动会分数统计系统c语言,运动会分数统计系统
  7. 新的RA Group勒索软件针对美国组织进行双重勒索攻击
  8. 服务器回收站误删的文件怎么恢复,回收站删除的文件怎么恢复
  9. 大数据教程【05.01】--Python 数据分析简介
  10. Springboot毕设项目药库药品智能入库出库及流转管理系统e46hijava+VUE+Mybatis+Maven+Mysql+sprnig)