开源项目SMSS开发指南

  

项目介绍

  SMSS是一个由我我的发起的开源项目,目的是创建一套轻量化,高可用,高安全和方便扩展的业务支撑框架。SMSS面向TCP/IP层开发,适合扩展上层业务接口。数据结构传输序列化经过Protobuf实现。传输过程当中的数据通过OpenSSL加密再由接收端进行解密,文件传输也须要由发送方的秘钥首先作签名再由接收方验签。核心功能彻底不须要DB支撑,下降学习、开发和部署的难度。客户端使用Electron,也足够简单和保持跨平台特性。另外一个方面,我相信对于每个曾经心怀梦想进入IT行业的人来讲,可以建立属于本身的开源项目都是一种对“我的价值”的体现。我也相信这样的梦想从未消失,只是各类“福报”淹没了。因此,三月前我决定与其等待他人给我“福报”不如本身动手来实现属于本身的“福报”。html

  目前项目已经发布在gitee上(源码地址),技术验证和原型开发已经完成。client目录下是客户端相关源码,开发语言为JavaScript。server目录下是服务端相关源码,开发语言为C++。扩展功能可能会经过Java来支撑。doc目录下主要是一些设计文档和Protobuf结构文档。node

  开发过程当中不管是技术要点仍是架构方面都有不少收获,本文主要就这些方面的感悟进行分享。更多实现细节我会在从此分专题介绍。linux

经验分享

核心框架是越丰富还好仍是越简单越好

  一个框架不管大小最终都须要服务于具体业务,或提供支撑或提供具体实现。但是咱们又不能仅仅经过具体业务来设计框架,那样话就失去了通用性。一段没有通用性的代码是毫不能称之为框架的。所以,为了设计一套优秀的系统,设计人员应该具有至少两个方面的能力——高度抽象的能力和剥离依赖的能力。首先,设计师须要先将业务需求抽象,抽象出那些适合开闭原则的接口。例如,模块A和模块B须要通讯,咱们能够分别在两个模块中实现一对Socket。但是若是还有模块C须要加入该怎么作呢?做为一个更加合理的方案是设计一个模块X,全部须要通讯的模块都须要先向模块X注册,而且只须要向模块X发送消息。转发和消息缓存所有由X内部完成。说到转发,X如何保证消息可以正确的从A发送到B呢。或许你会想到将每个模块的通讯端用一个map保存起来以方便点对点发送。点对点的发送是一个好方法,但是若是业务需求是A要同时向BCD发送消息呢?为了解决这个问题,我参考IP包TTL的概念,每个须要发送的消息都添加一个计数器。不管该消息是广播仍是点对点发送,都会通知每一节点来读取,每读取一次计数器减一。固然只有正确的节点才会将消息发送出去,对应的模块才会接收到。当计数器为0的时候表示该消息已经能够释放。模块X能够从缓存中取出下一条消息继续广播。没错,这就是微服务的本质,而模块X还有一个更通俗的名字——网络总线(netbus)。git

咱们什么时候应该考虑将代码封装

  这个问题也是我在开发工做中被问及最多的。这是一个简单的问题,每个开发人员都会面临相似的难题。有时候咱们发现,不少的代码堆在一块儿既没法阅读也没法维护。但是有时候咱们也发现,过渡封装让简单的逻辑难以理解。那么到底怎么作才是合理的呢?这里我提供封装的三个层次。在这三个层次上你均可以对代码进行封装,除此以外先堆在一块儿也不失为一个策略。算法

  1. 分解代码的规模:一段代码太长了,仅仅是很差阅读。那么你能够将他们用几个方法先作简单的分类。方法名要通俗易懂,让别人一看就知道大概分几步,须要修改也有的放矢。这种封装也是对应复杂业务最多见的方法,毕竟在面对绝大多数的开发任务中,咱们不会有足够的时间深刻对业务分解和抽象。
  2. 下降调用难度:针对一些复杂的逻辑,可能须要调用者传递多个参数。这时你能够考虑利用设计模式(建造者模式、代理模式等)将调用过程分解,必要的时候甚至能够经过返回值告诉调用者内部发生了什么。从而下降调用者出错的概率。
  3. 隐藏差别:设计接口和面向接口编程的目的是能够隐藏内部实现。优势不言而喻。这个方面C++没有像Java那样提供纯粹的接口,可是设计思想倒是共同的。

