最新消息: 生命不止,奋斗不息……

互联网app长连接消息push系统的架构和坑

研发 admin 1498浏览 1评论

push

# 区分长连接,半长连接,短连接

1. app的话,可以很容易通过客户端支持的语言,例如java、flash,开一个scoket服务,connet之后就不close,这是长连接(依然特雷西:58同城的帮帮就是flash)

2. web的话,一般通过js来完成,但是ajax的话,没有办法hold一个连接不断,象apache 有keep alive选项,其实还是没有真正的长连接,所以通常意义来说来说,web端的叫半长连接,它可能需要客户端插件辅助,例如js + flash

3. 短连接的话,就是通过js的setTimeout,每隔一段时间去后台拉数据,缺点是当用户没有新的消息时,也会不断的浪费请求到后台。(目前微信公众平台是用这种,每隔10s拉一次)·

# 客户端的处理

1. js的setTimeout

2. js调用flash,java等封装好的接口

3. nodejs的websocket配合服务器端的nodejs

# 服务器端的处理

1. 服务器端主要是三个,一个是io处理层,另外一个是逻辑处理层,第三个是数据存储层

2. io处理层是重头,因为要hold住很多长连接

3. 主流方案

a. nginx(lighttpd)+module + c/c++ (百度贴吧在用,性能最好,开发调试最麻烦)

b. nginx+lua+redis (第二简单,利用nginx的高性能io和lua的快速开发,也很方便)

c. nodejs+redis (简单,nodejs提供一个web端用的js半长连接库(猜是socket.io))

d. golang+redis (数字公司在用,跟开发普通后端server一样,不过golang是协程机制,hold连接很简单,单机一般有100w,经过优化后连接能到200w)

4. 后端架构一般会包含,register_server, user-server, push-server, message-server, storage-server等几个部分

# 扩展阅读

Comet:基于 HTTP 长连接的“服务器推”技术

【06-12】网站如何防攻击和入侵,包括应用层和网络层

1. 应用层,最少保证程序安全,包括注入,xss,csrf。

2. 另外一个,在接入层,做好负载均衡,还有把业务性能提高

3. 有钱的上硬件防火墙,没钱的上软件防火墙

4. 网络层,简单点的前面接入一些攻击防止层。

5. 我写过一个脚本,判断多少请求后,加入黑名单,把ip

6. 应用层,常见的就是隔离吧,例如把数据库放到内网

7. 比如用redis做个计数器,用当前分钟和ip做key,不断自增,如果超过100,说明超出频率,直接禁止ip访问

8. 好一点的做个nginx扩展,用来洗流量

9. 如果是协议层的攻击,只能上防火墙,如果到了应用层,就能够做很多我们力所能及的事情

10. 是啊,应用层是我们熟悉的环境,在这一层做比较简单,但效率也会比较相应的变低.

11. 很多站点除了机器,还有带宽问题

12. hostdeny,我部署了这个,连接数多了就日他

13. ip限制会遇到公网ip误杀问题,可以结合其他身份特征做限制,比如uid 前提是账号安全

14. 我觉得小网站,用百度的加速乐,安全宝,或者360的网站宝之类比较省事。大网站就要自己做一些事情了

15. DDOS,强刷怎么破?答:fail2ban

16. 还有就是分析一下用户,判断如果不是正常用户的直接封,可以通过,浏览记录,和当前的数据

17. ddos 如果是协议层,上别人的接入层。比如百度的加速乐、安全宝、网站宝。

18. 如果是应用层攻击,自己分析访问日志,然后ban掉ip

19. Tcp 里有个cookie设置也可以,对于三次握手中断的攻击。(通过Tcp_syncookies防护)

20. 一般是通过系统漏洞入侵吧,目前我们这块都用防火墙关闭不用的端口,向外面暴露很少的端口.还有一种应该就是暴力破解居多吧

21. 应用层封ip容易误封,做到自动封与解封需要一定的工作量,人工参与量会比较大

22. 一般是按时间段来控制,封ip对付初级的比较管用,但是我也想不到更好的办法,这个可能就要用机器学习之类的来处理了

23. 前端用云waf挡住一些xss sql注入这样的攻击

24. 每次访问都记日志,定时检测一段时间的访问次数,过高,就加入503的名单,一段时间后,恢复

25. 按ip,假如1个IP一秒钟请求1000次,我们就认为是在攻击或是刷接口,直接拦截掉了

26. 如果一个公司的IP都是一样的,但是只有一个人攻击了你,你把整个IP都封了,是不是不太好

27. 其实我想要的是如果这个IP攻击我了,那么我只想屏蔽这个攻击者,同IP下的其他人不受影响

28. 普通网站根据cookeid。记录频率 加验证码请求验证

29. 对,IP+cookie是个好办法,仅有IP或cookie是不好的

