更新時間:2021-10-29 10:13:04 來源:動力節點 瀏覽784次
有不少進行Java學習的小伙伴對微服務網關不是很了解,服務網關是在 ServiceStack 現有的基于消息的架構之上實現的,為開發松散耦合的模塊化服務架構開辟了令人興奮的新可能性。
新的IServiceGateway接口代表在支持同步和異步服務集成的形式化 API 中支持 ServiceStack 的不同調用約定所需的最小表面積:
public interface IServiceGateway
{
// Normal Request/Reply Services
TResponse Send<TResponse>(object requestDto);
// Auto Batched Request/Reply Requests
List<TResponse> SendAll<TResponse>(IEnumerable<object> requestDtos);
// OneWay Service
void Publish(object requestDto);
// Auto Batched OneWay Requests
void PublishAll(IEnumerable<object> requestDtos);
}
// Equivalent Async API's
public interface IServiceGatewayAsync
{
Task<TResponse> SendAsync<TResponse>(object requestDto,
CancellationToken token = default(CancellationToken));
Task<List<TResponse>> SendAllAsync<TResponse>(IEnumerable<object> requestDtos,
CancellationToken token = default(CancellationToken));
Task PublishAsync(object requestDto,
CancellationToken token = default(CancellationToken));
Task PublishAllAsync(IEnumerable<object> requestDtos,
CancellationToken token = default(CancellationToken));
}
上述 API 的最小集合對IServiceGateway實現者的負擔最小,而ServiceGatewayExtensions覆蓋了所有實現通用的便利 API,為請求 DTO 實現推薦IReturn和IReturnVoid接口標記提供了最好的 API 。擴展方法還為IServiceGateway那些也沒有實現 optional 的實現提供回退偽異步支持IServiceGatewayAsync,但將為那些實現的實現使用本機異步實現。
裸請求DTO的無注釋被發送作為POST與而是由標注請求DTO的替代動詞也支持HTTP動詞接口標記,其中請求DTO的含有IGet,IPut等使用類型化的動詞API,例如被發送:
[Route("/customers/{Id}")]
public class GetCustomer : IGet, IReturn<Customer>
{
public int Id { get; set ;}
}
var customer = client.Send(new GetCustomer { Id = 1 }); //GET /customers/1
//Equivalent to:
var customer = client.Get(new GetCustomer { Id = 1 });
要在內部執行現有的 ServiceStack 服務,您可以調用ExecuteRequest(requestDto)它,將請求 DTO 與當前一起傳遞IRequest到ServiceController.Execute()要執行的對象中。另一種方法是調用ResolveService<T>以解析服務的自動裝配實例,該實例注入了當前IRequest上下文,讓您可以直接調用服務實例上的方法。以下是使用這兩個 API 的示例:
public object Any(GetCustomerOrders request)
{
using (var orderService = base.ResolveService<OrderService>())
{
return new GetCustomerOrders {
Customer = (Customer)base.ExecuteRequest(new GetCustomer {Id=request.Id}),
Orders = orderService.Any(new QueryOrders { CustomerId = request.Id })
};
}
}
現在推薦的方法是使用所有服務、Razor 視圖、MVC ServiceStackController 類等中可用的IServiceGateway可訪問的方法base.Gateway。它的工作原理類似于ExecuteRequest()API(它現在取代),您可以僅使用填充的請求 DTO 調用服務,而是為實現推薦IReturn<T>或IReturnVoid標記的請求 DTO 生成理想的類型化 API :
public object Any(GetCustomerOrders request)
{
return new GetCustomerOrders {
Customer = Gateway.Send(new GetCustomer { Id = request.Id }),
Orders = Gateway.Send(new QueryOrders { CustomerId = request.Id })
};
}
或者,如果您更喜歡非阻塞版本,則可以使用 Async API:
public async Task<GetCustomerOrdersResponse> Any(GetCustomerOrders request)
{
return new GetCustomerOrdersResponse {
Customer = await Gateway.SendAsync(new GetCustomer { Id = request.Id }),
Orders = await Gateway.SendAsync(new QueryOrders { CustomerId = request.Id })
};
}
使 ServiceGateway 與眾不同的功能(除了提供更好的 API 之外)是該系統稍后可以將其客戶和訂單子系統拆分為不同的主機,并且這個確切的服務實現將繼續像以前一樣運行,盡管有一點點由于任何引入的進程外通信的開銷,速度較慢。
默認實現IServiceGateway使用InProcessServiceGateway,它將請求 DTO 委托給適當的ServiceController.Execute()或ServiceController.ExecuteAsync()方法來執行服務。一個明顯的區別是下游Service拋出的任何異常都會自動轉換為WebServiceException客戶端在外部調用Service時拋出的異常,因此無論是調用內部Service還是外部Service都無法區分異常,這開始觸及好處網關的...
無論您是在服務器上調用內部服務還是從客戶端調用遠程服務,ServiceGateway 都是相同的接口。它公開了一個理想的基于消息的 API,該 API最適合遠程服務集成,該API還支持自動批處理請求,用于將多個服務調用組合到一個請求中,盡可能減少延遲。
這些特性使得替換和自定義網關的行為變得容易,如下面的示例所示。支持的最簡單方案是將所有服務網關調用重定向到遠程 ServiceStack 實例,這可以通過針對IServiceGateway接口注冊任何 .NET 服務客戶端來完成,例如:
public override void Configure(Container container)
{
container.Register<IServiceGateway>(c => new JsonServiceClient(baseUrl));
}
您想要支持的更可能的場景是內部請求在進程內執行,外部請求調用各自的服務的混合。如果您的系統一分為二,這將成為一個簡單的檢查,以返回在此 ServiceStack 實例中定義的請求的本地 InProcess 網關,否則返回配置到備用主機的服務客戶端,例如:
public class CustomServiceGatewayFactory : ServiceGatewayFactoryBase
{
public override IServiceGateway GetGateway(Type requestType)
{
var isLocal = HostContext.Metadata.RequestTypes.Contains(requestType);
var gateway = isLocal
? (IServiceGateway)base.localGateway
: new JsonServiceClient(alternativeBaseUrl);
return gateway;
}
}
為此,我們需要實現IServiceGatewayFactory以便我們可以首先捕獲IRequest所需的電流,以便調用 In Process Service Gateway。便捷的ServiceGatewayFactoryBase將 API 的其余部分抽象出來,因此您只需負責為指定的請求 DTO 返回適當的服務網關。
捕獲當前IRequest使網關工廠實例不適合用作單例,因此我們需要使用AddTransient或ReuseScope.None作用域注冊它,以便每次解析新實例:
public override void Configure(Container container)
{
container.AddTransient<IServiceGatewayFactory>(() => new CustomServiceGatewayFactory());
// Equivalent to:
// container.Register<IServiceGatewayFactory>(x => new CustomServiceGatewayFactory())
// .ReusedWithin(ReuseScope.None);
}
該Metadata.CreateRequestFromUrl()API允許您從絕對或相對URL請求的DTO。如果您需要一個通用例程來從集合或 URL 執行許多不同的服務,這很有用,例如:
var processUrls = new []{ "https://example.org/invoices/generate?userId=1", "/assets/1/generate" };
foreach (var url in processUrls)
{
var request = HostContext.Metadata.CreateRequestFromUrl(url);
var responseType = HostContext.Metadata.GetResponseTypeByRequest(request.GetType());
var response = HostContext.AppHost.GetServiceGateway().Send(responseType, request);
db.Insert(new Task { Url = url, Response = response.ToJson(), Completed = DateTime.UtcNow });
}
服務網關提供了執行服務的最佳方式,它將使用配置的服務網關或服務發現解決方案透明地執行本地處理中的請求或遠程執行外部請求。
這展示了我們可以插入和攔截所有服務內調用并應用我們自己的高級自定義邏輯的基礎,這為其他增值功能(如服務發現)奠定了基礎,服務發現可以透明地將服務調用路由到最合適的可用遠程端點在運行時自動進行,無需額外的配置或代碼維護開銷。
無論系統是否從細粒度的微服務架構中整體受益,足以證明它所需的額外延遲、管理和基礎設施開銷是合理的,我們仍然看到微服務設計的開發過程中的價值,其中將自然隔離的組件解耦為松散耦合的子系統具有軟件架構優勢,整個系統的整體復雜性被降低到更小、更易于管理的邏輯范圍,這些邏輯范圍將它們的功能封裝在可重用的、粗粒度的消息到小的、定義良好的外觀上。
ServiceGateway 及其服務發現生態系統,以及 ServiceStack 推薦使用的 impl-free 可重用 POCO DTO 及其跨多個項目模塊化服務實現的能力,自然促進了微服務就緒架構,其中服務交互松散耦合在定義明確、可重用、粗粒度的消息。稍后以這種方式設計系統允許從主系統中提取隔離的服務實現 .dll 并將其包裝到其自己的 AppHost 中。與商定的服務發現解決方案一起,允許您生成新服務的多個實例 - 讓您獨立于系統的其余部分擴展、部署和維護它。
大家如果對相關知識比較感興趣,可以關注一下動力節點的Java在線學習,里面的課程內容豐富,從入門到精通,很適合沒有基礎的小伙伴進行學習,相信對大家會有所幫助的。
0基礎 0學費 15天面授
有基礎 直達就業
業余時間 高薪轉行
工作1~3年,加薪神器
工作3~5年,晉升架構
提交申請后,顧問老師會電話與您溝通安排學習