除此以外,从业务逻辑来看SNMP Agent相对的稳定,由于它只是翻译收到的SNMP消息并最终调用Box库中的函数完成消息的处理,而Box库会因业务的演进而频繁地变更,于是Box库出错的可能性也更大。那如何经过设计来介定当堆栈被破坏这类严重的问题出现时,应当由哪一个团队去负责追查问题的根源呢?或者说,SNMP Agent团队如何经过设计来保护本身以避免“背黑锅”呢?这种防范是有意义的,它不仅意味着问题出现时能快速的介定责任团队,也能够避免没有必要的团队扯皮,说到底就是能提升工做效率。
做者所提出来的第一个解决方案的思路是,可否经过设计一种方法记录SNMP Agent程序当前正在运行哪一部分的代码?固然,这种信息只要足于区分是运行Box库中的代码或是SNMP Agent中的就好了。最为直观的作法是,每调用Box库中的函数时,在调用以前打印一行日志,在调用返回后又打印一行日志。这种方法在前面说起了,可能会存在必定的性能问题,但其思路仍是对的,只是须要采用其它的更为高效的方式替代日志记录。做者想到了Linux中的共享内存!Linux中的共享内存有一个特色,一个程序若是分配了一块共享内存,若是程序不主动对其删除,则即便是程序出现了崩溃其中的内容也一直保存在那不会被更改,固然操做系统进行过了重启的话则除外。
如此一来,经过设计能够将调用Box函数以前和以后的信息经过使用一个×××变量的方式记录程序是不是在调用Box库,固然,这个×××变量是位于SNMP Agent所建立的共享内存中的。好比设置整型值3表示将要调用Box库中的某一个函数,而在调用完了这一函数后将这一值设置成4。当SNMP Agent出现崩溃后,在其下一次启动的初始化阶段时(咱们的系统有进程管理程序,发现一个进程出现崩溃之后,又会自动重启它),经过打开同一个共享内存块就能够知道上一次程序出错时,是不是出如今调用Box库其间,若是是则记录一个错误日志。好比,若是发现整型变量的值为3说明崩溃是发生在Box库内的,则记录一条错误日志。固然,设计考虑到了多线程的问题,且以线程为单位来设计的。有了这种方法,当出现问题时,经过查看日志就能很快地定位责任团队,且几乎彻底不失程序的执行效率。
这种设计方案在操做中存在必定的运做效率问题。好比,即便是Box库的问题,这一问题一旦在测试部门发现,则必定会将缺陷提交给SNMP Agent团队,SNMP Agent团队在查看日志后,发现是Box库形成的问题,因而将缺陷转交给了Box库团队。能不能又经过设计让Box库一出现问题就让测试部门将缺陷提交给Box库团队呢?图2展现了进一步的设计方案。
图2
在这一方案中,增长了一个新的Proxy进程,这个进程的程序也是由SNMP Agent团队开发的。SNMP Agent进程和Proxy进程之间采用了IPC(Inter-Process Communication,即进程间通信)进行通信,就是将前一方案中SNMP Agent直接调用Box库函数的形式转化成了经过进程间通信将这一调用发送给Proxy进程,Proxy进程再经过FDR接口调用Box案。固然上一方案中采用共享内存记录哪一部分代码正被调用的方法被运用到了Proxy进程上,以帮助介定问题是发生在Proxy进程自己仍是在Box库内。在这种方案中,其中很重要的一个内容是,Proxy进程的逻辑很是的简单,即接受来自SNMP Agent的消息而后调用Box库函数并经过消息将Box库函数所返回结果传给SNMP Agent,其逻辑不会由于项目的不断变化而变化,除非FDR发生了变化。可能这种方案刚开始部署时,Proxy会有必定的缺陷,但通过必定的时期稳定后,一旦出现Proxy崩溃的问题,则极有可能就是Box库所引发的了,而这种情形下测试部门能够直接将缺陷提交给Box库团队。
至此,相信读者已明白了“保护本身”这一设计原则是如何起做用的了,可能有的读者也会有一点灵感去解决本身项目中正面临的相似恼人问题。另外,不知读者注意到了没有,这里所谈的共享内存方案,其实能够做为一种通机制去辅助缩小出现问题时程序的出错范围。前面也提到是经过一个位于共享内存中整型变量来记录程序的运行点的,而这个变量能够定义232个值用于表示程序的不一样执行点,固然应用程序须要在合适的地方对其设置不一样的值来指示程序运行到了什么地方。