• 第五节:基于Ocelot网关简介、路由功能、集成Consul使用


    一. 基础说明

    1. API网关剖析

    (1).什么是Api

     API是Application Programming Interface缩写,翻译成中文就是应用程序接口。在实际微服务中可以理解一个个功能方法。就比如你一个商品服务的微服务, 可以对外提供 API 接口为,获取商品目录、获取商品详情等。

    (2).什么是网关(Gateway)

     它是一个服务器,用来转发其他服务器通信数据的, 它接收从客户端发送来的请求时,它就像自己拥有资源的源服务器一样对请求进行处理。

    (3).什么是Api网关

     通俗的来说就是用来限制客户端访问服务端api一道门槛。

    2. 微服务架构中为什么要用网关?

    (1).在这之前,我们的技术栈中只引入了Consul,客户端访问Consul拿到对应的IP+Port,最终还是要访问业务服务器的,但很多情况我们并不想让业务服务器直接对外开放,所以这个时候就需要引入网关进行转发了.

    (2).现在的微服务还没有加权限校验,如果将权限校验加个每个微服务的业务服务器上,开发量很大,这个时候引入网关,可以在网关层校验.

    (3).没有网关,很难做限流,而且各个业务的负责人员不能独立负责自己的服务器器。

    3. 网关都有哪些作用?

     路由、负载均衡、限流、认证、授权、链路监控、熔断降级、Service Fabric

    4. Ocelot相关信息

    (1).依赖程序集:通过Nuget安装 【Ocelot 15.0.6】

      GitHub地址:https://github.com/ThreeMammals/Ocelot

    (2).参考文档:

      官网:https://ocelot.readthedocs.io/en/latest/

      ocelot 中文文档:https://blog.csdn.net/sD7O95O/article/details/79623654

      资料:http://www.csharpkit.com/apigateway.html

      中文文档:http://www.jessetalk.cn/2018/03/19/net-core-apigateway-ocelot-docs/

    (3).其他网关框架:

      A. Netflix Zuul +java实现

      B. Kong nginx +lua脚本实现

      C. Tyk go语言开发,收费版本

      D. Ocelot aspnetcore开发的

    5. Ocelot的原理

      Ocelot是一堆的asp.net core middleware组成的一个管道。当它拿到请求之后会用一个request builder来构造一个HttpRequestMessage发到下游的真实服务器,等下游的服务返回response之后再由一个middleware将它返回的HttpResponseMessage映射到HttpResponse上。

    (1).上游是什么:Ocelot自身就是上游(Upstream)

    (2).下游是什么:Ocelot转发给的(业务)服务器就是下游(Downstream)

    二. 路由功能

    1.路由的含义

      Ocelot(即上游)按照匹配规则接收客户端发送的请求 将客户端请求转换成业务服务器(即下游)的地址 → 调用下游服务,返回结果  →  Ocelot再将下游服务的结果返回给客户端.

    2. 参数介绍

      - Downstream 下游服务配置

      - UpStream 上游服务配置

      - Aggregates 服务聚合配置

      - ServiceName, LoadBalancer, UseServiceDiscovery 配置服务发现

      - AuthenticationOptions 配置服务认证

      - RouteClaimsRequirement 配置Claims鉴权

      - RateLimitOptions 限流配置

      - FileCacheOptions 缓存配置

      - QosOptions 服务质量与熔断

      - DownstreamHeaderTransform 头信息转发

    3. 路由直接转发指定的地址

    (1).业务场景:

      客户端访问网关 → 网关把请求直接转发给"指定ip+端口"业务服务器 (该场景网关本身不配置Consul,直接转发)

    (2).业务编写与测试:

     A. 新建网关项目OcelotGateWay,通过Nuget安装【Ocelot 15.0.7】程序集

     B. 新建一个OcelotConfig.json的配置文件,属性改为"始终复制",用于存放Ocelot的配置。

    代码如下:

    {
      "ReRoutes": [
        {
          //转发下游(业务服务器)的匹配规则
          "DownstreamPathTemplate": "/api/{url}",
          //下游请求类型
          "DownstreamScheme": "http",
          //下游的ip和端口,和上面的DownstreamPathTemplate匹配起来
          "DownstreamHostAndPorts": [
            {
              "Host": "127.0.0.1",
              "Port": 7001
            }
          ],
          //上游(即Ocelot)接收规则
          "UpstreamPathTemplate": "/GoodsService/{url}",
          //上游接收请求类型
          "UpstreamHttpMethod": [ "Get", "Post" ]
        },
        {
          "DownstreamPathTemplate": "/api/{url}",
          "DownstreamScheme": "http",
          "DownstreamHostAndPorts": [
            {
              "Host": "127.0.0.1",
              "Port": 7004
            }
          ],
          "UpstreamPathTemplate": "/OrderService/{url}",
          "UpstreamHttpMethod": [ "Get", "Post" ]
        }
      ]
    }

    剖析上述xml:

    - DownstreamPathTemplate:下游路径模板

    - DownstreamScheme:下游服务http schema

    - DownstreamHostAndPorts:下游服务的地址,如果使用LoadBalancer的话这里可以填多项

    - UpstreamPathTemplate: 上游也就是用户输入的请求Url模板,会将这个请求转发给下游,如上代码,客户端请求 :网关ip+端口/GoodsService/{url},会转发给下游:127.0.0.1:7001/api/{url}

    - UpstreamHttpMethod: 上游请求http方法,可使用数组

     C. 在Program中通过AddJsonFile将上述json文件加载进来.

      public static IHostBuilder CreateHostBuilder(string[] args) =>
                Host.CreateDefaultBuilder(args)
                    //配置相关
                    .ConfigureAppConfiguration((hostingContext, config) =>
                    {
                        //1. 加载json文件 (配置后面两个参数为true,当配置文件发生变化的时候,会自动更新加载,而不必重启整个项目)
                        config.AddJsonFile("OcelotConfig.json", optional: true, reloadOnChange: true);
                    })
                    .ConfigureWebHostDefaults(webBuilder =>
                    {
                        //添加命令行支持(写在上面的Main里也可以)
                        var config = new ConfigurationBuilder().AddCommandLine(args).Build();
                        webBuilder.UseStartup<Startup>();
                    });

     D. 在Startup中进行注册和使用,services.AddOcelot(); app.UseOcelot().Wait();

       public void ConfigureServices(IServiceCollection services)
            {
                //1.注册Ocelot
                var ocelot = services.AddOcelot();
                services.AddControllers();
            }
    
            // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
            public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
            {
                if (env.IsDevelopment())
                {
                    app.UseDeveloperExceptionPage();
                }
                //1.使用Ocelot
                app.UseOcelot().Wait();    //这里不写异步用法了
    
                app.UseRouting();
                app.UseAuthorization();
                app.UseEndpoints(endpoints =>
                {
                    endpoints.MapControllers();
                });
            }

     E. 启动项目,7001端口启动GoodsService、7004端口启动OrderService、7020端口启动OcelotGateWay,指令如下:

      【dotnet GoodsService.dll --urls="http://*:7001" --ip="127.0.0.1" --port=7001】 业务服务器地址

      【dotnet OrderService.dll --urls="http://*:7004" --ip="127.0.0.1" --port=7004】   业务服务器地址

      【dotnet OcelotGateWay.dll --urls="http://*:7020" --ip="127.0.0.1" --port=7020】  网关地址

     F. PostMan测试

     (1). Get测试: http://127.0.0.1:7020/GoodsService/Catalog/GetGoodById1?id=123,会将请求地址转发给  http://127.0.0.1:7001/api/Catalog/GetGoodById1?id=123 ,请求成功。

     (2).  Post请求:http://127.0.0.1:7020/OrderService/Buy/pOrder1,会将请求地址转发给  http://127.0.0.1:7004/api/Buy/pOrder1,请求成功。

     

    三. 集成Consul

      与Consul结合实现业务服务器的负载均衡(推荐用法)

    1.业务背景

      上述通过 Ocelot直接转发给指定的 ip+端口,只是为了演示,实际场景中,比如OrderService这个业务服务器,会部署在多台服务器上进行分摊请求压力,当然我可以利用Ocelot自身实现负载均衡,但不推荐,原因有二: ① Ocelot本身的负载均衡机制不完善 ② 每次增加或减少业务服务器,都需要改网关的配置文件,耦合性很强。

           解决方案:Ocelot与Consul结合,客户端访问网关→网关通过ServiceName去Consul中找一个地址进行匹配访问(Ocelot提供了多种算法去Consul中找地址)

    2.业务编写与测试

     A. 通过Nuget安装【Ocelot 15.0.7】程序集 和 【Ocelot.Provider.Consul 15.0.7】程序集

     B. 新建一个OcelotConfig.json的配置文件,属性改为"始终复制",用于存放Ocelot的配置.

     配置分享:

    //模式三:将Ocelot与consul结合处理,在consul中已经注册业务服务器地址,在Ocelot端不需要再注册了(推荐用法)
    {
      "ReRoutes": [
        {
          "DownstreamPathTemplate": "/api/{url}",
          "DownstreamScheme": "http",
          "ServiceName": "GoodsService", //Consul中的服务名称
          "LoadBalancerOptions": {
            "Type": "RoundRobin" //轮询算法:依次调用在consul中注册的服务器
          },
          "UseServiceDiscovery": true, //启用服务发现(可以省略,因为会默认赋值)
          "UpstreamPathTemplate": "/GoodsService/{url}",
          "UpstreamHttpMethod": [ "Get", "Post" ]
        },
        {
          "DownstreamPathTemplate": "/api/{url}",
          "DownstreamScheme": "http",
          "ServiceName": "OrderService",
          "LoadBalancerOptions": {
            "Type": "LeastConnection" //最小连接数算法
          },
          "UseServiceDiscovery": true,
          "UpstreamPathTemplate": "/OrderService/{url}",
          "UpstreamHttpMethod": [ "Get", "Post" ]
        }
      ],
      //下面是配置Consul的地址和端口
      "GlobalConfiguration": {
        //对应Consul的ip和Port(可以省略,因为会默认赋值)
        "ServiceDiscoveryProvider": {
          "Host": "127.0.0.1",
          "Port": 8500
        }
      }
    }

    剖析配置:  

    LoadBalancer将决定负载均衡的算法

    - LeastConnection – 将请求发往最空闲的那个服务器

    - RoundRobin – 轮流发送

    - NoLoadBalance – 总是发往第一个请求或者是服务发现

    ServiceName(对应服务名), UseServiceDiscovery 启用注册发现(可省略),ServiceDiscoveryProvider 配置Consul的ip和端口。

     C. 在Program中通过AddJsonFile将上述json文件加载进来. (代码同上)

     D. 在Startup中进行注册和使用,services.AddOcelot().AddConsul(); app.UseOcelot().Wait(); 

    代码分享:

            public void ConfigureServices(IServiceCollection services)
            {
                //1.注册Ocelot和Consul
                services.AddOcelot().AddConsul();
                services.AddControllers();
            }
    
            // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
            public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
            {
                if (env.IsDevelopment())
                {
                    app.UseDeveloperExceptionPage();
                }
                //1.使用Ocelot
                app.UseOcelot().Wait();    //这里不写异步用法了
    
                app.UseRouting();
                app.UseAuthorization();
                app.UseEndpoints(endpoints =>
                {
                    endpoints.MapControllers();
                });
            }

     E. 启动项目

      7001,7002,7003 端口启动GoodsService、7004,7005,7006端口启动OrderService、7020端口启动OcelotGateWay

      【dotnet GoodsService.dll --urls="http://*:7001" --ip="127.0.0.1" --port=7001】 业务服务器1地址

      【dotnet GoodsService.dll --urls="http://*:7001" --ip="127.0.0.1" --port=7001】 业务服务器1地址

      【dotnet GoodsService.dll --urls="http://*:7001" --ip="127.0.0.1" --port=7001】 业务服务器1地址

      【dotnet OrderService.dll --urls="http://*:7004" --ip="127.0.0.1" --port=7004】   业务服务器2地址

      【dotnet OrderService.dll --urls="http://*:7004" --ip="127.0.0.1" --port=7004】   业务服务器2地址

      【dotnet OrderService.dll --urls="http://*:7004" --ip="127.0.0.1" --port=7004】   业务服务器2地址

      【dotnet OcelotGateWay.dll --urls="http://*:7020" --ip="127.0.0.1" --port=7020】  网关地址

     F. PostMan测试:

      (1).Get测试: http://127.0.0.1:7020/GoodsService/Catalog/GetGoodById1?id=123, 会按照轮询算法依次转发给 :http://127.0.0.1:7001/api/Catalog/GetGoodById1?id=123,http://127.0.0.1:7001/api/Catalog/GetGoodById1?id=123,http://127.0.0.1:7001/api/Catalog/GetGoodById1?id=123,请求成功。

      (2).Post请求:http://127.0.0.1:7020/OrderService/Buy/pOrder1 ,会根据最小连接数算法,转发给7004 7005 7006连接数最小的业务服务器。

    测试结果同上述路由转发的图

     

    !

    • 作       者 : Yaopengfei(姚鹏飞)
    • 博客地址 : http://www.cnblogs.com/yaopengfei/
    • 声     明1 : 如有错误,欢迎讨论,请勿谩骂^_^。
    • 声     明2 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。
     
  • 相关阅读:
    monkeyrunner之夜神模拟器的安装与使用(二)
    monkeyrunner之安卓开发环境搭建(一)
    MySQL 返回未包含在group by中的列
    MySQL数据库初体验
    MongoDB安装
    关于数据库你必须知道的事~
    PostgreSQL中的MVCC 事务隔离
    深入浅出MySQL之索引为什么要下推?
    Java集合篇:Map集合的几种遍历方式及性能测试
    Oracle11g:数据库恢复总结
  • 原文地址:https://www.cnblogs.com/yaopengfei/p/13038527.html
Copyright © 2020-2023  润新知