用互聯網思惟來開發客戶端軟件——項目開發小結

      隨着智能手機、平板電腦的快速發展,臺式電腦在我的用戶那裏已經沒落了,可是臺式電腦仍然是企業用戶工做中的主要工具,且具備不可替代的做用。客戶端軟件在企業級用戶那裏有着不可替代的做用,結合時代發展,咱們應以互聯網思惟來作好企業級應用客戶端軟件?研發快速迭代、快速試錯,把大功能拆分紅小功能,分階段實現,追求微創新。
前端

    一般企業級應用的客戶端,就是企業管理應用系統,通常分爲BSCS兩種架構,CS架構要求在用戶的電腦上裝上客戶端與數據庫,或者數據庫安裝在數據庫服務器上。這種方式咱們常常會碰到一些問題,好比用戶的數據庫壞,要求服務商幫助進行恢復;用戶說個人數據沒法保存到數據庫中了,大家來看一下,這樣就要派出人力到現場進行問題診斷,或者簡單問題使用遠程維護的方式,無論哪一種方式,一旦用戶的數量超過了必定的量,那麼公司的運維成本就上去了。那麼有沒有一種方式,改變這種狀況呢?雲服務風起雲升,雲數據庫的興起,寬帶速率的大幅度的提高,寬帶價格的不斷下降。讓我看到了一種解決方式。此次公司開發的新項目中,力主採用數據庫放在雲端,客戶端經過服務端的Rest Ful接口去雲端訪問數據,而後加載到本地,用戶進行業務操做。  java

      提及互聯網,你們一個反應便會想到網站,例網易、新浪、淘寶、京東。你們想必也知道網站與客戶端軟件各有優劣吧,好比:網站能夠運行在任何設備的瀏覽器上,不須要用戶安裝,網站有更新了,也不須要用戶去升級,只要刷新一下瀏覽器就能夠了,能在各類終端(平板電腦,智能手機,臺式電腦等)保持統一的用戶體驗(固然須要有很是好的前端工程師);而相比之下,安裝在臺式電腦上的客戶端軟件會運行得更快,而且可以充分利用本地資源爲用戶帶來更多的功能、更方便的操做。BSCS各有優劣,那麼如何能把二者進行一些融合呢,讓客戶端軟件具備一些BS架構的優勢呢。我試着把一些互聯網的優勢融合進了這次的客戶端軟件中。web

項目介紹算法

     這是一個很大的項目,企業級用戶數在1000以上,業務多並且複雜。我作爲項目的客戶端負責人蔘與系統需求分析至測試和部署的整個過程。負責溝通需求,創建客戶端開發團隊,肯定系統架構風格和技術實現方案。因爲項目開發資源(好比時間、人力)緊張,項目的業務邏輯複雜,項目組對業務並不熟悉,難以在一開始預估將全部需求開發完成的時間。所以,在開發模型選擇上,採用螺旋式增量開發。數據庫

     在開發技術的選擇上,因爲本公司以往開發中,客戶端都是使用微軟的開發技術,服務端使用的是Java。 因此這次的項目仍是採用微軟技術+java技術結合。瀏覽器

      整個系統部署共有12臺服務器:四臺前置機用於運行REST服務+前臺管理系統+MQ+報文生成;四臺Web服務器Linux + Weblogic 11, 分別運行後臺管理系統+MQ+報文處理;四臺數據庫服務器 Linux + Oracle 12C;通過試運行,於10月份投入正式使用。目前系統情況良好,經運行評估,實現了所有必須功能,性能、安全性等質量均達到了原定設計要求。目前系統正在根據業務需求,作二次開發中。緩存

 

快速迭代開發、快速試錯安全

 

      此次咱們對客戶端的開發採用了Scrum敏捷開發流程——兩週一次迭代,每兩週發佈一個版本。咱們稱之爲小步快進」——用戶需求拆分,分階段實現,先讓用戶看到咱們的工做在不斷的推動。比較一下傳統的軟件開發模式:先制定一份詳盡冗長的詳細設計文檔、項目任務計劃,而後是少則12個月,多則是56個月甚至更久的開發週期,再加上一個較長的穩按期來修復足夠多的bug,而後再給用戶佈署。性能優化

      那麼如何快速試錯呢?這就要須要靠數聽說話了!網站是能夠很方便地收集到相關數據:用戶在網站上停留了多久,點了什麼網頁,在網頁上點了什麼按鈕,用戶使用的是什麼瀏覽器,同時有多少人在線,訪問的峯值出如今什麼時間段,等等。這次咱們在客戶端的一些主要操做都是要調用服務端REST接口進行操做的,咱們在服務端加入了一些收集信息的代碼,同時在客戶端中也加入了相似的收集信息的代碼,不斷的收集咱們開發的客戶端軟件中出現的BUG讓咱們對客戶端軟件的性能以及用戶行爲了如指掌。咱們就能知道用戶使用客戶端時哪些查詢比較慢,哪些操做是不合理的須要改進等信息。每次咱們作了一些改進或是增長了新功能以後,咱們都會先在小範圍內給用戶更新,而後在後臺觀察各類統計數據,同時也會派人去用戶那裏收集用戶的使用反饋。以此來幫助咱們決定是否應該繼續完善這個功能。服務器

