開源項目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的線程池》

相關文章
相關標籤/搜索