注释越多越好吗

  要解释这个问题,咱们应该明确几个概念。你的代码给谁看?注释须要解释什么?注释如何被利用?编程

  1. 代码给谁看?答:若是你的代码是让新手可以尽快上手而且在不须要看源码的层次上就马上着手开发。那么注释应该越详细越好,甚至一行代码三行注释都不为过。
  2. 注释须要解释什么?答:主要是两个方面。首先是对这段代码的做用加以解释,让别人可以对业务首先有一个了解。其次是对算法作出说明。
  3. 注释如何被利用?答:如今有愈来愈多的工具能够根据你的注释生成文档。所以,你应该学习这些工具的使用方法并充分利用它们为你的代码加分。你所须要作的仅仅是按照规定的格式来写注释而已。
  4. 注释越多越好吗?答:为何不少开发人员不肯意写注释。不只仅是由于浪费时间,更多的缘由实际上是写注释会打断开发的思路。不少时候注释都是在代码开发完成后才补充上去的,这就成了一项额外的工做。大部分时候,企业也不多作代码评审,写的注释也没有人关注。而且我我的其实也很不喜欢看到注释不少的代码。光看注释看不懂,看代码又收到影响。

  所以,我对注释的观点是:按照文档生成工具的规定格式写注释便可。提交源码的同时生成一份document,既能够证实你的工做量又知足了大多数状况下的要求。至于方法内部的注释,关键地方说明一下便可。json

我应该掌握更加底层的原理仍是应该学习更加新颖的技术

  若是只能用一句话来回答,就是都要学。设计模式

  全部的发明本质上都是发现。新技术的产生并非一个孤立的事件,它每每是为了解决一些之前不被重视的难题。Java中有IO和NIO的概念,相信不少人都了解。工做中我发现,不少人其实对NIO的理解不够深入,仅仅是知道它是一种non block IO。但是为何它是非阻塞的,非阻塞就必定比阻塞好吗?我经过学习libevent,理解了在操做系统层面自己就对IO提供了select、poll和epoll几种驱动模型,目的是IO的多路复用。但是系统总线只有一条,复用的究竟是什么。复用的实际上是程序(CPU运算)。相比IO总线来讲,CPU的运算效率高得多。传统的阻塞IO当程序须要从文件或网络上读取/发送数据的时候就需等待在那里直到操做完成,而非阻塞IO模型使得程序能够在这个过程当中先向下运行,直到数据准备好之后再回来处理。缓存

  那么非阻塞IO必定比传统IO好吗?有过JavaScript开发经验的人必定会对各类回调不陌生,甚至“深恶痛绝”。因为nio模型不会等待数据读取,一般状况下咱们须要经过注册回调函数来完成任务。若是有大量的IO须要处理,回调函数就会层层递进。这样就增长了开发和维护的难度。安全

  你瞧,学习底层原理和理解新技术自己并不矛盾。理解一些底层原理也会更容易掌握新技术。除此之外,设计模式和算法也是咱们平时须要积累的地方。SMSS中利用红黑树完成用户ID和用户名的查找,在用户登陆和用户离线的时候会触发红黑树的旋转。最后我想说,底层原理和新技术自己不矛盾,你都应该学习。更加多元的技术能让你走的更远,更加扎实的理论功底能让你走的更稳。

  面对一项复杂的任务,我应该注意些什么

  和全部人同样,这也是我在开发SMSS中常常思考的问题。目前,每次增长一个新的功能我都会首先考虑,这个功能应该如何测试,尽可能作到每完成一块均可以经过测试观察是否达到了预期。传统的瀑布式开发显然已经不适用了,因为全部的设计和开发工做都由我我的在业余时间完成,时间并不容易自由控制。所以若是一个小的功能点在写完后没法被验证,几天后我就极容易忘记当初的思路。完成一个较大的模块每每须要几周时间,若是等到那时再测试就很难发现问题了。若是你也能遵循这套标准来安排本身的工做和学习,那么恭喜你,你已经掌握了敏捷开发的关键要点。

  不少时候,有关设计方面的应用就是在这样的一点一滴中获得实践。

技术介绍

接下来简单介绍一下我在SMSS中运用到的技术。

  • 利用libevent开发的网络复用模型,而且在它的基础上实现了一套线程池。使得多条链接能够复用在一个线程中运行,从而最大限度的利用系统性能。
  • 数据通讯采用protobuf做为序列化方案。这要比json或xml更好的利用网络,减少信道占用。而且,因为protobuf支持多语言的特性,后期扩展也很容易。不过,在使用protobuf后我也发如今js端的支持还有待改进。
  • 目前服务端的日志系统使用了log4cplus。做为一个Java开发人员,我对log4j很是熟悉,这也是我选择它的缘由。
  • 客户端采用Electron,毕竟开发便捷和提供的跨平台特性是目前开发桌面系统的不二选择——相对而言Qt就显得略笨重。不过Electron毕竟是使用JavaScript做为开发语言,开发方式不如传统语言来的顺手(也多是受我的能力限制)。
  • 用户登陆验证借鉴了git的方案,依赖linux系统来完成这些工做。
  • 信息加密由用户获取服务端经过OpenSSL生成的秘钥来完成,nodejs也支持对应的加解密算法。

最后,但愿你们能继续关注我后面的技术分享,也欢迎加群来与我交流。

相关文章:《开源项目SMSS开发指南(二)——基于libevent的线程池》

相关文章
相关标签/搜索