专注Java教育14年 全国咨询/投诉热线:400-8080-105
动力节点LOGO图
始于2009,口口相传的Java黄埔军校
首页 hot资讯 微服务网关详解

微服务网关详解

更新时间:2021-10-29 10:13:04 来源:动力节点 浏览572次

有不少进行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 });  

服务集成 API

要在内部执行现有的 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);
}

从 URL 调用内部和外部服务

该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在线学习,里面的课程内容丰富,从入门到精通,很适合没有基础的小伙伴进行学习,相信对大家会有所帮助的。

提交申请后,顾问老师会电话与您沟通安排学习

免费课程推荐 >>
技术文档推荐 >>