軟體的累加式更新是什嗎?

來源:互聯網
上載者:User

軟體的累加式更新

因為轉戰C#了,之前很多東西都丟了。現在從頭開始弄基礎服務,首先第一個就是用戶端的自動更新。之前簡單搜了一下相關功能的實現。有一個文章我沒有看懂,另一片文章裡邊說的應該是提交本機資料,然後計算差異化包,讓伺服器返回差異化資料包。當然這樣不是不行。肯定是可行的,但是對於伺服器來說這部分工作可能就有點麻煩了。因為你得讓伺服器有這個計算能力。參考Cocos2dx 3.9的Lua累加式更新模組,簡單做了一個基礎架構模型出來。

原來怎麼做

覆蓋安裝

這個其實很簡單,就是重新下載一個完整的安裝包,然後重新安裝一遍,不管原來存不存在內容,如果原來存在內容那麼久替換掉,如果原來不存在內容那麼就添加上新內容就是了。其實這個說起來很簡單,但是可能會存在一些問題。

- 流量問題 可能現在看來這個問題並不是多麼大的問題,因為現在頻寬已經非常寬了。100M的內容按照10Mpbs的頻寬來算,也就一分多鐘就能下載完了。- 渣子問題 這種覆蓋安裝一般會存在一個渣子的問題。比如說,我在安裝目錄裡邊產生了一個不在後續安裝包的檔案,那麼這個檔案就沒有辦法被清理掉。這就可能很尷尬了,比如說你的項目依賴系統提供的一個Dll,如果你的目錄中直接存在這個Dll那麼就會優先使用你對應目錄中的Dll(如果我沒記錯應該是這樣),如果是我作為攻擊者的話,我很有可能會給你放一個我種下病毒的Dll。這就很尷尬了

打補丁

這個原理也比較簡單,其實就是我們都覺得完整安裝太費勁了,那麼我的軟體又需要比較頻繁的更新,比如說某些桌遊可能過個節日要上節日相關的功能,這樣就可以添加新的Dll然後又不能出一個一個的完整安裝包。那麼我可以在完整安裝包的基礎上打補丁嘛。比如說,我出了版本1.0,過了十天半個月過端午了,我出個龍舟皮膚一類的,那我就可以直接在1.0的基礎上打個龍舟補丁,這樣他就變成了最新的用戶端1.1。如果將來要上別的功能了我就在1.1的基礎上打個補丁,讓用戶端變成1.2。不過這樣也會有他的問題。

- 順序安裝 在安裝的過程中只能以此遞增式安裝,我只能1.0 => 1.1 => 1.2;不能1.0 =》 1.2。因為中間是沒有對應的補丁的。- 流量問題 其實這種解決方案可能會帶來一些問題,比如說,現在端午節,我需要把房子裝飾成龍舟的樣式;然後五一勞動節,我又需要把房子裝修成五一勞動節的樣子。那麼都是關於房子的皮膚,我是沒有辦法都保留的,因為來年的時候肯定就不能這麼裝修了,因為過時了太Low了。那麼關於這部分的內容,如果你想一點一點的升級上來對於最後的版本來說是沒用的,你佔用的流量一點用都沒有。太尷尬了。- 維護的複雜度 因為你不能直接出了一個1.0之後全都是使用補丁,如果當你的版本號碼遞增到一定程度以後,補丁的大小可能遠遠超過了你重新去下載一個最新的用戶端的大小。所以只能通過時間也好(比如半年或者一個季度)通過意義(比如說大版本號碼 2.0 3.0)來產生一個完整的用戶端。這樣使用者在下載的時候就可以找一個最近的完整的用戶端版本號碼。然後再打補丁的方式來獲得最新的用戶端,不過這種維護的複雜度應該也不小。

理理我們最核心的需求吧

其實我們的需求很簡單,擷取最新的用戶端。然後附加要求就是要省流量、下載方便、服務端發布方便。

省流量

其實說到省流量,就是能用本地的就直接使用本地。本地實在是沒有的檔案,那麼就從網路上下載。這樣基本上就做到了省流量的效果。

