注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

yu.chen的博客

坚持到底就是胜利

 
 
 

日志

 
 
关于我

喜欢数学, 喜欢编程,喜欢开发系统,喜欢逆向工程,喜欢欣赏开源前辈的代码

网易考拉推荐

保持连接,自动重启的问题  

2012-11-13 16:25:28|  分类: 系统开发 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
上周初,遇到下列问题。
==============
问题一描述
1. gen_server的正常工作依赖于另一个服务的正常连接,比如说是数据库连接,或者是队列服务的连接。
当连接故障时,希望连接故障解决后,系统可以自动恢复正常工作。而不是系统故障超过一定时间期限后,系统就停止工作。
------
问题原因:
这个问题的麻烦在于,直接使用supervisor的restart strategy机制进行重启,设置maxr参数与maxt参数,参数设置过小时,由于连接的中断时间是不确定的,可能是几秒钟,也可能是几个小时。很容 易造成supervisor遇到reached_max_restart_intensity的情况。

上述原因一旦发生,supervisor就不会在启动服务,造成系统停止的问题。
------
尝试解决的过程
1. 开始想到的是使用定时器解决这个问题,将连接问题,不作为exit进行处理,在模块内部try...catch这个问题,当出现故障时,过N秒钟,发送一个消息给自己,尝试重新连接。
但是写完后,发现用定时器的代码,比较难以调试,尤其是在多个服务直接有依赖关系时,更麻烦。
另外,放着otp的supervisor机制不用,不在这个机制内解决问题,自己写一个类似的重启方案,是种比较差的方案,总觉得有一个更好的解存在。

2. 尝试另一种方法解决,还是捕获连接错误,但是这次不是自己构造与处理消息,在模块内部解决问题。而是在handle_info中尝试添加等待的时间,在等 待完毕后,在让服务停止,造成supervisor重启该服务。由于supervisor的maxr与maxt的参数配置与这里的等待时间比例合适,造成 supervisor永远不会遇到reached_max_restart_intensity的情况,那就避免了系统在一定时间的重试后,停止系统的情 况出现。




=======================
问题二描述
这是上面问题的一个派生出来的问题是,当这些连接在系统启动时,就已经处于故障状态时,系统可以启动,而不是开始就处于故障状态,要等待连接正常后,才能启动。这个派生问题涉及到gen_server的init如何编写的问题。
----------
问题原因描述
1. 当连接相关的代码写在init函数中时,当init执行出现异常时,会导致supervisor的init出现异常,而supervisor的init异常会导致restart的主体故障,restart的机制无法生效。系统无法启动

尝试解决的过程
1. 开始想到的还是定时器的方法,把代码移出init函数,使init函数中的代码尽量都是简单代码不容易出现故障的内容。
使用timer:sendafter(0,Message)方法,在0秒后,立刻执行。
这个解决方法的缺点也是调试困难,在上述写法的客户端中,在start_link函数之后,必须提供一定的延迟(timer:sleep(N),否则服务器还没有正常连接完成。因此客户端的代码会显得很差劲。其中的N参数纯粹是一种猜测。

2. 不满意这个解决方案,那就在找其他解决的方法,又翻了一遍rabbitmq的源码,在rabbit_networking.erl中找到了一些线索,做了 一些调整后,尝试使用process_flag(trap_exit,true) + exit(pid,reason)解决这个问题。
当在init函数中遇到连接问题时,尝试捕获这个问题,并调用exit给自己发送一个消息。然后添加一个handle_info处理这个消息。这样就不会 造成在init中退出。为了使服务能够捕获消息,所以在文件的开头使用process_flag(trap_exit,true).
其中调用exit有两个选择,一个是exit/1,另一个是exit/2, exit/1不能使用,而只能选择exit/2,理由是exit/1无法转换为消息。

再次核对rabbitmq源码时,发现对方使用的是exit/1函数,不知道为什么,应该是某处自己理解错误了。有其他看到这个帖子知道答案的人请回复一下。
  评论这张
 
阅读(243)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017