zoukankan      html  css  js  c++  java
  • .Net core+Ocelot+Consul 实现API网关 服务注册 服务发现 负载均衡

    前言

    .Net Core 已经发布3.0了在最近的一两年中.NET Core的关注度持续上升, 微服务及云原生应用开发上采用.NET Core也越来越多,Ocelot 作为.NET Core平台下一款开源的API 网关开发库越来越得到社区的认可,应用到生产中的案例也很多,本文分享以下两部分内容

    1、基于Ocelot搭建Api网关;2、Ocelot+Consul 实现下游服务的服务注册、服务发现、健康检查、负载均衡 参考 《.NET Core 在腾讯财付通的企业级应用开发实践》

    先给大解释下Ocelot 和 Consul到底是干啥的

    Ocelot(http://ocelot.readthedocs.io)是一个用.NET Core实现并且开源的API网关,它功能强大,包括了:路由、负载均衡、请求聚合、认证、鉴权、限流熔断等,这些功能只都只需要简单的配置即可完成

    Consul(https://www.consul.io)是一个分布式,高可用、支持多数据中心的服务注册、发现、健康检查和配置共享的服务软件,由 HashiCorp 公司用 Go 语言开发

    Ocelot天生集成对Consul支持,在OcelotGateway项目中Ocelot.json配置就可以开启ocelot+consul的组合使用,实现服务注册、服务发现、健康检查、负载均衡。

    接下来分享下如何搭建这样一个项目。

    软件

    Asp.net Core:2.1 

    Ocelot:7.1.0

    Consul:1.1.0   github 分享地址 (https://github.com/zhangbojr/Consul.git)

    项目解决方案目录

    Bo.ApiGateway Asp.net Core 2.0 Api网关

    Bo.ApiServiceA  Asp.net Core 2.0 Api下游服务A

    Bo.ApiServiceB  Asp.net Core 2.0 Api下游服务B

    Consul:

    conf 配置目录

    data 缓存数据目录,可清空里面内容

    dist Consul UI目录

    consul.exe 注册软件

    startup.bat 执行脚本

    项目实现

    1、搭建Api网关

    新建Bo.ApiGateway 基于Asp.net Core 2.0空网站,在 依赖项 右击 管理NuGet程序包 浏览 找到 Ocelot 版本7.1.0-unstable0011安装

    1.1、在项目根目录下新建一个 Ocelot.json 文件,打开 Ocelot.json 文件,配置Ocelot参数,Ocelot.json 代码如下

    {
      "ReRoutes": [
        {
          "UpstreamPathTemplate": "/apiservice/{controller}",
          "UpstreamHttpMethod": [ "Get" ],
          "DownstreamPathTemplate": "/apiservice/{controller}",
          "DownstreamScheme": "http",
          "DownstreamHostAndPorts": [
            {
              "host": "localhost",
              "port": 5011
            },
            {
              "host": "localhost",
              "port": 5012
            }
          ],
          "LoadBalancerOptions": {
            "Type": "LeastConnection"
          }
        }
      ],
    
      "GlobalConfiguration": {
        "BaseUrl": "http://localhost:5000"
      }
    }
    

    如果有多个下游服务,把ReRoutes下 {...} 复制多份,最终如: "ReRoutes":[{...},{...}]

    Ocelot参数说明如下,详情查看官网(http://ocelot.readthedocs.io)

    ReRoutes 路由配置 

    UpstreamPathTemplate 请求路径模板
    UpstreamHttpMethod 请求方法数组
    DownstreamPathTemplate 下游请求地址模板
    DownstreamScheme 请求协议,目前应该是支持http和https
    DownstreamHostAndPorts 下游地址和端口
    LoadBalancerOptions 负载均衡 RoundRobin(轮询)/LeastConnection(最少连接数)/CookieStickySessions(相同的Sessions或Cookie发往同一个地址)/NoLoadBalancer(不使用负载)

    DownstreamHostAndPorts配了两个localhost 5011和localhost 5012用于负载均衡,负载均衡已经可以了,但没有健康检查,当其中一个挂了,负载可能还是会访问这样就会报错,所以我们要加入Consul,我们稍后再讲。

    请求聚合,认证,限流,熔错告警等查看官方配置说明

    GlobalConfiguration 全局配置
    BaseUrl 告诉别人网关对外暴露的域名

    1.2、修改 Program.cs 代码,读取Ocelot.json配置,修改网关地址为 http://localhost:5000

    代码如下:

    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Threading.Tasks;
    using Microsoft.AspNetCore;
    using Microsoft.AspNetCore.Hosting;
    using Microsoft.Extensions.Configuration;
    using Microsoft.Extensions.Logging;
    
    namespace Bo.ApiGateway
    {
        public class Program
        {
            public static void Main(string[] args)
            {
                CreateWebHostBuilder(args).Build().Run();
            }
    
            public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
                WebHost.CreateDefaultBuilder(args)
                .ConfigureAppConfiguration((context, builder) =>
                {
                    builder.SetBasePath(context.HostingEnvironment.ContentRootPath)
                        .AddJsonFile("Ocelot.json");
                }).UseUrls("http://localhost:5000")
                    .UseStartup<Startup>();
        }
    }
    

    1.3、修改Startup.cs代码,注入Ocelot到容器,并使用Ocelot

     代码如下:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    using Microsoft.AspNetCore.Builder;
    using Microsoft.AspNetCore.Hosting;
    using Microsoft.AspNetCore.Http;
    using Microsoft.Extensions.DependencyInjection;
    using Ocelot.DependencyInjection;
    using Ocelot.Middleware;
    
    namespace Bo.ApiGateway
    {
        public class Startup
        {
            // This method gets called by the runtime. Use this method to add services to the container.
            // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
            public void ConfigureServices(IServiceCollection services)
            {
                services.AddOcelot();
            }
    
            // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
            public void Configure(IApplicationBuilder app, IHostingEnvironment env)
            {
                if (env.IsDevelopment())
                {
                    app.UseDeveloperExceptionPage();
                }
                app.UseOcelot().Wait();
                app.Run(async (context) =>
                {
                    await context.Response.WriteAsync("Hello World!");
                });
            }
        }
    }

     2、搭建服务Bo.ServiceA,Bo.ServiceB 基于Asp.net Core 2.0 Api网站

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    using Microsoft.AspNetCore.Mvc;
    using Microsoft.Extensions.Configuration;
    
    namespace Bo.ServiceA.Controllers
    {
        [Route("api/[controller]")]
        [ApiController]
        public class ValuesController : ControllerBase
        {
    
            public IConfiguration Configuration { get; }
    
            public ValuesController(IConfiguration configuration)
            {
                Configuration = configuration;
            }
            [HttpGet]
            public string Get()
            {
                return HttpContext.Request.Host.Port + " " + Configuration["AppName"] + " " + DateTime.Now.ToString();
            }
            [HttpGet("/health")]
            public IActionResult Heathle()
            {
                return Ok();
            }
    
            // GET api/values
            // GET api/values/5
            [HttpGet("{id}")]
            public ActionResult<string> Get(int id)
            {
                return "value";
            }
    
            // POST api/values
            [HttpPost]
            public void Post([FromBody] string value)
            {
            }
    
            // PUT api/values/5
            [HttpPut("{id}")]
            public void Put(int id, [FromBody] string value)
            {
            }
    
            // DELETE api/values/5
            [HttpDelete("{id}")]
            public void Delete(int id)
            {
            }
        }
    }

     2.2、修改appsettings.json配置,加入 "AppName": "ServiceA"

    {
      "Logging": {
        "LogLevel": {
          "Default": "Warning"
        }
      },
      "AllowedHosts": "*",
      "AppName": "ServiceA"
    }

     2.3、修改Program.cs代码,修改该服务地址为 http://localhost:5011

      

    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Threading.Tasks;
    using Microsoft.AspNetCore;
    using Microsoft.AspNetCore.Hosting;
    using Microsoft.Extensions.Configuration;
    using Microsoft.Extensions.Logging;
    
    namespace Bo.ServiceA
    {
        public class Program
        {
            public static void Main(string[] args)
            {
                CreateWebHostBuilder(args).Build().Run();
            }
    
            public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
                WebHost.CreateDefaultBuilder(args)
                  .UseUrls("http://192.168.2.6:5011")
                    .UseStartup<Startup>();
        }
    }

     2.4、新建Bo.ServiceB 基于Asp.net Core 2.0 Api网站,几乎与ServiceA一样,除了 "AppName": "ServiceB",.UseUrls("http://localhost:5012")

    3、启动 运行Bo.ServiceA,Bo.ServiceB,Bo.ApiGateway项目,在浏览器打开 http://localhost:5000/apiservice/values 地址

     

     

    Ocelot已内置负载均衡,但没有健康检查,不能踢除坏掉的服务,所以加入Consul,Consul提供服务注册发现、健康检查,配合Ocelot负载就能发现坏掉的服务,只负载到正常的服务上,下面介绍加入Consul。

    二、在Ocelot网关加入Consul,实现服务注册发现、健康检查

     

    1、启动Consul,开启服务注册、服务发现

    首先下载Consul:https://www.consul.io/downloads.html,本项目是windows下进行测试,得到consul.exe

    再下载Consul配置文件和Consul UI(配置文件适合本例Demo的,可根据具体项目修改调整):https://github.com/Liu-Alan/Ocelot-Consul/tree/master/Consul

    conf:配置文件目录

    data:缓存数据目录,可清空里面内容

    dist:Consul UI,用于浏览器查看注册的服务情况;如果用Consul默认自带UI,该目录可以删除,Consul 启动脚本 -ui-dir ./dist 改为 -ui 

    Consul支持配置文件和Api两种方式服务注册、服务发现,下面主要讲解配置文件方式

    Consul 配置文件service.json配置如下:

    {
      "encrypt": "7TnJPB4lKtjEcCWWjN6jSA==",
      "services": [
        {
          "id": "ApiServiceA",
          "name": "MyService",
          "tags": ["ApiServiceA"],
          "address": "192.168.2.6",
          "port": 5011,
          "checks": [
            {
              "id": "CK A 5011",
              "name": "CK A 5011",
              "http": "http://192.168.2.6:5011/health",
              "interval": "5s",
              "tls_skip_verify": false,
              "method": "GET",
              "timeout": "1s"
            }
          ]
        }
      ]
    }
    

    打开ValuesController.cs 加入 health

    重新生成运行项目Bo.ServiceA,Bo.ServiceB

    清除Consul/data 内容,新建startup.bat文件,输入下面代码,双击启动Consul,本项目测试时一台机器,所以把 本机IP 改成 192.168.2.6

    consul agent -server -datacenter=dc1 -bootstrap -data-dir ./data -config-file ./conf -ui-dir ./dist -node=n1 -bind 本机IP -client=0.0.0.0

    再在Consul目录下启动另一个cmd命令行窗口,输入命令:consul operator raft list-peers 查看状态查看状态,结果如下

    由于ServiceA、ServiceB是在一台机器上两个服务做负载 所以在一个Consul里配置了两个name一样的服务。

    如果用两个机器做ServiceA负载,本机IP是192.168.2.6,另一台IP是192.168.2.180上,以本机上主Consul

    把ServiceB和Consul拷到另一个192.168.2.180 机器,修改Consul配置文件 

    修改启动Consul脚本的IP为192.168.2.180,-node=n2,去掉 -bootstrap,启动Consul,在Consul UI下查看服务是否正常

    在192.168.2.6下,把192.168.2.180加到集群中,命令如下

    consul join 192.168.2.180

    注意,consul集群中,consul配置文件中的encrypt,一定要相同,否则无法放加入同一个集群

    用consul operator raft list-peers查看状态,会发现n1,n2在一个集群中了

    2、配置Ocelot,加入Consul,启用服务健康检查,负载均衡

    打开 Snai.ApiGateway 网关下的Ocelot.json文件,加入下面配置

    ServiceName 是Cousul配置中服务的name名字

    UseServiceDiscovery 是否启用Consul服务发现

    ServiceDiscoveryProvider 是Consul服务发现的地址和端口

    重新生成启动Ocelot网关,到此Ocelot+Consul配置完成

    三、运行测试Ocelot+Consul服务发现、负载均衡

    打开 http://localhost:5000/api/values 地址,刷新页面负载得到ServiceA,ServiceB返回内容

     当把ServiceB服务关掉,再多次刷新页面,只能得到ServiceA的内容

     

     

      

     源码地址:(https://github.com/zhangbojr/.Net-core-Ocelot-Consul.git

  • 相关阅读:
    pycharm永久破解方法
    Django-视图&网址
    Django-初体验
    Appium+Pytest实现app并发测试
    我是如何在一周内拿到4份offer的?
    Jenkins集成allure测试报告
    Allure-pytest功能特性介绍
    requests的深入刨析及封装调用
    pytest-html报告修改与汉化
    RobotFrameWork Web自动化测试环境搭建
  • 原文地址:https://www.cnblogs.com/bob-zb/p/11635893.html
Copyright © 2011-2022 走看看