关于库接口的几点思考

 由于项目需要,我写的服务进程要同别的进程进行通信,目前采用的是本地socket方式。旧工程中采用接口的是直接暴露通信格式,由服务使用者自己写调用函数,封装数据进行通讯,这会有以下几点问题:
  1、使用烦琐,每个不同的进程都需要写自己通信函数:建立socket,链接,写入,读出,关闭等一系列重复的操作。
  2、通讯格式改动不便。由于服务升级或者别的原因通讯格式会产生变动,而这种接口方式一旦变动就需要把所有调用者的程序重新修改编译。
  3、升级扩展不方便。也是由于上点的原因,如果我想加入新的功能,或者改变现有功能必须重新编写调用者的函数。
 综上,需要开发一个动态库给调用者使用,只要我保证接口规格不变,内部实现可以随意升级,额外代价只是覆盖掉旧的动态库,而且减少了调用者重复工作,增加了开发效率。
 在设计和实现该接口过程中,遇到如下问题:
  1、本地socket文件位置问题,旧的方案是把socket文件名作为常量字符串直接写在代码中,但是服务端的socket文件是可配置的,如果被用户配置为另外的文件,就不能成功通信,所以必须要采用一种更好的方案。后来和老赵讨论了这个问题,我说要不要直接读服务的socket文件,反正这个文件的位置不会变动,可以直接hardcoding到代码中。老赵说这样就破坏了结构性,服务的配置文件不是客户端需要关心的东西。最后提出了一个方案,客户端可以通过自己的配置文件来得到服务端的socket文件位置,然后作为参数传给通信库,如果参数有效,那么就使用,如果无效就使用通讯库的代码中写入一个默认的socket。这样算是比较好的解决了问题,而又不会使得调用者改动太多。
  2、内部还是外部状态的问题。当前服务端采用的方案是每进行一次通信就需要开启和关闭一次socket,所以我打算在通讯库里面也进行同样的操作,其通信socket由初始化参数决定,作为一个static变量保存在通信库中。但是在web处理这种小数据,大并发量的任务中可能会造成IO开销过大。所以通信格式以后可能会改动为在规定时间内维持socket通信,或者一方显式的提出关闭通讯的请求才会结束这次通信。目前有两种更好的方案,1是使用外部变量保存socket信息,由初始化函数去初始化之,这样不同的外部变量可以保存不同的socket通信,之间互不干扰。所以我以后升级了通信方式也不会对程序产生影响了。2是库内部内置一个池,池的容量,默认量,最小量可以由初始化函数决定,池内保存了很多待用的socket,我使用互斥的访问它们就可以了。第1种方案性能调用者拥有更大自主性和优化空间,但是使用起来也麻烦,需要自己保管外部状态变量的空间以及状态。第二种方案包装的更加完整,调用者使用起来很方便,完全不用关心通信状态,但是由于使用了互斥,在高频访问下造成性能下降。到底使用哪个方案还得要看实际环境下哪种更有优势。
 接口的问题很大一部分就是一个封装的问题,封装的太多,用户感觉不够灵活,不能微调;封装太少了,用起来又繁琐,容易出错。同样需要在实际环境下去观察,分析,总结。
 所谓计算机工程师和计算机科学家不同,他们不钻到理论中,去发明什么新的东西,而是利用已有的成熟的资源,去根据工程参数的不同而使用和改造现有方法。以工程化(可测量,可计算,可推断,可重现)的方法在时间空间人力财务各个方面使用最优的手段去解决实际问题,这才是工程师存在的本质。我想自己正向着工程师迈进,可原本的愿望却是后者呢(你原本到底有没有愿望 –!)...

This entry was posted in 软件工程 and tagged . Bookmark the permalink.

2 Responses to 关于库接口的几点思考

  1. kyee says:

    可以下载GCI: http://download.csdn.net/source/2451725

    GCI (General Communication Interface 的缩写)目前支持Linux(内核在2.6以上)和Windows, 服务端只要定义自已的函数, 客户端就可以远程调用了, 可以参考一下。

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注