C語言程式設計第五版第九章習題答案譚浩強課後答案
關於這個翻譯檔案的一些說明:
之前逛部落格園的時候,看見有個園友在自己的部落格上介紹Orleans. 覺得Orleans 是個好東西. 當時心想:如果後面有業務需要的時候可以用用Orleans框架.
當真的有業務需要的時候, 我驚奇的發現很多介紹Orleans框架的人,都只是寫了一個入門的示例. 關於Orleans框架的中文資料似乎很少.
直到翻到csdn部落格中有個叫閆輝的人有一個系列部落格叫《Orleans 2.0 官方檔案》, 我非常開心的點了進去,然後我就悲劇的發現這檔案幾乎是機器翻譯, 當然也不是沒有收穫. 受他的啟發,我決定自己來翻譯Orleans框架的檔案. 當然我的英文還停留在小學的水準, 因此我也是藉助機器翻譯.所不同的是我會盡量去理解檔案的內容, 在我理解的基礎上進行翻譯.以期能幫到需要了解Orleans框架的園友.
因此翻譯的準確度我理解的深淺直接掛鉤. 所以如果英文水準高的園友還請移步原版檔案( http://dotnet.github.io/orleans/Documentation/index.html) 去看原版檔案. 翻譯有誤的地方也歡迎園友能夠指正,在此不勝感激.
概述
Orleans是一個跨平臺框架,用於構建強大、可擴充套件的分散式應用程式.
Orleans基於 .NET 的開發人員工作效率,並將其引入分散式應用程式(如雲服務)的世界。奧爾良從單個本地伺服器擴充套件到雲中全球分散式、高可用的應用程式。
Orleans採用熟悉的概念,如物件、介面、async/awai和try/catch並擴充套件至多伺服器環境。因此,它可以幫助開發人員將單伺服器應用程式向構建彈性、可擴充套件雲服務和其他分散式應用程式擴充套件。因此,奧爾良通常被稱為"分散式 .NET"。
它由 Microsoft Research 建立,並引入了虛參與者(Virtual Actor)模型,作為為雲時代構建新一代分散式系統的新方法。Orleans的核心貢獻是其程式設計模型,它馴服了高度並行分散式系統原有的複雜性,同時也不要求開發人員有高超的開發能力.
Grains(顆粒)
所有通過Orleans建立的應用程式的基本單位都是Grains. 也可以理解為任何Orleans程式都是由一個一個的Grain組成的. Grain是一個由使用者自定義標識,行為和狀態組成的實體. 標識是使用者自定義的鍵(Key),其他應用程式或Grain通過鍵來呼叫該Grain. Grains是通過強型別介面(協議)與其他Grains或客戶端進行通訊. Graint是實現一個或多個這些介面的例項.
Grains 可以在任何儲存系統中儲存揮發性、永續性狀態, 因此,Grains隱式地對應用程式狀態進行分割槽,從而實現自動可伸縮性並簡化故障恢復。當Grains處於活動狀態時,Grains狀態儲存在記憶體中,這樣可以降低延遲和資料儲存的負載.
Grains的例項化工作由Orleans runtime根據需要自動實現.一段時間不用的Grains將自動從記憶體中移除以釋放資源,這主要是因為Orleans框架允許通過唯一的標識去呼叫grains(不論這些Grains是否已經載入到記憶體中去); 同時支援故障自動恢復,因為呼叫方不需要知道Grains有沒有例項化,在哪個伺服器上例項化. Grains的生命週期由Orleans執行時進行管理——Orleans執行時負責啟用/停用Grains,並會根據需要放置/定位Grains. 開發人員在呼叫它們的時候就好像它們在記憶體中一樣.
總之, Grains的標識穩定性,有狀態性,生命週期受Orleans執行時的管理性,使得基於Orleans框架開發的程式具有可伸縮性,可靠性以及較高效能,同時也不需要開發人員為了系統支援分散式而編寫複雜的程式碼.
示例:物聯網後臺程式
思考一下這樣一個物聯網系統的後臺程式:程式允許裝置接入,然後處理這些資料:過濾、聚合、彙總等;還要支援向裝置傳送命令. 在Orleans框架下,我們很自然的想到用Grains來對每個裝置進行建模. 每一個Grain就像想對應的物理裝置的一個雙胞胎兄弟一樣. Grains將裝置最新的資料存放在記憶體中,以便更快速的查詢和處理這些資料,而不需要與物理裝置進行直接通訊. 通過分析裝置時序資料, Grains可以檢測裝置的狀態或條件的變化(例如測量值超過某個閾值)來觸發某個特定的動作.
下面是一個簡單恆溫器的建模:
public interface IThermostat : IGrainWithStringKey
{
Task<List<Command>> OnUpdate(ThermostatStatus update);
}
可以通過呼叫OnUpdate方法把前端的事件傳送給相應的Grain, Grain再根據需要有選擇的把命令反饋給物理裝置.
var thermostat = client.GetGrain<IThermostat>(id);
return await thermostat.OnUpdate(update);
相同的Grain可以單獨實現一個介面,用於控制系統與之互動:
public interface IThermostatControl : IGrainWithStringKey
{
Task<ThermostatStatus> GetStatus();
Task UpdateConfiguration(ThermostatConfiguration config);
}
這兩個介面(Ithermostat和IThermostatControl)由一個類來實現:
public
class
ThermostatGrain : Grain, IThermostat, IThermostatControl
{
private ThermostatStatus _status;
private List<Command> _commands;
public Task<List<Command>> OnUpdate(ThermostatStatus status)
{
_status = status;
var result = _commands;
_commands = new List<Command>();
return Task.FromResult(result);
}
public Task<ThermostatStatus> GetStatus() => Task.FromResult(_status);
public Task UpdateConfiguration(ThermostatConfiguration config)
{
_commands.Add(new ConfigUpdateCommand(config));
return Task.CompletedTask;
}
}
以上的Grain類不儲存其狀態,後續的檔案中提供了更詳細的狀態持久化的示例.
Oreans執行時
Oreans執行時實現了Oreans程式的程式設計模型. 執行時的主要元件是silo, silo負責託管Grain. 通常, 一組silo是以叢集方式執行的, 並以此來實現可伸縮性和容錯性. 當這些silo作為叢集方式執行的時候,silo之間彼此協調分配工作, 檢測故障以及故障恢復. Orleans執行時使得叢集中的Grian能夠像在一個程式中一樣彼此相互通訊.
除了核心程式設計模型之外,silo還為grains提供一組執行時服務,如計時器、提醒(持久計時器)、永續性、事務、流等. 相關的詳細資訊, 請參閱下面功能部分.
Web以及其他外部客戶端通過客戶端類庫呼叫叢集中的Grains,客戶端類庫將自動管理網路通訊. 當然還有更簡單的方式: 客戶端與Silo託管到共同的程式中去.
Orleans 相容 .NET Standard 2.0 及以上版本. 能夠在裝有.NET Framework(只支援windows) 或.NET Core 的 Windows、Linux 和 macOS上執行.
功能
持久化
Orleans 提供了一個簡單的持久化模型, 該模型可以確保處理請求之前Grain是可用 狀態的, 並保持一致性. Grain 可以有多個命名持久化資料物件. 例如:把使用者配置命名為"Profile";把庫存命名為"Inventory"來做持久化. 而這些持久化物件可以儲存在任何的儲存系統中. 例如:把使用者配置(Profile)儲存到資料庫A, 而庫存(Inventory)則儲存到資料B. 當Grain執行時,Profile和Invertory都將被載入到記憶體中去, 這樣,在處理裡讀取請求的時候就不用再去訪問儲存器. 當Grain的狀態被更新時,呼叫 state.WriteStateAsync() 就可以確保狀態的永續性和一致性. 更多詳細資訊,請參閱Grain持久化的相關檔案.
分散式ACID事物
除了上述簡單的持久化模型外,Grain還支援有狀態事務: 可以把多個Grain放到同一個ACID事務中去,無論這些Grain的狀態儲存在哪裡. Orleans的事務是分散的分散式事務(沒有中央事務管理器或事物協調器),並且支援序列化隔離. 更多Orleans 事務的詳細資訊, 請參閱後續檔案和微軟Resarch技術報告( https://www.microsoft.com/en-us/research/publication/transactions-distributed-actors-cloud-2/).
流
流(或者說流計算)可以幫助開發者近乎實時地去處理連續資料. 流是託管在Orleans框架中的: Grain或客戶端釋出或訂閱流之前,無需建立或註冊. 這樣使得流的產生者、消費者、基礎框架相互之間進行極大險度的解耦. 流處理的可靠性: Grains可以儲存檢查點(遊標). 並可以在啟用期間或者之後的任何時間重置已存在的檢查點. 流支援向消費者傳輸批量訊息,並以此提高傳輸效率和恢復效能. 流由排隊服務(如:Azure事件匯流排、Amazon Kinesis等)提供支援, 任意多個流可以多路複用到較少的佇列上,並在整個叢集中均衡的處理這些資料.
Timers & Reminders(此處本來想翻譯提醒的,但感覺怪怪的,索性就不翻譯了)
Reminders 和Timer都是Grain的一種排程機制. Reminder主要用於在未來的某個時間點(就算Grain當時沒有啟用)完成指定的操作(針對Grain被持久化到儲存器的情況); 而Timer則是用於處理非可靠的頻繁出現的事件(例如某些不重要的通知). 更多Timer 和 Reminders 請參閱後續檔案.
靈活的Grain放置
當Orleans啟用一個Grain時,Orleans執行時決定在哪個伺服器(silo)上進行啟用, 這個過程被成為Grain放置. Orleans的放置過程是完全可以靈活配置的, 開發人員可以從一組開箱即用的放置策略中進行選擇,可選的選項有:隨機,本地優先,基於負載以及自定義邏輯. 這使得Grain的放置非常具有靈活性, 例如: 可以將Grain 放置在靠近需要操作的資源上或者跟它有通訊往來的其他Grain伺服器上.
Grain 版本控制和異構叢集
應用程式的程式碼都會隨著時間或者業務的發展而變化, 如何將這些變化安全快捷地升級到生產系統(這裡應該是不停機更新)會面臨很大的挑戰, 特別是在有狀態的系統中. Grain 介面支援版本控制. 叢集中維護了一個對映表, 分別記錄了在叢集中有哪些Grain 可以被哪些Silo所使用, 以及實現的版本. Orleans執行時會結合這個記錄資訊與Grain放置策略配合使用,以便客戶端呼叫的時候Orleans執行時決定路由到相對應的Grain上. Orleans除了支援Grain版本控制外,還支援異構叢集. 不同的Silo可以有不同Grain實現集. 更多相關資訊,請參閱 Grain版本控制相關檔案.
可伸縮性&容錯性
Orleans在設計的時候,就已經充分考慮了系統的可伸縮性. 當有一個新的Silo加入到叢集時,Orleans會根據需要去啟用它; 當某個Silo由於某個原因(系統規模縮減或節點故障)需要從叢集移除的時候,在當前Silo上的Grain會叢集的其他Silo上面重新啟用. Orleans叢集,最小可以縮小到單Silo服務. Orleans支援可伸縮性的同時也支援容錯性: Orleans叢集會自動檢測各個Silo是否故障,並能快速地從故障恢復.
處處執行
Orleans可以執行在任何支援.net core 或 .net Framework的系統上,包括Windows,Linux,macOS,並支援通過K8s部署到docker 等其他物理或虛擬主機上,以及像Azure一樣的共有云上的Paas服務.
無狀態工作者
Grain可以通過新增一個特殊的標記,使它與其它Grain之間沒有任何關聯狀態. 這樣就可以在多個Silo上同時啟用, 從而增加無狀態操作的並行性. 有關更多資訊,請參考無狀態工作者Grain的相關檔案.
Grain呼叫過濾器
Grain呼叫過濾器是指多個Grain之間的公共邏輯. Orleans支援傳入和傳出呼叫過濾器. 常見的過濾器用例有: 授權,日誌,遙測以及錯誤處理等.
請求上下文(Request Context)
元資料和其他資訊可以使用請求上下文(Request Context)在一些列的請求中傳遞. 請求上下文(Request Context)可以用來儲存分散式跟蹤資訊或其它使用者自定義的值.
開始
請參考入門教程.
編譯生成
在Windows系統可以通過執行 build.cmd 指令碼在本地生成Nuge包,然後從"/Artifacts/Release/"目錄引用所需的Nuget包。接下來就可以執行 test.cmd指令碼進行版本驗證測試,以及執行 testall.cmd 較本進行功能測試。
在Linux或Mac系統則通過執行 build.sh指令碼 或 執行命令 dotnet build ./OrleansCrossPlatform.sln 來生成Orleans。
官方編譯
最新的穩定的釋出在此處
夜間生成(即每天晚上進行生成)釋出到 https://dotnet.myget.org/gallery/orleans-ci 這些生成通過了所有的功能測試,但是沒有像釋出穩定版本或預釋出版本那樣進行徹底測試。
在專案中使用夜間生成的Nuget包
若要在專案中使用夜間生成,請使用以下任一方法新增 MyGet 源:
修改 .csproj 檔案,在專案檔案新增以下節點
<RestoreSources>
$(RestoreSources);
https://dotnet.myget.org/F/orleans-ci/api/v3/index.json;
</RestoreSources>
或者
在解決方案目錄下面,建立一個Nuget.Config檔案,並新增以下內容
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<clear />
<add
key="orleans-ci"
value="https://dotnet.myget.org/F/orleans-ci/api/v3/index.json" />
<add
key="nuget"
value="https://api.nuget.org/v3/index.json" />
</packageSources>
</configuration>
社群
- 在GitHub 的issue 或 Stack Overflow提題
- Gitter 聊天室
- Orleans 部落格
- 在Twwitter 上關注Orleans 賬戶 @msftorleans (沒有微博賬號,哈哈哈)
- OrleansContrib – 給Orleans設計各種外掛的社群專案。 包含 健康,設計模式,儲存提供程式等。
- 為希望改進Orleans而貢獻程式碼的開發人員提供的指南。
- 我們還鼓勵您通過GitHub來報告bug 或者在GitHub啟動一個新的技術討論.
授權
這個專案的授權協議是 MIT license.
快捷連結
Orleans 的起源
Orleans是在微軟研究部建立的,設計用於雲中。自 2011 年以來,它已被多個 Microsoft 產品組廣泛用於雲和內部辦公,其中最引人注目的是遊戲工作室,如 343 工業公司和聯盟,作為Halo 4和5、Gears of War 4背後的雲服務平臺。
2015年1月開源以來吸引了許多開發者,他們形成了.NET生態系統中最具活力的開源社群之一。在社群開發人員和微軟Orleans團隊的積極合作中,每天都會新增和改進特性。微軟研究院繼續與Orleans團隊合作,推出新的主要功能,如地理分佈、索引和分散式事務,這些功能正在推動最新技術的發展。對於許多.NET開發人員來說,Orleans已經成為構建分散式系統和雲服務的首選框架。