如何解決版本碎片化問題?

       你們若是有過客戶端軟件運維的經歷,那麼確定會知道客戶端軟件到了用戶那裏,版本控制就是一個很是麻煩的事情了,在用戶那裏會有不少版本,這個用戶的版本多是2.1,那個用戶的版本多是2.2。若是版本更新比較頻繁的話,特別是項目進行運維初期,咱們每兩週就對外發佈一個版本,那麼用戶那裏的版本就更加不可控了。此次咱們在客戶端中加入了強制更新機制,一旦在服務器端設置了這個參數以後,就可經過軟件自帶的升級機制把最新版本的客戶端送到用戶手上。

      在功能實現方面,咱們時刻保持着一種意識:儘可能不把業務邏輯在客戶端裏寫死。不然的話,一旦業務邏輯有變,咱們必須修改客戶端的代碼,而後再作強制升級,一來週期比較長,二來萬一有什麼BUG就會影響用戶使用,就必須不得不當即再次更新一個版本,同時通知用戶更新,結果就比較被動了。舉一個用戶提交數據的例子吧。在客戶端,當用戶對單證數據進行了變動,提交數據的時候,要判斷一下是否有變動?具體的業務邏輯是:若是用戶對當前單證的數據進行了修改,則保存數據,調用保存接口;若是用戶對當前單證數據沒有作變動,則不用保存到數據庫,同時給出提示。若是是以往的CS架構,這樣作多少也會有點問題,由於存在併發的問題,更況且是訪問的是雲端數據。一些經驗欠缺的開發人員 會把上述邏輯直接實如今客戶端軟件裏。遺憾的是,這樣作沒法解決併發的問題,併發狀況下那會死的很慘的!更靈活的實現方式應該是客戶端只要把用戶的單證數據作爲參數傳給保存接口,而具體的業務邏輯實現則由服務器端來實現。

    固然,上面只是一個很小的例子。爲了在客戶端裏得到足夠的靈活性(不經過發佈新版本就能知足業務需求),咱們給不少功能加上了雲端配置。只要咱們發現某些功能的用戶使用上有問題,好比查詢超時了,咱們就能夠隨時均可以調整控制參數,甚至能夠控制用戶每分鐘的請求數。咱們始終牢記,咱們在作的不是一個單純的、孤立的客戶端軟件——咱們提供的是一種互聯網服務,咱們提供的是雲端功能。 

   

爲何採用REST作爲數據訪問接口

     咱們採用REST服務方式來實現客戶端與雲端的交互,是由於考慮到項目開發的兩個因素:簡單和靈活。

      REST (Representation State Transfer) 描述了一個架構樣式的網絡系統,好比 web 應用程序。它首次出如今 2000 年 Roy Fielding 的博士論文中,他是 HTTP 規範的主要編寫者之一。REST 指的是一組架構約束條件和原則。知足這些約束條件和原則的應用程序或設計就是 RESTful。

      使用REST作爲業務邏輯接口是由於,從客戶端到服務器的每一個請求都必須包含理解請求所必需的信息。若是服務器在請求之間的任什麼時候間點重啓,客戶端不會獲得通知。此外,無狀態請求能夠由任何可用服務器回答,這十分適合雲計算之類的環境。客戶端能夠緩存數據以改進性能。

      在服務器端,應用程序狀態和功能能夠分爲各類資源。資源是一個有趣的概念實體,它向客戶端公開。資源的例子有:應用程序對象、數據庫記錄、算法等等。每一個資源都使用 URI (Universal Resource Identifier) 獲得一個唯一的地址。客戶端使用的是標準的 HTTP協議進行資源訪問,同時還可使用標準的HTTP方法,好比 GET、PUT、POST 和 DELETE。

      REST的一個重要原則是系統分層,這表示組件沒法瞭解它與之交互的中間層之外的組件。經過將系統的某些功能限制在某一層,由此能夠限制整個系統的複雜性,促進了底層的獨立性。

      當 REST 架構的約束條件做爲一個總體應用時,將生成一個能夠擴展到大量客戶端的應用程序。它還下降了客戶端和服務器之間的交互延遲。統一界面簡化了整個系統架構,改進了子系統之間交互的可見性。REST 簡化了客戶端和服務器的實現。