30. 要遵从一个原则,一切的客户端行为都是不可靠的

【06-18】HTTP接口的设计,包括请求,响应,频率控制,容灾等

1. 对url和调用者的ip或者key来来记录次数 — 光光

2. 应该用redis做计数器的 — 如果当时

3. 一般用mc啥的,操作保证原子性 — 黑夜路人

4. 先要确定好接口规范,比如采用restful 然后再确定接口的目标用户是否需要验证后请求等,还可以设置白名单之类的,用户访问对url和ip或者key来唯一来记录调用次数和每个时间内规定的调用次 — 光光

5. 如果是幂等的接口,例如从数据库查询一条记录,无副作用,可以不用加锁, 如果不是幂等,如向数据库插入一条记录,就得考虑加锁,保证请求原子性 — twin

6. 加锁的方法比较简单, mc->add(‘key’, true, ‘最大请求时间或0′). 要加锁就得解锁,解锁其实很简单,不推荐在return之前写,因为一个action有很多return, 也不能在__descruct里面写,因为fatal error时不会调用__descruct,应该通过register_shutdown_function注册个回调解锁 — twin

7. 问: 给客户端app调用的接口如何设计以保证安全性?

答: 目前我用的是 aes 加解密,准备换成 oauth — 姚文强

8. 问: https的话会不会导致客户端请求与解析变慢?

答: 慢一倍 — hilojack

9. 如果是面向客户端的接口,可以加签名做验证,面向浏览器的,就只能用验证码了。 服务器间的接口调用通过ip限制最简单可行。面向客户端的可以用oauth,但是麻烦了点。频率控制的话很多都是ip,单ip下每秒钟请求次数限制 — 我是谁

10. 通过IP误伤率很大 — skccc

11. https://github.com/interagent/http-api-design 推荐这本书 heroku的api设计? 虽然我也还没看过 呵呵 — 24K纯金男屌

12. 安全验证我们可以认为有两种,一种是有状态,一种是无状态. 象签名验证,根据你请求数据验证是否合法,就是无状态,象Oauth2.0这种,每次都带着key过去确定身份,就是有状态. 无状态的好处在于客户端和服务器设计比较简单,不用记录用户状态,当然有伪造数据风险,有状态就麻烦了,两边都得考虑用户身份,验证过期等问题 — twin

13. 这里有大量restful接口设计的指导 http://www.vinaysahni.com/best-practices-for-a-pragmatic-restful-api — twin

14. 我先分享一点体会,我使用过的http接口方式,前后端之间、后端之间使用的是WebService,提供给JS、APP调用的是JSON,这些接口都是有状态的,使用session保存状态数据,不同服务器间使用单点. 登录验证,所有接口均需要支持返回未登录错误消息,由调用者保证负责与单点登录服务器通讯 — 水浸街

15. RESTful要求无状态、HTTP标准方法,我们只在不需要用户认证的服务上尝试使用了,由于要HTTP标准方法,GET的时候要把数据拼到url上,一长串路径很难看懂,数据较多时存在url超长的情况,还有开发人员把JSON数据编码到url上了,总的来说我感觉RESTful是看起来很美,实际使用挺难受的 — 水浸街

16. 有状态的接口要做频率控制很容易的,放在session中就可以了,但我们没有作控制,因为误伤是无法避免的,有些情况下确实就需要频繁调用,我们采用的是管控方案,在连接调用次数超常是发出告警信息,由维护人员手工处理 — 水浸街

17. 容灾应该是架构需要考虑的问题,我们的方案是,同一个系统的前端服务器都运行同样的服务,可简单通过增加服务器方式增加处理能力,集群之前架设F5负载均衡平均分配到前端服务器上,后端服务按用户群分服务器、数据库,用户路由数据保存在缓存服务器上,前端服务器根据查询的用户路由数据访问相应的后端服务器。这种架构下任何一台前端服务器down机均不会造成太大的影响,任何一台后端服务器down机只影响特定用户群,后端服务器还可以采用主备方式避免这种情况发生。 — 水浸街

18. 问: 连接调用次数怎么控制频率呢?

答: 记在session中的不必采用统计方式,可以设计一个算法,session中记录两个变量,一个是上次调用时间,另一个是调用频率权值,然后计算本次调用当前时间与上次时间的差值,给时间差值分段定义单次权值、权值衰减率,调用频率权值*权值衰减率+本次权值=新的调用频率权值,然后给调用频率权值设置一个阈值判断就可以了。这个方法在设计时我有考虑,但最终没有使用 — 水浸街

19. 问: 这对前端用户频率访问控制很有效。但这样会不会因为接口太多而造成session里存的东西太多?

