一、概述
木舟平臺分為微服務平臺和物聯網平臺, 上面幾篇都是介紹如何透過網路元件接入裝置,那麼此篇文章就細緻介紹下在木舟平臺下如何構建微服務。
木舟 (Kayak) 是什麼?
木舟(Kayak)是基於.NET6.0軟體環境下的surging微服務引擎進行開發的, 平臺包含了微服務和物聯網平臺。支援非同步和響應式程式設計開發,功能包含了物模型,裝置,產品,網路元件的統一管理和微服務平臺下的註冊中心,服務路由,模組,中間服務等管理。還有多協議適配(TCP,MQTT,UDP,CoAP,HTTP,Grpc,websocket,rtmp,httpflv,webservice,等),透過靈活多樣的配置適配能夠接入不同廠家不同協議等裝置。並且透過裝置告警,訊息通知,資料視覺化等功能。能夠讓你能快速建立起微服務物聯網平臺系統。
那麼下面就為大家介紹如何從建立元件、協議、裝置閘道器,裝置到裝置閘道器接入,再到裝置資料上報,把整個流程透過此篇文章進行闡述。
二、構建服務
建立服務介面,繼承IServiceKey,新增特性[ServiceBundle("api/{Service}/{Method}")] 配置routepath,程式碼如下:
[ServiceBundle("api/{Service}/{Method}")] public interface ITestApiService:IServiceKey { public Task<string> SayHello(string name); }
建立服務例項,繼承ProxyServiceBase, ITestApiService, ISingleInstance,如果只是業務處理只需繼承ProxyServiceBase,繼承ISingleInstance表示注入的生命週期 為單例模式,新增特性ModuleName標識一個服務多個例項,可以在呼叫的時候傳入ServiceKey
[ModuleName("Test")] public class TestService : ProxyServiceBase, ITestApiService, ISingleInstance { public Task<string> SayHello(string name) { return Task.FromResult($"{name} say:hello world"); } }
二、身份鑑權
webapi呼叫必然會牽涉到身份鑑權,使用者登入問題,而surging 已經整合了一套jwt驗證機制
然後在Stage配置節上配置ApiGetWay
"ApiGetWay": { "AccessTokenExpireTimeSpan": "240", "AuthorizationRoutePath": "api/sysuser/authentication",//身份鑑權服務的routepath "AuthorizationServiceKey": null, "TokenEndpointPath": "api/oauth2/token",//對映呼叫的routepath "CacheMode": "MemoryCache" //MemoryCache or gateway.Redis save token }
然後在介面方法上加上 [Authorization(AuthType = AuthorizationType.JWT)] 特性,服務呼叫就要進行身份鑑權
public interface IModuleService : IServiceKey { [Authorization(AuthType = AuthorizationType.JWT)] Task<ApiResult<bool>> Add(ModuleModel model); [Authorization(AuthType = AuthorizationType.JWT)] Task<ApiResult<bool>> Modify(ModuleModel model); [Authorization(AuthType = AuthorizationType.JWT)] Task<ApiResult<Page<ModuleModel>>> GetPageAsync(ModuleQuery query); }
三、快取攔截
surging 可以支援攔截快取,可以透過ServiceCacheIntercept特性進行配置,獲取快取可以透過CachingMethod.Get, 刪除快取可以透過CachingMethod.Remove,可以支援MemoryCache,Redis, 可以支援一,二級快取,
啟用EnableStageCache表示閘道器呼叫也可以走快取攔截(注:不支援模型引數)
[ServiceBundle("api/{Service}/{Method}")] public interface IProductService : IServiceKey { [Authorization(AuthType = AuthorizationType.JWT)] [ServiceCacheIntercept(CachingMethod.Remove, "GetProducts", CacheSectionType = "ddlCache", Mode = CacheTargetType.MemoryCache, EnableStageCache = true)] Task<ApiResult<bool>> Add(ProductModel model); [Authorization(AuthType = AuthorizationType.JWT)] Task<ApiResult<ProductModel>> GetProduct(int id); [Authorization(AuthType = AuthorizationType.JWT)] Task<ApiResult<Page<ProductModel>>> GetPageAsync(ProductQuery query); [Authorization(AuthType = AuthorizationType.JWT)] Task<ApiResult<List<ProductModel>>> GetProductByCondition(ProductQuery query); [Authorization(AuthType = AuthorizationType.JWT)] [ServiceCacheIntercept(CachingMethod.Remove, "GetProducts", CacheSectionType = "ddlCache", Mode = CacheTargetType.MemoryCache, EnableStageCache = true)] [ServiceLogIntercept] Task<ApiResult<bool>> DeleteById(List<int> ids); [Authorization(AuthType = AuthorizationType.JWT)] [ServiceCacheIntercept(CachingMethod.Remove, "GetProducts", CacheSectionType = "ddlCache", Mode = CacheTargetType.MemoryCache, EnableStageCache = true)] Task<ApiResult<bool>> Modify(ProductModel model); [Authorization(AuthType = AuthorizationType.JWT)] Task<ApiResult<bool>> Validate(ProductModel model); [Authorization(AuthType = AuthorizationType.JWT)] [ServiceCacheIntercept(CachingMethod.Remove, "GetProducts", CacheSectionType = "ddlCache", Mode = CacheTargetType.MemoryCache, EnableStageCache = true)] Task<ApiResult<bool>> Stop(List<int> ids); [Authorization(AuthType = AuthorizationType.JWT)] [ServiceCacheIntercept(CachingMethod.Remove, "GetProducts", CacheSectionType = "ddlCache", Mode = CacheTargetType.MemoryCache, EnableStageCache = true)] Task<ApiResult<bool>> Open(List<int> ids); [Authorization(AuthType = AuthorizationType.JWT)] [ServiceCacheIntercept(CachingMethod.Get, Key = "GetProducts", CacheSectionType = "ddlCache", EnableL2Cache = false, Mode = CacheTargetType.MemoryCache, Time = 480, EnableStageCache = true)] Task<ApiResult<List<ProductModel>>> GetProducts(); }
引數如果是非模型集合型別的引數,快取key 會取第一個引數值,如果是模型引數就需要新增CacheKey特性,程式碼如下:
public class PropertyThresholdQuery { [CacheKey(1)] public string PropertyCode { get; set; } [CacheKey(2)] public string ProductCode { get; set; } [CacheKey(3)] public string DeviceCode { get; set; } }
四、服務管理
1.平臺是支援服務路由管理,此項功能除了可以檢視後設資料,服務節點,服務規則外,還可以在權重輪詢負載演算法情況下,改變權重可以讓更多的訪問呼叫到此服務節點上,還有可以優雅的移除服務節點
選擇權重輪詢負載分流演算法,程式碼如下:
[ServiceBundle("api/{Service}/{Method}")] public interface ITestApiService:IServiceKey { // [Authorization(AuthType = AuthorizationType.JWT)] [Command(ShuntStrategy =AddressSelectorMode.RoundRobin)] public Task<string> SayHello(string name); }
以下是編輯權重
2. 熱部署中間服務
3. 黑白名單,新增IP地址或者IP段就能限制相關IP訪問
就比如訪問api/testapi,結果如下:
4.支援swagger API文件
五、分散式鏈路追蹤
支援skywalking 分散式鏈路追蹤
六 、構建釋出
1. 微服務釋出:
釋出微服務的時候,需要引用的是微服務,不要引用stage, 如下圖
2. 閘道器釋出, 引用服務介面和聚合服務(中間服務)模組,還有stage 模組
七、總結
以上是木舟平臺如何構建服務,平臺定於11月20日釋出1.0社群版本。也請大家到時候關注捧場。