原先作服務器程序, 都是部署在xx雲上, 也沒理解雲是個啥, 不就是個服務器(虛擬機)租賃商嗎? 好吧, 其實這個是IaaS, 而接下來要學習的ServiceFabric(如下簡稱SF)是PaaS. 前端
首先SF和Orleans相似, 都是基於actor模型, 而後編程方式也很像, 大概就是定義公開接口, 而後後端服務實現接口, 前端調用接口這樣.node
這裏說的先後端着實不夠嚴謹, 實際上是指服務器上的先後端, 前端是服務的前端並不是服務器對應的客戶端. 若是有web(asp.net)或是其餘無狀態相似網關的服務在前面接收客戶端消息並調用服務接口, 那就是服務的使用者也就是這裏語義上的前端了(語死早). web
服務根據其是否有狀態分爲: 無狀態服務和有狀態服務. 編程
無狀態服務很容易理解, 一個helloword, echo示例, 計算器示例, 只處理用戶輸入自己不保存狀態, 那就是無狀態服務. 無狀態服務的擴展很簡單, 增長節點既是.後端
然而如計算器這種服務, 若是須要保存一些數據等待用戶下次使用, 那就須要變成有狀態服務了. 固然也能夠引入第三方存儲來規避狀態, 繼續使用無狀態服務(僞), 由於此時的狀態已經託付給第三方存儲了. 服務器
固然上述作法使得結構又複雜起來了, 也可能形成額外的調用等待, 不如使用有狀態服務. 多線程
而服務有了狀態, 那又涉及到狀態的落地, 容災, 同步, 鎖...這些東西煩擾了我整個編程生涯. 聽說能夠在SF中找到答案. app
官網的文檔入門案例太複雜了, 引入了angular等加高門檻攪腦汁的東西, 而我今天不打算學太多, 先作一個helloworld消化下. 最後的功能是能經過一個console程序調用服務接口, 而後接收返回的字符串helloworld. asp.net
一 安裝必須工具less
毫無疑問, visual studio是必須的, 我選擇目前最新的vs2017社區免費版.
而後安裝sdk
二 建立無狀態服務
打開vs->新建項目->Visual C#->cloud->Serivce Fabric Application, 名稱爲HelloWorldApplication
選擇無狀態服務(stateless service), 名稱爲HelloWorldService
三 定義接口
建立接口, IHelloWorldService.cs
定義方法Task SayHello(string msg);
爲了能遠程調用, 使用nuget安裝包Microsoft.ServiceFabric.Services.Remoting
此時打開"編輯項目文件csproj", 會看到以下的包引用
<ItemGroup> <PackageReference Include="Microsoft.ServiceFabric.Services" Version="3.1.301" /> <PackageReference Include="Microsoft.ServiceFabric.Services.Remoting" Version="3.1.301" /> </ItemGroup>
編輯IHelloWorldService, 繼承自IService(在剛纔安裝的remoting包中, 須要添加引用)
最後以下
using Microsoft.ServiceFabric.Services.Remoting; using System; using System.Collections.Generic; using System.Text; using System.Threading.Tasks; namespace HelloWorldService { public interface IHelloWorldService : IService { Task<string> SayHello(string msg); } }
這裏的返回值是Task類型. 老實說我初次接觸SF並不清楚其是否和Orleans同樣將消息接收和處理異步開來, 同時經過task的同步調用使服務處理不用擔憂多線程問題. 但我猜自家產品沒有理由不採用一樣先進的方式吧?
四 實現接口
編輯HelloWorldService.cs文件, 繼承IHelloWorldService接口, 實現SayHello方法.
刪除原先存在的StartAsync方法. (Azure Cloud Service方式的延續?)
最後代碼以下
internal sealed class HelloWorldService : StatelessService, IHelloWorldService { public HelloWorldService(StatelessServiceContext context) : base(context) { } public Task<string> SayHello(string msg) { return Task.FromResult($"hello world! {msg}"); }/// <summary> /// 可選擇性地替代以建立偵聽器(如 TCP、HTTP),從而使此服務副本能夠處理客戶端或用戶請求。 /// </summary> /// <returns>偵聽器集合。</returns> protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners() { //return new ServiceInstanceListener[0]; return this.CreateServiceRemotingInstanceListeners(); } }
服務到此就建立完畢了.
五 發佈到本地集羣
右鍵HelloWorldApplication項目, 而後發佈, 選擇LocalNode配置, 而後發佈.
經歷漫長的等待以後, 右下角出現了一個SF的橘黃色圖標, 右鍵Manage local cluster, 能夠查看和管理已經發布的applicaiton, 以及具體運行的node.
注意, 忘記說了, vs須要用管理員打開...
六 接下來建立客戶端.
新建項目, console application, 任意, 我選擇.net Core Console Application.
nuget獲取包
<ItemGroup> <PackageReference Include="Microsoft.ServiceFabric.Services" Version="3.1.301" /> <PackageReference Include="Microsoft.ServiceFabric.Services.Remoting" Version="3.1.301" /> </ItemGroup>
添加現有項, 將剛纔的IHelloWorldService.cs添加進去(注意能夠選擇添加連接文件保持同步)
保持接口同步的還有一個方法是另建一個類庫項目, 引用同一個類庫(如同Orleans示例中同樣)
修改Program中的main函數
static void Main(string[] args) {
var client = ServiceProxy.Create<IHelloWorldService>(new Uri("fabric:/HelloWorldApplication/HelloWorldService"));
string msg = Console.ReadLine();
var result = client.SayHello(msg).Result; Console.WriteLine(result); Console.ReadKey(); }
F5運行客戶端, 查看結果.
同上示例, 還能夠拓展爲計算器服務.
糾錯: 上面說接口返回是Task多是由於內部維持序列同步調用的關係, 實際上是錯誤的. SF還有actor模型, 才和Orleans同樣, 普通的有狀態服務仍會異步調用.