答: 这个判断只有两个变量,session数据是一个连接保存一份,除了这个数据还有用户编号等少数几个索引数据,不会太多的,担心这个问题可以通过缩短session有效期方式优化 — 水浸街

20. 频率控制也可以用令牌桶做. 基本思路,有一个桶,桶里面放令牌,然后每次请求来的时候会从桶里面取一个令牌,另外一端会按照一定速率往桶中放令牌,桶可以设置一定大小. 当取的时候没有令牌了,那就说明调用频率超限制了. 实际实现的时候一般不会真的开一个线程去投放令牌,一般在消费令牌的时候,判断是否往桶里放令牌。这个方法似乎在open api里面使用比较多,例如一小时最多调用150次之类的。不过我在最近一个对外接口项目中也使用了。 — 项超

21. 问: 思路不错,但是我觉得放令牌是不是和消费令牌拆开比较好?

答: 嗯,具体实现其实根据场景选择就好!比如使用golang写的话,用channel做桶,放令牌用一个协程去做,就挺合适 — 项超

22. 单独开线程这个开销太大了,消费的时候放入令牌就好,记录桶的创建时间、令牌生成时间间隔、已生成令牌数,就可计算当次需要生成新的令牌数,生成后是否放入桶中受桶的容量影响,但不影响令牌生成计数先生成、放入再消费,和单独一个线程没什么区别 — 水浸街

21. 接口可以用zabbix监控,频率控制要自己写计数器吧~可以用redis来做频率控制 — penn

22. 我先喷吧 接口设计要原子化,尽量简单,使用优雅的面向对象风格,监控。服务管理可以借鉴esb — alex

【06-19】如何做好运维?分享下你遇到的坑,用的运维程序和工具

1. 我先来 线上布个phpmyadmin 通过授权访问,虽然很危险,但很可以快排查问题,痛并快乐着 — twin

2. 这么说还有mongo admin redis admin之类的. rock mongo, phpredisadmin — 零度西瓜

3. Phpmyadmin不用好多年,最垃圾的工具,没有之一 — 如果当时

4. sqlyog不错 — 张文涛

5. heidSQL 免费的 也不错 — 姚文强

6. 我也是sqlyog直接通过ssh tunnel连线上 不过mysql admin的好处是 有浏览器就行. 尤其是对数据库和能访问数据库的机器限制比较严的情况 — 蚂蚁

7. mysql-front 不错 — 慕枫

8. 一般db都在内网,sqlyog失效 — 雪豹

9. navicat可以用你前端服务器作为代理连接你的内网db, sqlyog不知道有没?

答: 只要有 ssh 通道就可以把 — 姚文强

答: 有 但是如果前端服务器做了限制不能直连就会比较麻烦 — 蚂蚁

答: sqlyog也可以的 — 朝沐金风

10. 所以命令行才是王道 — 零度西瓜

11. 问: 你们数据库字段命名用什么风格?

答: 跟你的程序一样,你的程序用下划线,就下划线,用驼峰,就驼峰. 虽然官方推荐是下划线,但从整体来说, url请求参数,html表单字段名称,程序变量命名,数据库字段命名都应该尽可能是一样的风格 — twin

答: 前缀+下划线 — xufz

12. 我觉得表单名字和数据库字段一样容易被人猜出数据库字段名有风险 不一样的话后台做转换会安全点 有时候偷懒会直接把提交字段当变量写在SQL里 被人注入 — weizhao

答: 能注入,还要什么字段名 — 徐刚

答: 更容易猜到 有些时候手写SQL一不小心就容易忘记 不是说保持一样就不行 — weizhao

13. 我这边使用navicat,链接全部用内网ip,每个人不同账户,只有部分负责人有写数据库链接。

报警部分日志直接写文件,有内容直接发短信。

简单的必须运营手工处理的部分给他们做列表,敦促他们处理。

用于沟通的时间大于维护时间。

做得成功的话,策略时间大于修复时间。 — 幽灵灵空

14. 我们这边基本要连数据库更新表操作都找SA,数据库密码等配置在nginx的配置文件里,php通过$_SERVER来调用环境变量,一般程序员是不清楚线上数据库账号密码等的,代码提交也不需要修改内外网不同的数据库账号密码 — 幽灵灵空

15. 看过过国外的一些服务就是这样搞的 — 姚文强

16. 都知道密码又怎么样 能访问吗. 没必要折腾这个 权限分清楚就可以了 — 王春光

17. 那个方法配置一多就不行了,微博原来这么干过 — 花生

18. 问: 想了解下代码发布、上线管理,有经验的请分享下呢。

答: jenkins 我们在用 持续集成 线下发布是神器 — 张浩

19 问: 用jenkins你们会做哪几类工作呢?

答: 自动构建 发布 — 张浩

20 问: 自动构建是一个任务,每次提交就触发, 发布又是另一个任务,手动触发是吧?