下載方便

不需要做太多的操作,當然這個很多軟體都做到了這一點。上文中提到的其實也可以做到自動化,比如說,完整安裝的那麼我就直接下載最新的完整安裝包就好了,如果是打補丁的這種,那麼就下載最新的完整安裝包以及後邊的補丁就好了。其實這個真的要做,對使用者來說應該是沒有感覺得。都一樣,不過對於程式員來說。可能面臨的開發就不太一樣了。

服務端發布方便

其實這個完全是針對於程式員的了,一般來說,如果這個事情可以程式來自動完成那麼就肯定交給程式了。比如說完整晚裝包的這種,肯定能夠做到自動打包。打補丁的這種,無非也就是根據上一個版本產生一個補丁。或者再產生一個完整安裝包。上傳到合適的檔案伺服器就好了。其實打補丁也好,完整安裝包也好,都有一個顯著的優勢就是可以很方便的放到多個伺服器上來進行檔案的負載平衡。

那麼我們該怎麼做

在考慮這個問題的時候,我想到了之前接觸的Cocos2dx 3.9 Lua 自動更新模組,他是這麼做,通過一個設定檔,來說明最新的用戶端中都包含了那些檔案,這些檔案的MD5值是什麼,然後網路路徑是什麼。這樣用戶端拿到這個配置清單的時候,就可以輕鬆的判斷本地的那些檔案是可以繼續用的。那些檔案是過時了的,這樣用戶端通過配置心中的網路路徑位置擷取最新的對應檔案就好了嘛。不過那也是很久之前的事情了,不然,我就不需要自己重新規划了。直接抄一份代碼就好了嘛。還是自己整理一套吧。這樣來的更徹底一些,想改什麼就改什麼。

檔案的格式

{"VersionsCheckCode": "XC09VU4QCRD43LRF01BYOD26D45DWEEKX5KECUKIA7Q4160FKAWQBHXTKE63Z148","TimeStamp": 1496649771,"ServerUrl": "http://or2dwwrsz.bkt.clouddn.com","FileInfos": [{"FilePath": "JumpKick.HttpLib\\packages\\Moq.4.2.1409.1722\\lib\\net40\\Moq.xml","FileMD5": "c7e9c70a19b84f31e51eb65f4ee38803","FileUrl": "LV4ZBB_c7e9c70a19b84f31e51eb65f4ee38803"},{"FilePath": "JumpKick.HttpLib\\packages\\Moq.4.2.1409.1722\\lib\\sl4\\Moq.Silverlight.dll","FileMD5": "0ee20e7ccba7d6667c48efebe41503ff","FileUrl": "X057QT_0ee20e7ccba7d6667c48efebe41503ff"},{"FilePath": "JumpKick.HttpLib\\packages\\Moq.4.2.1409.1722\\lib\\sl4\\Moq.Silverlight.xml","FileMD5": "c25417228db2dd820f45e93112e8596c","FileUrl": "S0LO6G_c25417228db2dd820f45e93112e8596c"}]}

簡單的說明

  • VersionsCheckCode:當前的版本檔案校正資訊。

  • TimeStamp:做這個檔案的的時間戳記

  • ServerUrl:伺服器的地址,主要是用來跟後續的檔案進行拼接來用的

  • FileInfos:對應的檔案資訊列表

  • FileInfos[?]:FilePath:本地檔案路徑,從網路下載之後對應的本地地址

  • FileInfos[?]:FileMD5:這個檔案的MD5值,用來判斷原始的對應位置的檔案是否與網路中的檔案相同

  • FileInfos[?]:FileUrl:這個檔案在網路中存在的位置,當然這個是沒有前邊的URL路徑的是ServerUrl後邊的內容

項目地址

其實嘛整個項目最複雜的地方時這個更新的想法與這個檔案的制定。剩下的內容其實就比較簡單了,就是具體的代碼的實現了。代碼方便我就懶得講了,直接把項目的地址扔上來了事。

用戶端


服務端


這樣做的好處

