更新時(shí)間:2021-10-29 10:13:04 來源:動(dòng)力節(jié)點(diǎn) 瀏覽836次
有不少進(jìn)行Java學(xué)習(xí)的小伙伴對微服務(wù)網(wǎng)關(guān)不是很了解,服務(wù)網(wǎng)關(guān)是在 ServiceStack 現(xiàn)有的基于消息的架構(gòu)之上實(shí)現(xiàn)的,為開發(fā)松散耦合的模塊化服務(wù)架構(gòu)開辟了令人興奮的新可能性。
新的IServiceGateway接口代表在支持同步和異步服務(wù)集成的形式化 API 中支持 ServiceStack 的不同調(diào)用約定所需的最小表面積:
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實(shí)現(xiàn)者的負(fù)擔(dān)最小,而ServiceGatewayExtensions覆蓋了所有實(shí)現(xiàn)通用的便利 API,為請求 DTO 實(shí)現(xiàn)推薦IReturn和IReturnVoid接口標(biāo)記提供了最好的 API 。擴(kuò)展方法還為IServiceGateway那些也沒有實(shí)現(xiàn) optional 的實(shí)現(xiàn)提供回退偽異步支持IServiceGatewayAsync,但將為那些實(shí)現(xiàn)的實(shí)現(xiàn)使用本機(jī)異步實(shí)現(xiàn)。
裸請求DTO的無注釋被發(fā)送作為POST與而是由標(biāo)注請求DTO的替代動(dòng)詞也支持HTTP動(dòng)詞接口標(biāo)記,其中請求DTO的含有IGet,IPut等使用類型化的動(dòng)詞API,例如被發(fā)送:
[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 });
要在內(nèi)部執(zhí)行現(xiàn)有的 ServiceStack 服務(wù),您可以調(diào)用ExecuteRequest(requestDto)它,將請求 DTO 與當(dāng)前一起傳遞IRequest到ServiceController.Execute()要執(zhí)行的對象中。另一種方法是調(diào)用ResolveService<T>以解析服務(wù)的自動(dòng)裝配實(shí)例,該實(shí)例注入了當(dāng)前IRequest上下文,讓您可以直接調(diào)用服務(wù)實(shí)例上的方法。以下是使用這兩個(gè) 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 })
};
}
}
現(xiàn)在推薦的方法是使用所有服務(wù)、Razor 視圖、MVC ServiceStackController 類等中可用的IServiceGateway可訪問的方法base.Gateway。它的工作原理類似于ExecuteRequest()API(它現(xiàn)在取代),您可以僅使用填充的請求 DTO 調(diào)用服務(wù),而是為實(shí)現(xiàn)推薦IReturn<T>或IReturnVoid標(biāo)記的請求 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 之外)是該系統(tǒng)稍后可以將其客戶和訂單子系統(tǒng)拆分為不同的主機(jī),并且這個(gè)確切的服務(wù)實(shí)現(xiàn)將繼續(xù)像以前一樣運(yùn)行,盡管有一點(diǎn)點(diǎn)由于任何引入的進(jìn)程外通信的開銷,速度較慢。
默認(rèn)實(shí)現(xiàn)IServiceGateway使用InProcessServiceGateway,它將請求 DTO 委托給適當(dāng)?shù)腟erviceController.Execute()或ServiceController.ExecuteAsync()方法來執(zhí)行服務(wù)。一個(gè)明顯的區(qū)別是下游Service拋出的任何異常都會(huì)自動(dòng)轉(zhuǎn)換為WebServiceException客戶端在外部調(diào)用Service時(shí)拋出的異常,因此無論是調(diào)用內(nèi)部Service還是外部Service都無法區(qū)分異常,這開始觸及好處網(wǎng)關(guān)的...
無論您是在服務(wù)器上調(diào)用內(nèi)部服務(wù)還是從客戶端調(diào)用遠(yuǎn)程服務(wù),ServiceGateway 都是相同的接口。它公開了一個(gè)理想的基于消息的 API,該 API最適合遠(yuǎn)程服務(wù)集成,該API還支持自動(dòng)批處理請求,用于將多個(gè)服務(wù)調(diào)用組合到一個(gè)請求中,盡可能減少延遲。
這些特性使得替換和自定義網(wǎng)關(guān)的行為變得容易,如下面的示例所示。支持的最簡單方案是將所有服務(wù)網(wǎng)關(guān)調(diào)用重定向到遠(yuǎn)程 ServiceStack 實(shí)例,這可以通過針對IServiceGateway接口注冊任何 .NET 服務(wù)客戶端來完成,例如:
public override void Configure(Container container)
{
container.Register<IServiceGateway>(c => new JsonServiceClient(baseUrl));
}
您想要支持的更可能的場景是內(nèi)部請求在進(jìn)程內(nèi)執(zhí)行,外部請求調(diào)用各自的服務(wù)的混合。如果您的系統(tǒng)一分為二,這將成為一個(gè)簡單的檢查,以返回在此 ServiceStack 實(shí)例中定義的請求的本地 InProcess 網(wǎng)關(guān),否則返回配置到備用主機(jī)的服務(wù)客戶端,例如:
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;
}
}
為此,我們需要實(shí)現(xiàn)IServiceGatewayFactory以便我們可以首先捕獲IRequest所需的電流,以便調(diào)用 In Process Service Gateway。便捷的ServiceGatewayFactoryBase將 API 的其余部分抽象出來,因此您只需負(fù)責(zé)為指定的請求 DTO 返回適當(dāng)?shù)姆?wù)網(wǎng)關(guān)。
捕獲當(dāng)前IRequest使網(wǎng)關(guān)工廠實(shí)例不適合用作單例,因此我們需要使用AddTransient或ReuseScope.None作用域注冊它,以便每次解析新實(shí)例:
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。如果您需要一個(gè)通用例程來從集合或 URL 執(zhí)行許多不同的服務(wù),這很有用,例如:
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 });
}
服務(wù)網(wǎng)關(guān)提供了執(zhí)行服務(wù)的最佳方式,它將使用配置的服務(wù)網(wǎng)關(guān)或服務(wù)發(fā)現(xiàn)解決方案透明地執(zhí)行本地處理中的請求或遠(yuǎn)程執(zhí)行外部請求。
這展示了我們可以插入和攔截所有服務(wù)內(nèi)調(diào)用并應(yīng)用我們自己的高級自定義邏輯的基礎(chǔ),這為其他增值功能(如服務(wù)發(fā)現(xiàn))奠定了基礎(chǔ),服務(wù)發(fā)現(xiàn)可以透明地將服務(wù)調(diào)用路由到最合適的可用遠(yuǎn)程端點(diǎn)在運(yùn)行時(shí)自動(dòng)進(jìn)行,無需額外的配置或代碼維護(hù)開銷。
無論系統(tǒng)是否從細(xì)粒度的微服務(wù)架構(gòu)中整體受益,足以證明它所需的額外延遲、管理和基礎(chǔ)設(shè)施開銷是合理的,我們?nèi)匀豢吹轿⒎?wù)設(shè)計(jì)的開發(fā)過程中的價(jià)值,其中將自然隔離的組件解耦為松散耦合的子系統(tǒng)具有軟件架構(gòu)優(yōu)勢,整個(gè)系統(tǒng)的整體復(fù)雜性被降低到更小、更易于管理的邏輯范圍,這些邏輯范圍將它們的功能封裝在可重用的、粗粒度的消息到小的、定義良好的外觀上。
ServiceGateway 及其服務(wù)發(fā)現(xiàn)生態(tài)系統(tǒng),以及 ServiceStack 推薦使用的 impl-free 可重用 POCO DTO 及其跨多個(gè)項(xiàng)目模塊化服務(wù)實(shí)現(xiàn)的能力,自然促進(jìn)了微服務(wù)就緒架構(gòu),其中服務(wù)交互松散耦合在定義明確、可重用、粗粒度的消息。稍后以這種方式設(shè)計(jì)系統(tǒng)允許從主系統(tǒng)中提取隔離的服務(wù)實(shí)現(xiàn) .dll 并將其包裝到其自己的 AppHost 中。與商定的服務(wù)發(fā)現(xiàn)解決方案一起,允許您生成新服務(wù)的多個(gè)實(shí)例 - 讓您獨(dú)立于系統(tǒng)的其余部分?jǐn)U展、部署和維護(hù)它。
大家如果對相關(guān)知識(shí)比較感興趣,可以關(guān)注一下動(dòng)力節(jié)點(diǎn)的Java在線學(xué)習(xí),里面的課程內(nèi)容豐富,從入門到精通,很適合沒有基礎(chǔ)的小伙伴進(jìn)行學(xué)習(xí),相信對大家會(huì)有所幫助的。
初級 202925
初級 203221
初級 202629
初級 203743