答: 生产环境是脚本,测试环境一键构建发布,一个任务 — 张浩

21. 问: 现在生产环境php版本推荐哪个版本?

答: 如果是新开发的项目,可以选用5.5,旧项目如果不想太折腾可以用5.3 — skccc

22. 问: 小于5.5的版本可以直接配置鸟哥的那个opcache吗

答: 5.2以上 — 我是谁

23. jenkins除了可以做构建发布,还有很多插件:单元测试和覆盖率,代码风格,代码安全,文档,邮件…还可自定义脚本,啥都能干 — 懂哥

24. Devops,开发也讨论运维的事情,好事 — Hank

25. 不是,是开发运维工具,工具是第一,现在有很多工具,但是还要搞适合自己平台的 – Hank

26. 问:我想知道你们多机房同步是怎么做的

答:实时要求高的话只能自己拉专线或者租用 — 崔玉松

27. 光纤等于光钱 不是一般企业的方案

答: 那就只能牺牲实时性 – 崔玉松

28. 其实我觉得能不分机房就尽量不分。没办法,例如一个机房的机柜有限,那就分模块,不同模块不同机房。 — skccc

29. 不同模块不同机房 同一用户要访问多个机房数据 不合适吧 — york

30. 分模块要尽量减少模块间的数据交换。有时候需要和产品做协调。 — skccc

【07-03】哪个队列服务好? — twin

1. redis 简单 方便 易用,一服务多功能 而且效率不低. 结合webdis(此处原来是redis) 秒杀很多应用场景. 至于redis在队列方面保持够简单就行。本人喜欢这么简单的东西 — 悬非

2. 太多太多好用的mq系统了,ZeroMQ,,还有RabbitMQ,其他的什么MemcacheQ, HttpSQS,Mysql Q4M也行,不过都稍微架构上面简单些. 从应用情况来看,最靠谱和吞吐量最好的还是Apache Kafka. Beanstalkd,也是一个选择. 当然,其实redis也能做队列用 — 黑夜路人

3. 用过beanstalkd 做为任务队列 表示非常好使 我觉得他更适合吞吐量相对低的 比如任务 短信 邮件 — 吴子棋

4. 我们用nsq,分布式去中心化 — 李小邪

5. 问: 消息队列分布式有意义么?你们怎么选择一个节点的?

答: 避免单点故障. 随机选一个,如果这个发送失败就取下一个 — 李小邪

6. 说说任务队列,Python栈用的celery,主要业务为web消息及视频转码同步,用队列实现异步及降低复杂度。选择时主要考虑运行环境、成熟度。评判好坏不好做评价,任务量不大,目前一直工作良好。 — Garfielt

7. 问: 消息推送例如APNS,放在业务里面处理,还是推到队列任务里面,由另外的线程来处理好?放在业务里面我怕会影响业务,毕竟去访问第三方的推送会耗时或者出意外。不知道大家都是怎么处理的

答: 任何时间不可控的操作都应该放入消息队列改由其他进程做异步处理。 — 刘光耀-村长

8. 我一般队里服务最大的用处是用来解偶业务逻辑。 比如说一个用户注册了。那后续有系列的操作要做,比如他的各种数据初始化之类的,发邮件通知一类的。如果串行在业务逻辑里几乎是不可接受的。一般会产生一条消息,然后后台的多个进程都会订阅这个类型的消息,它们就可以并行的去做很多事情了。 — 刘光耀-村长

9. 问: 我服务端用的是PHP,有没有推荐的队列服务

答: 试试zeromq吧,这个主要还看业务设计,redis其实也可以当队列来用。 — 刘光耀-村长

10.问: 订阅赞,如何保证订阅的及时性呢,如果不同进程相互有依赖如何处理

答: 看需要。如果多个逻辑都存在不可控因素且必须有先后关系,可以用多条消息队里。消息满天飞也不是一个良好的架构设计,要平衡取舍。 — 刘光耀-村长

11. 我们用的rabbitmq,个人认为还有一个好处是后段可以横向扩展 而不需要考虑前段服务器 — 张浩

12. Nmq都用这个吧,还有个金山出的,支持http的也挺好用的 – 七文

13. 问:nmq全称是什么?

答: nmq是百度内部的消息队列系统,全称是:New Mesaage Quene

是为了取代百度之前的cm/tranafer诞生的 – 黑夜路人

14. 我最经常就是用redis的队列了。项目小就简单搞 – 轩脉刃

扩展

http://blog.csdn.net/shagoo/article/details/8964009 [架构] ZeroMQ 深度探索(一)

http://lynnkong.iteye.com/blog/1699684 【架构】关于RabbitMQ

