.Net 6 使用Ocelot、Consul、Ids4系列

发布时间 2023-04-04 17:36:40作者: 白码一号

.Net 6 使用Ocelot、Consul、Ids4系列

主要以Ocelot为切入点,先进行.net 6的简单实现于应用在此基础上逐步扩展

一、先了解一下Ocelot的用法

API网关是:系统暴露在外部的一个访问入口。从面向对象设计的角度看,它与外观模式类似。API网关封装了系统内部架构,为每个客户端提供一个定制的API。它可能还具有其它职责,如身份验证、监控、负载均衡、缓存、请求分片与管理、静态响应处理等等。
API网关方式的核心要点是,所有的客户端和消费端都通过统一的网关接入微服务,在网关层处理所有的非业务功能。通常,网关也是提供REST/HTTP的访问API。服务端通过API-GW注册和管理服务。

Ocelot在API网关实现上有什么优点呢?

它的功能包括了:路由、请求聚合、服务发现、认证、鉴权、限流熔断、并内置了负载均衡器、Service Fabric、Butterfly Tracing等的集成。而且这些功能都只需要简单的配置即可完成。
Ocelot的开源地址:https://github.com/ThreeMammals/Ocelot

Ocelot工作流程是怎样的呢?

实际上Ocelot就是一系列按特定顺序排列的中间件。
Ocelot首先通过配置将HttpRequest对象保存到一个指定的状态直到它到达用来创建HttpRequestMessage对象并将创建的HttpRequestMessage对象发送到下游服务中的请求构造中间件。通过中间件来发出请求是Ocelot管道中做的最后一件事。它不会再调用下一个中间件。下游服务的响应会存储在每个请求 scoped repository中,并作为一个请求返回到Ocelot管道中。有一个中间件将HttpResponseMessage映射到HttpResponse对象并返回给客户端。
接下来是你使用Ocelot是可能会使用的配置。

基本集成

OcelotBasic

用一台web service来host Ocelot,在这里有一个json配置文件,里面设置了所有对当前这个网关的配置。它会接收所有的客户端请求,并路由到对应的下游服务器进行处理,再将请求结果返回。而这个上下游请求的对应关系也被称之为路由。

注意:只有一个网关是很危险的,单点模式下只要它挂了,所有的服务全挂。这显然无法达到高可用,所以我们也可以部署多台Ocelot网关。当然这个时候在多台网关前,你还需要一台负载均衡器。

扩展Consul的用途:

在Ocelot已经支持简单的负载功能,也就是当下游服务存在多个结点的时候,Ocelot能够承担起负载均衡的作用。

但是它不提供健康检查,服务的注册也只能通过手动在配置文件里面添加完成。这不够灵活并且在一定程度下会有风险。这个时候我们就可以用Consul来做服务发现,它能与Ocelot完美结合。

 

扩展Ids4的用途:

Ocelot在入口加入Ids4在进入系统前进行权限验证,IdentityServer是基于OpenID Connect协议标准的身份认证和授权程序,它实现了OpenID Connect 和 OAuth 2.0 协议。目的都是在软件应用中为客户端颁发令牌并用于安全访问的。

IdentityServer应用场景:

  • 保护你的资源
  • 使用本地帐户或通过外部身份提供程序对用户进行身份验证
  • 提供会话管理和单点登录
  • 管理和验证客户机
  • 向客户发出标识和访问令牌
  • 验证令牌

开始简单应用不注入任何应用下的服务是这样的

项目工程目录如下

 

 

 

 

 Program类

using Ocelot.DependencyInjection;
using Ocelot.Middleware;

var builder = WebApplication.CreateBuilder(args);

//builder.Host.ConfigureAppConfiguration(c =>
//{
//    c.AddJsonFile("", optional: false, reloadOnChange: true);
//});

//IConfiguration configuration = new ConfigurationBuilder()
//.AddJsonFile($"ocelot.{builder.Environment.EnvironmentName}.json", true, true)
//.Build();

//IConfiguration configuration = new ConfigurationBuilder().AddJsonFile("Ocelot_Config_Origin.json").Build();

builder.Configuration.AddJsonFile("ocelot.json"); //添加配置文件(1.可以使用数据库配置,读取数据库配置 2.使用json的配置文件进行配置)

builder.Services.AddControllers();

builder.Services.AddEndpointsApiExplorer();

builder.Services.AddOcelot();//加入Ocelot服务

var app = builder.Build();

app.UseHttpsRedirection();

app.UseOcelot().Wait(); //加入管道中

app.UseAuthorization();

app.MapControllers();

app.Run();

这里使用的是配置文件的方式(配置如下)

//无Consul配置,简单配置,包含两大配置块,转发路由和全局配置
{
  // 转发路由,数组中的每个元素都是某个服务的一组路由转发规则
  "Routes": [
    {
      // 下游(服务提供方)服务路由模板
      "DownstreamPathTemplate": "/api/{path}",
      // Uri方案,http、https
      "DownstreamScheme": "http",
      // 服务地址和端口,如果是集群就设置多个
      "DownstreamHostAndPorts": [
        {
          "Host": "localhost",
          "Port": 5240
        },
        {
          "Host": "localhost",
          "Port": 5240
        }
      ],
      // 允许的HTTP请求方法,可以写多个
      "UpstreamHttpMethod": [ "Get", "Post" ],
      // 上游(客户端,服务消费方)请求路由模板
      "UpstreamPathTemplate": "/OcelotNotes/{path}", //OcelotNotes/{path}
      // 负载均衡,只有上面匹配了集群,才有效
      /*
       负载均衡算法,总共三种类型。
        LeastConnection:最小链接,将请求发往最空闲的那个服务器
        RoundRobin:轮询,轮流发送
        NoLoadBalance:无负载均衡,总是发往第一个请求或者是服务发现
        */
      "LoadBalancerOptions": {
        "Type": "RoundRobin" // 轮询
      }
    },
    {
      // 下游(服务提供方)服务路由模板
      "DownstreamPathTemplate": "/api/{path}",
      // Uri方案,http、https
      "DownstreamScheme": "http",
      // 服务地址和端口,如果是集群就设置多个
      "DownstreamHostAndPorts": [
        {
          "Host": "localhost",
          "Port": 7001
        },
        {
          "Host": "localhost",
          "Port": 7002
        }
      ],
      // 允许的HTTP请求方法,可以写多个
      "UpstreamHttpMethod": [ "Get", "Post" ],
      // 上游(客户端,服务消费方)请求路由模板
      "UpstreamPathTemplate": "/MyServiceB/{path}",
      // 负载均衡,只有上面匹配了集群,才有效
      "LoadBalancerOptions": {
        "Type": "RoundRobin" // 轮询
      }
    }
  ],
  // 全局配置,此节点的配置会覆盖Routes,可以在这里设置一些通用的配置
  "GlobalConfiguration": {
    "ReRouteIsCaseSensitive": false, // 路由是否区分大小写
    "BaseUrl": "http://localhost:5200"
  },
  "ServiceDiscoveryProvider": {
    "Host": "localhost",
    "Port": 5200
  }
}