省流量、跟其他軟體結合方便、伺服器發布方便。省流量這個上邊提到了我就說了。

跟其他軟體結合方便

其實很容易理解,就是這個軟體跟被更新的軟體一毛錢關係沒有。所以我可以直接跑起來就行了,不需要關係具體被更新的軟體是怎麼搞得。最多採用這個的項目。重新改一下我們這邊的UI就行了。

伺服器發布方便

其實最麻煩的事情就是伺服器這邊。需要產生這個設定檔,我這邊伺服器端其實並沒有在運行指的就是產生這個檔案的工具。我可以指定一個目錄。然後產生這個檔案,將對應目錄的所有檔案匯出到一個輸出目錄。不過對於很多CDN不支援多級目錄(比如七牛),所以我將所有的檔案都換掉了名字,讓他們盡量的不重複,程式可讀就行了。

怎麼用

首先使用我寫好的服務端產生對應的設定檔和改名檔案。

產生的目錄結構是這樣色的,設定檔放到一個固定的目錄裡邊去。UpLoad檔案夾上傳到某一個檔案伺服器上,這裡我是用的七牛雲

然後把UpLoad目錄中的檔案全都上傳上來

上傳完了就是這個樣子的。

致辭伺服器就部署好了,等有了新版本重複一遍這個操作就行。其實上傳伺服器的這部分工作可以整合到服務端中。上傳內容就好了嘛,其實很簡單的。當然了,這個我懶。之前也沒有研究七牛的SDK這個可以作為一個功能上的擴充,反正項目我已經開源了,感興趣的人可以自己擴充這部分功能。好吧我們繼續來說用戶端怎麼弄吧。

怎麼用用戶端呢

            AutoUpdateHelper helper = new AutoUpdateHelper();            helper.WebXmlUrl = "http://7xs9hw.com1.z0.glb.clouddn.com/VersionInfo.json";            helper.ConfigXmlPath = "SynchronizeVersions.xml";            helper.TempXmlPath = "SynchronizeVersions_Temp.xml";            helper.FilePath = "Client";            helper.CallBack = obj =>            {                if (obj is Dictionary<UpdateDataType, object>)                {                    var dic = obj as Dictionary<UpdateDataType, object>;                    foreach (var item in dic)                    {                        if (Name2Action.ContainsKey(item.Key))                            Name2Action[item.Key](item.Value);                    }                }            };            try            {                helper.Start();            }            catch (Exception ex)            {                MessageBox.Show(ex.Message);            }

其實就是一個簡單的設定網址跟設定檔。其實呢這個地方應該吧配置也放到設定檔裡邊去,為什麼沒放呢?因為我懶,哈哈哈。

用戶端的運行圖

用戶端跑完了就關了,其實應該是跑完了運行某一個具體的檔案,然後自動更新的邏輯就完成了,這部分我會之後繼續完善。

不妥之處

這麼樣處理其實下載會變得很靈活。但是也會帶來其他的問題。比如之前提到的打包的問題。因為伺服器只是一個檔案伺服器,所以伺服器並沒有計算出差異包的能力,所以所有的檔案都是一個一個的下載的,這樣就會出現很多小檔案的下載。這樣的下載其實是比較蛋疼的。這是設計上的坑。為了靈活只能妥協了。

實現的不妥之處

其實到目前為止我只是實現了最基礎的功能。甚至還不全,比如之後的檔案啟動,不過大體的架構已經搭建起來了。至於後邊有很多實現不是很合理的地方,我先簡單列一列,方便之後維護。

  • 下載失敗重試不存在

  • 下載數量的限制不存在(現在是有多少下載多少,很多同時下載可能會存在逾時的問題。)

  • 完成了之後沒有啟動對應的檔案

  • 現在沒有快速啟動的功能(現在每次啟動都需要重新校正所有檔案,其實可以避免這個問題的。)

後話

雖然這個項目只是一個並不完善的架構。但是這種更新方式應該會讓更新變得更有意思。讓我們一塊來完善這個架構吧。比較希望做一個成功的開源項目,不忘初心。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.