http://m.sogou.com/web/uID=Rxae36LBHM095u99/v=5/mobile=1/sz=2-2/type=1/sp=1/ct=140702104414/keyword=kafka/pid=sogou-clse-2996962656838a97/dp=1/e=1427/de=1/ab=/tc?pg=webz&clk=6&url=http%3A%2F%2Fblog.chinaunix.net%2Fuid-20196318-id-2420884.html&f=0&id=7bd04341-ab0c-4aaa-a8ae-91fe61689adc&pid=sogou-clse-2996962656838a97&dp=1&de=1&e=1427&key=kafka&pno=1&g_ut=3&wml=0&w=1347&clkcost=19494 KAFKA分布式消息系统

http://baike.m.sogou.com/baike/fullLemma.jsp?sid=AaB59HKNW6sKePp8CYL19meX&lid=63258453&max=&g_ut=3&adapted=1 beanstalkd百科介绍

【08-02】当你的程序(PHP,C/C++,Java,Python,Go等等)出错了,网络请求失败了,如何调试和定位? — twin

1. 断点,error log. — 零度西瓜

2. 网络请求失败,比如404,500,cannot resolve host, 返回数据格式不正确等等 — twin

3. 分析程序日志,系统日志,各种系统网络路由器监控日志,再结合机房的配合 基本能搞定 — Mandman

4. 一步步定位,看是哪个环节出错,把php的error_reporting打开,fpm日志打开,nginx日志打开,tcpdump抓包看是否正常请求和到达 — 星星