REST架構風格能夠爲開發者帶來三方面的利益:

  • 簡單性

  採用REST架構風格,對於開發、測試、運維人員來講,都會更簡單。能夠充分利用大量HTTP服務器端和客戶端開發庫、功能測試/性能測試工具、HTTP緩存、HTTP代理服務器、防火牆。這些開發庫和基礎設施早已成爲了平常用品,不須要昂貴小型機、大型機等硬件,使用增長日常使用的便宜的PC服務器,就能解決大多數可伸縮性方面的問題。

  • 可伸縮性

  充分利用好通訊鏈各個位置的HTTP緩存組件,能夠帶來更好的可伸縮性。其實不少時候,在客戶端作性能優化,產生的效果不亞於僅僅在服務器端作性能優化,可是HTTP協議層面的緩存經常被一些資深的架構師徹底忽略掉。

  • 鬆耦合

  統一接口+超文本驅動,帶來了最大限度的鬆耦合。容許服務器端和客戶端程序在很大範圍內,相對獨立地進行開發,並行開發。對於設計面向企業內網的API來講, 鬆耦合並非一個很重要的設計關注點。可是對於設計面向互聯網的API來講,鬆耦合變成了一個必選項,不只在設計時應該關注,並且應該放在最優先位置。

     REST服務具備很是出色地靈活性,同時方便用瀏覽器和 firebug等工具進行測試。咱們在項目中,並無將REST服務單純視爲一串地址的響應,基於HTTP協議,能夠最大地利用HTTP協議的語義特性。如數據的增刪改查操做對應不一樣Http Method(Put/Delete/Update/Get)。用戶能夠用相同訪問URI,根據須要,經過在請求頭中設置不一樣的 Accept-Type,獲取不一樣形式的數據結果,好比JSON(用於Ajax)或XML(用於後臺)。

     REST服務請求因爲不須要構造SOAP消息,開銷更小。 REST服務能夠利用高速緩存控制頭,從而減小帶寬的需求,從而REST能夠改善響應時間和改進用戶體驗。
    REST的每一個請求都是獨立的。一旦被調用,服務器不保留任何會話,這樣就能夠更具響應性。經過減小事件後通信狀態的維護工做,提升了服務器的可擴展性。 

在此係統開發過程當中,也遇到了一些問題:

1、安全性方案。特別是指Restful Api的訪問控制方法。REST既能夠被服務器端調用又能被客戶端調用,因此一開始就要明確地區分用戶訪問權限和系統訪問權限,區分Web頁面權限和REST API接口權限。可是在開發過程當中常常會混爲一談,從此要增強設計階段這方面的文檔和評估工做。

2、服務接口規範性。REST服務基於URI地址訪問,URI不只僅指明瞭被標識資源所在的位置,並且經過這個URI能夠直接獲取目標資源。REST服務接口的每一個操做都基於一個URI模板。在實際業務中,功能相似的操做被作成多個重載,隨之重載的增多,URI模板如何約定,如何擴展便成爲一個規範性問題。開始時,對此未予以足夠重視,REST服務接口由不一樣的人來進行開發,以至於一些REST服務接口定義上產生了混亂,影響了理解和正確使用。後來,又額外花費時間定義了操做URI的規範。經過這次的項目讓我知道了應該從設計時就應該全面考慮URI模板的語義擴展方式。

3、因爲服務端使用的是Spring與Hibernate這些JAVA的第三方組件,因此形成了一個問題,效率問題,一旦數據量稍微大一點,就會出現問題。我仔細研究了一下服務端工程師寫的JAVA程序,發現原來他們的寫法很成問題,我不知道這是否是JAVA使用Hibernate就是這樣使用的。我舉個例子:

表結構與要顯示的結果以下圖。

 

通常咱們,應該使用SQL語句,使用SQL的(inner join 、left join、right join)三種中的一種,把三個表關聯起來,一條SQL語句,把結果查詢出來。

服務端的實際寫法倒是,先查詢了「單證實細表」,而後循環去查詢貨物信息表,獲得品名,查詢企業信息表,獲得名稱。也就是說,由一條SQL語句,變成了

明細數量*2條SQL語句,最後,形成了很大的性能瓶頸。服務端的負責人最後爲了達到性能上的指標,使用了內存數據庫,來解決這個問題。

相關文章
相關標籤/搜索