5. 调试一个请求:b/s 用浏览器的network,如果有302的话可选择preserve log 或者用插件stop掉302;b/s的话可以tail -f查access.log 如需更详尽的请求信息可以用抓包工具fiddler、Charles 等。拿到请求后可在命令行下做调试(chrome 可以在networks右键得到curl)。高效率依赖于好工具,比如灵活使用用管道,查看json的话用:curl url | php -r ‘var_dump(json_decode(file_get_contents(“php://stdin”))); 还有更强大的jq: curl url | jq 。如果需要直接编辑可以用vim:curl curl | vim – 。而代码调试中经常用到二分打印,或者二分法分断删除再执行。 — hilojack

6. wireshark抓包分析 — 杨锡坤

7. if(isset($_GET['debug']))

register_shutdown_function(function(){

var_dump(error_get_last());

}); //加在头部 无需修改任何配置 对程序无害 绿色 — 吴子棋

8. PHP firebug也不错啊 或者直接封装好函数输出<!—— print_r($var) ——> 查看源码 — weizhao

9. 先判断是否是网络故障了, ping 不同ip, dig 不同域名或路由, 检查防火墙, curl 测试不同链接, 如果不是网络问题, 就要看网络请求失败的具体header status, 是否404,301,302, 或500, 如果500, 则基本可以断定是对方服务问题, 比如请求某接口, 超过频率限制, 或对方服务已挂 — 老李

10. ping, telnet, dig, route, traceroute, iptables, curl, 基本上可以确定问题了 — 老李

11. 开发要掌握dns的原理, 为啥/etc/hosts 可以绑定域名, /etc/resolv.conf用来干啥, 主要理解dns是怎样工作的 — 老李

12. 如果linux防火墙端口没开,talent是不是也会通?

答: 恩 — 老

13. 用户说你的网站打开太慢,请列出所有可能性,以及排查方法

一、网络问题

1、临时性

检查:ping, mtr 等命令,检查网络状况,DNS等

解决:联系机房或视具体情况而定

2、网络不同或距离太远

检查:客户端和机房所在网络情况

解决:双线机房或分布式部署,动态DNS,需要考虑成本

3、资源加载慢

检查:chrome控制台

解决:CDN,合并请求,压缩页面代码等

二、前端问题

1、浏览器太烂

2、页面设计不佳

检查:浏览器解析时间,是否DOM节点过多,JS有问题等

解决:优化页面代码

三、服务端问题

1、服务器状态

检查:负载,CPU, 网络,内存,磁盘空间等使用情况

如果单台服务器性能受限,考虑调整为分布式架构,如nginx转发,DB分库分表等

2、PHP响应慢

检查webserver日志中的响应时间

如果服务器整体负载不高,但PHP的数据返回时间过长,在PHP代码中分段输出处理时间

更具环境的不同,可以选择直接输出或是写入日志

如果是高访问量的在线调试,一般选取一定比例记录日志,防止日志过多带来的额外系统开销

逐步缩小范围,定位、优化

3、DB响应慢

有分为读取慢和写入慢

读取慢

检查:慢查询日志;

show processlist 查看当前DB状态,看哪些请求停留较多

top查看mysql进程的开销

代码中记录SQL和执行时间

解决:

手动执行可疑SQL(注意排除query cache的影响),用explain,profile等工具分析SQL性能

再考虑是否优化索引,或者分库分表,或者增加缓存

写入慢

检查:除读取慢的检查方法外,还有

iostat 检查磁盘IO

查看mysql binlog的写入速率

解决:增加缓存,分库分表,优化索引,从业务逻辑上考虑减少DB操作,合并写入

4、其他

被攻击,webserver进程数受限,甚至内网流量过高等原因,都有可能导致访问缓慢,具体情况具体分析

– XiangZ

14. 大家说了网络层面的,我说一下应用层面的吧,对于后端程序最靠谱的方法是看日志,因此代码里写日志就非常重要了,我这的后端产品都有全局的日志对象,每条日志记录编号、时间、类型、级别、执行经过时间、内容以及SessionID、请求编号、调用顺序号、访问渠道、用户编号、IP地址等标识请求方的字段,一般开发时的日志级别是Debug级别,线上运行时记录的日志级别是Error级别,可以通过配置指定特定的用户、IP地址的日志级别,比如某用户反映操作出错或相应很慢,排除网络问题后可以对该用户开启Debug级别的日志,通过日志定位问题。有两块日志是公共的,一是接口入口,记录接口的响应时间及未接管异常的错误信息、栈信息,二是统一封装的数据库模块记录的SQL执行日志,记录SQL响应时间及出错信息。 — 水浸街

15. 问: 线上不开debug有哪些原因呢? 为什么要分两块日志呢?sql出错也可以归到异常的

答: 日志记录本身是要消耗资源的,debug的信息非常多,所以不能开,当然性能允许也可以开。我说的两块日志是公共日志,就是不需要业务模块显式写日志的,实际写还是一个入口的。SQL出错的原因有很多,比如违反唯一性约束,这种情况下还是可控的,称为错误(error)合适一些,而异常则会引起程序流程终止执行,属于更高级别的错误(fault)。

16. 对sql日志更多的应该还是一个审计,有没有异常,有没有慢sql. 要保障数据库的安全和稳定 — 易元建

17. 对,这是另一个功能,这里再次说一下SQL绑定变量,使用绑定变量除了可以提高效率,还可以保证一个系统的SQL语句的数量是有限的,可以从日志统计出各SQL语句的平均耗时,发现有问题的SQL语句 — 水浸街

18. 问: sql的error和fatal通过errorno区分? 那业务逻辑不就变复杂了吗?每次都得考虑各种code

答: 写日志不需要通过errorno区分,在入口try-catch捕获异常就可以了。 — 水浸街

19. 有个记log的形式叫cross finger。debug类型日志会先放内存里不落地 当出现error以上日志 就会把所有debug(包括之前未记录)也落地。这样可以更了解出错时的情况,减少让用户去重现的次数 — twin

20. log+strace+tcpdump+systemtap – 李奇

21. 出错比请求慢定位方便。取出URL,手动请求,根据返回一点点下去,一般会很容易发现问题在哪。–7 Days

22. 重点还是要log打的好 — 李秋林

23. java,机器挂了有报警,业务出错有日志,有专门监控异常的系统定期分析异常原因,自己也有业务api工具线上出问题先看接口是否异常,然后再跟踪日志 — hello,zhuli

【08-19】WEB IM中,消息系统如何设计开发? — Micarol

1. 消息系统应该是分即时+队列,双方在线的话直接socket.io即时推送,有一方离线状态就转到离线消息队列,也可以是数据库 — 青衫隐_刘

2. 问: 通过上线监控出队?

回: 是的 — 青衫隐_刘

回: 怎么出? — 王春光

回: redis、memcache都可以啦 — 青衫隐_刘

回: 这得维护多少队列 — 王春光

回: 对,我就感觉这样队列太多。 — Micarol

3. 真正的IM 比这个难多了 你得判断用户接收到没有 还分会话 — 吴子棋

4. 100w在线不知道我就做过小型的 企业内部的那种我那种方案还是能hold住的 中小企业吧 我们是做办公软件的,在试水用socket.io+Node.js 所以用户量大的话估计也hold不住… — 青衫隐_刘

5. 在之前我有个创新项目有考虑过,但最终没有落地,可以说出来供大家参考一下,也欢迎指出问题:使用redis存储消息列表和用户相关信息,消息采用结构为list,每用户一个key,设置最大消息数(如200),消息体使用json结构存储消息id、发送者、时间、内容等,给用户发送消息把消息加入用户的消息队列即可,使用lua执行消息入队操作以保证入队、删除超出容量的消息、更新未读消息数量原子性执行;用户相关信息使用hash,至少需要用户id和未读消息数两个field;redis的key总数是有限制的,使用一致性哈希方式把用户分布到多个redis实例上,这种方式易于扩展,用户量增加时加机器就可以了,初期可以在一台主机上部署多个redis实例;Web端使用http方式交互,在任何地方登录时均可从list中读取指定数量(如10条)最新消息,可翻查历史消息,然后每过一定时间(如5秒)调用http请求检测是否有新消息。 — 水浸街

6. web端轮询?还有优化空间的,如果是高级浏览器可采用socket.io 相信能减轻不少服务端压力 低级的自动降级成comet 当然这就是前端的优化了 — 青衫隐_刘

7. http是无状态协议,很适合大量用户同时访问,我看微信web版也是使用http — 水浸街

8. 问: @水浸街 你们当时设想的用户基数是多少

答:当时是一万用户左右,但这个架构已经考虑了扩展性,具体能支撑多少没有实验过,理论上只受制于带宽和计算能力 — 水浸街

9. 微信在高级浏览器上用的也是长轮询的方式 — 光阴的故事

10. 我想socket.io或者其它websocket实现肯定有其优势的,具体我没怎么了解,我的理解是长连接可以节省带宽,但对服务端有资源消耗的,并且系统的逻辑也会更复杂,而http连接的技术很成熟,分布式、负载均衡方案稳定可靠,对我当时的系统要求来说足够了,最终所以设计时采用了http长轮询方式。至于采取哪种方案更合适,我想这是一个取舍问题。 — 水浸街

11. socket.io可以设置transport优先顺序的 — 朝沐金风

12. Web socket+flash socket. 以后移动端也可以用websocket协议 很方便 Android和ios都可以用 — 刘祥昆

13. 木有深入尝试过消息系统

偷懒用redis的队列做消息服务了 — 闵敢

回:嗯。好多是利用redis搞的

pub。sub模式本身就是不存数据的

具体看下redis源码 — alex

14. 我们现在基本上基于 tornado + socket io + redis 来做

如果深入用redis 还是需要一个ORM工具,不然不太好设计,redis 的pub/sub 性能很好,就是消费者不存在的时候消息不存 — 崔玉松

15. 研究了下web微信,消息同步不同类别分别有一个消息id,不同端去维护自己的消息id,通过token和消息id去拉消息可以保证不同端的消息不会丢失。就研究这么点 — Rogee

【09-10】交流下大家Nosql的应用场景 — 刘卫涛

1. 非实时数据都可以用nosql做缓存,nosql做缓存,落地还是用sql关系形数据库。 — @理鱼

回: 还得看是kv还是document — John__

2. 昨天看了下做本地缓存可以用redis做lru的缓存队列 — John__

3. 缓存高频sql,这个应该是最常见的吧 — 徐刚

4. 一些层级比较多的数据,用nosql可以保留原始数据结构,用mysql程序复杂度就变高了 — twin

5. 问: Infobright 大家谁用过 — 太公望

回: 我用过免费版。因为不能插入数据,觉得麻烦,试用之后就不用了. 必须每天dump入数据 — Micarol

回: 这个就忍了。Infobright 我在想,给它多大的内存呢? — 太公望

回: 我当时数据量也就几千万,所以没考虑配置调优,试用的时候用的是默认 — Micarol

回: 一步到位吧. hadoop. 去年这个时候我们也为了这些离线计算和数据头疼,几乎试了所有一个普通web工程师能搞定的方案,最后都放弃了 . 除非你很牛逼 否则Infobright 对你没用 — 崔玉松

回: hadoop我试过。感觉太大了。 Infobright 我觉得刚好。 至少看广告是这么感觉的。今天就部署个,争取明天投入使用 — 太公望

回: 看你多少数据了 一亿以内,随便怎么算. 搞个mongodb 都能算 — 崔玉松

回: 目前有几亿吧。。。刚看了一眼,7.5亿 — 太公望

回: 那不太看好你用ib — 崔玉松

6. 存储问题大多数情况下关系数据库是第一选择,如果需要在某一方面有更高的要求(一般是读写性能、吞吐量、数据量之一),且可以放弃关系数据库的某些特性(一般是数据一致性、可靠性、可用性之一),那么nosql会是更好的选择 — 水浸街

7. 我这用memcached、ttserver、redis、hadoop+hive比较多,前三个是缓存,memcached是早期方案,成熟但不支持持久化,ttserver完全是因为兼容使用memcached的代码的持久化方案,性能一般,新项目都用redis了,推荐,hadoop+hive是廉价的高可用大数据存储方案,合理的设计情况下查询速度比关系数据库还快 — 水浸街

8. 业务增长快,变化未知 。nosql首选 — flea

9. redis的持久化有一些坑。。。用的时候要小心,我遇到过redis大了,持久化的时候就不能做set操作。。。我觉得redis还是纯当不需要持久化,可即时生成的缓存比较好。。 — 轩脉刀

回: 嗯,redis的持久化要谨慎选择,一般建议使用aof,闲时清理. 你说的不能set是什么情形下的?我看源代码是开内存副本支持set的,内存要预留够大就没问题 — 水浸街

回: 如果按照默认设置stop—write-on-bgsave-error 是off值的话,当时redis 占用1.8g,所以做快照的时候发现set操作返回错误. 解决就是把这个设置直接开on了. 开内存副本就意味着要预留至少redis同样大小的内存对吧. 如果没有预留这么大内存redis会怎么表现呢 — 轩脉刀

回: 你把内存大小设置下。。然后改下落地时间不可以么. 我说下我们的吧,我们是用户操作只到缓存,,然后间隔同步到数据库 — tywei

回: @轩脉刃 你说的那个配置项设为yes时也只是当bgsave出现错误时才禁止写的吧,这是一个保护机制,避免没人发现持久化失败了,问题应该出现在持久化上,可以看日志查找一下原因. 不是一定要同样大小的内存,fork子进程与主进程开始是共享同一份内存的,只有新的set到来时才按页写副本,极端情况下所有内存页都被修改时才需要同样大小的内存 — 水浸街

回: 我们有几百个redis实例,整个业务体系就是用redis做持久化,没什么不可以的。 — lalala

10. @水浸街 ttserver有对冷热数据的处理么 — 花生

回: 不太清楚,我们只用了ttserver很少一部分功能,就是兼容memcached协议的hash table存储,据了解ttserver在大数据量时会有问题,性能又不是很好,不建议使用 — 水浸街

回: 看了下有冷热数据的. 热的在内存. 说的tt在单存储文件较多值时会变慢,但是现在可以设置存储文件个数,哈希分不到文件里解决这个问题. 这玩意儿太适合我了,我的情况是冷热分的特别特别的清楚. redis不适合我,因为我的情况是1w个数据中,热数据就只有10个,其他全是冷数据。所以放redis是严重浪费内存,因为数据量有点大 — 花生

11. 积分墙广告回调接口使用的redis,手机识别码作为key,时间戳作为value,编程简单,响应速度快 — ning

12. 日志收集 缓存 不支持事物所以还没大范围使用 只用到以上两部分 — 汉族教父

13. 大部分都做数据库连接缓存用, — 阎铭

14. 输入框自动补全用redis速度快 — 光阴的故事

15. 目前我们公司用了redis和mongodb,前者用于市场推广数据后者用于平台程序日志。推荐本书《深入NoSQL》 还不错 — 慕枫

16. 个人站,用redis list类型做队列。不如专业队列系统牛但是100个线程跑还是够用的,多的没试过。 — Rogee

17. 用redis非常多 实时的数据业务全部构建在redis上面. 队列 集合 有序集 kv 哈希表 都有用 — 闵敢

18. 用的Saab. Facebook开源了rocksdb. 都是基于leveldb开发的 — 刘祥昆

19. 這個我最近有一些感觸,能用NoSQL或k/v存儲解決的,就不要用RDBMS, 能在應用服務器內部內存解決的,就不要用NoSQL,應用服務器內存解決掉,在OpenResty的應用場景就是ngx.shared.dict與lua-resty-lrucache, 前者是跨進程基於mmap實現的共享內存,後者是跨coroutine級別能共享table級別的資料形態,這兩種都是效率極高的應用級別”NoSQL”而且完全沒有網路或磁盤IO overhead,如果是openresty的應用場景,大量使用這個減少外部redis或mongoDB 存取,大流量的時候性能會有驚人的表現,但是不能只用這個,也是要搭配redis,mongoDB來做類似二級NoSQL緩存的概念,包括資料持久化也在這裡完成。– Pahud

20. Redis的evalsha功能非常強大,一些業務邏輯寫成lua載入到redis內部,redis客戶端透過evalsha來叫用內部函式,性能極好,但是要小心不能有太多CPU bound的運算,會影響redis單線程的堵塞。 — Pahud

21. 此外,如果應用場景需要用到依時間排序取得key,在透過key取得具體payload這樣的情況, redis sorted set可以滿足大部分的需求,不需要用到mongoDB或MySQL了。 — Pahud

22. 再來一個分享就是,無論是用哪一種基於網路的NoSQL, 客戶端盡可能使用conn pooling,而且用完務必放回pool不要讓他自然關閉,否則服務器會有非常多的TIME_WAIT連線等著被回收,浪費了服務器資源。 — Pahud

23. 用过redis的pub/sub,用于消息推送 — 古手

问: pub/sub是不是要长连接? — 陈一回

回: 当时是做一个内部系统,用websocket连一个服务,服务长连redis — 古手

转载请注明:IT世界 » 互联网app长连接消息push系统的架构和坑

您必须 登录 才能发表评论!

网友最新评论 (1)

  1. 好文章,内容酣畅淋漓.
    荷兰网2015-02-28 04:28