栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > .Net

3. .NET5微服务添加Consul中间件

.Net 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

3. .NET5微服务添加Consul中间件

什么是Consul
在上一篇文章中引入了 Ocelot,客户端的调用变得简单的,但是对于网关层来说,每新增一个接口,或者服务实例,我都需要把网关在重新更新发布,这样无疑增加了网关层的负担,如果说我能自动识别服务实例,并且不需要把每个接口都写一遍,那我的网关岂不是只需要更新一次就好,不管你服务实例怎么增加,接口怎么增加,我都能自动识别。

Consul就可以自动做到服务的注册与发现,那怎么注册发现呢,其实Consul是一个单独的进程,启动Consul之后,在服务里向Consul去注册,意思就是告诉Consul,我是用户服务实例1,我的地址是 localhost:5050,我启动了,你把我加入到你的名单中,然后Consul就把用户服务实例1加入名单中了。接着用户实例2,用户实例3都加入到Consul的名单中了。

这时候,网关就不直接去调用服务实例了,网关还不知道有哪些服务实例呢,它需要先去问Consul,我想要用户服务实例,你把你所有的用户服务实例地址都给我,然后Consul把 localhost:5051,localhost:5052,localhost:5053,等地址都给了网关,然后网关在按照一定的策略,比如轮询,随机等算法去获取对应的服务实例地址,然后再去请求。


所以Consul做的事情很简单,就是管理各个服务实例的地址,当网关或者谁要地址了,就通过名字把当前名字下服务实例地址全部返回。

Consul除了可以做服务的发现,还可以做服务的移除,关键字是健康检查,或者说心跳检查,当服务实例注册到Consul时,会同时提供一个健康检查地址,Consul就可以按照用户设定的时间,比如说每5秒向健康检查地址发送一个请求,若你能正常响应了,我就认为你还活着,若没响应,或者没按规定时间内响应,Consul会认为服务已经挂掉了,就把这个服务实例从当前的服务名称下进行移除,下次网关再要地址了,Consul不会把已经挂掉的地址在返回了。

Consul的安装与启动

Consul的官网地址地址: https://www.consul.io

下载好之后就是一个Consul.exe文件,这是Windows环境下的,其他环境请自行查找资料。

然后把当前Consul.exe上一级文件夹地址加入到环境变量中,这样不用每次都进入到这个文件夹去启动了。

启动Consul,打开Terminal,输入

consul.exe agent -dev

若能出现Consul agent running,说明Consul 启动成功了。

这时可以打开浏览器,端口号默认8500,若能出现网页,说明Consul 正常了。

代码实战
服务实例

Consul已经准备好了,那接下来就应该把服务注册到Consul中了,由于多个服务都需要注册,所以单独把注册到Consul的代码封装为一个类库,其他项目去引用即可。新建类库,ConsulBuilder,然后添加两个文件。
添加Consul 的nuget包

  

ConsulRegistrationExtensions.cs

using System;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options;
using Consul;
using ConsulBuilder;

namespace ConsulBuilder
{
    public static class ConsulRegistrationExtensions
    {
        public static IApplicationBuilder AddConsul(this IApplicationBuilder app, ConsulServiceOptions consulServiceOptions)
        {
            var consulClient = new ConsulClient(x =>
            {
                // consul服务地址,默认安装consul后端口为8500
                x.Address = new Uri(consulServiceOptions.ConsulAddress);
            });
            var registration = new AgentServiceRegistration()
            {
                ID = Guid.NewGuid().ToString(),
                Name = consulServiceOptions.ServiceName,// 服务名
                Address = consulServiceOptions.ServiceIP, // 服务绑定IP(也就是你这个项目运行的ip地址)
                Port = consulServiceOptions.ServicePort, // 服务绑定端口(也就是你这个项目运行的端口)
                Check = new AgentServiceCheck()
                {
                    DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(5),//服务启动多久后注册
                    Interval = TimeSpan.FromSeconds(10),//健康检查时间间隔
                    HTTP = consulServiceOptions.ServiceHealthCheck,//健康检查地址
                    Timeout = TimeSpan.FromSeconds(5)
                }
            };
            // 服务注册
            consulClient.Agent.ServiceRegister(registration).Wait();
            return app;
        }
    }
}

ConsulServiceOptions.cs

namespace ConsulBuilder
{
    // Consul配置模型类
    public class ConsulServiceOptions
    {
        /// 
        /// 服务名称
        /// 
        public string ServiceName { get; set; }
        /// 
        /// 服务IP
        /// 
        public string ServiceIP { get; set; }
        /// 
        /// 服务端口
        /// 
        public int ServicePort { get; set; }
        /// 
        /// 服务健康检查地址
        /// 
        public string ServiceHealthCheck { get; set; }
        /// 
        /// Consul 地址
        /// 
        public string ConsulAddress { get; set; }
    }
}

接下来,我们以用户服务举例,首先引用ConsulBuilder类库,接着修改Startup.cs文件的Configure方法。

   //获取关于Consul的配置节点
            var consulSection = Configuration.GetSection("Consul");
            var consulOption = new ConsulServiceOptions
            {
                ServiceName = consulSection["ServiceName"],
                ServiceIP = consulSection["ServiceIP"],
                ServicePort = Convert.ToInt32(consulSection["ServicePort"]),
                ServiceHealthCheck = consulSection["ServiceHealthCheck"],
                ConsulAddress = consulSection["ConsulAddress"]
            };
            //注册consul服务
            app.AddConsul(consulOption);

修改appsetting.json

//Consul的配置
  "Consul": {
    "ServiceName": "UserService",
    "ServiceIP": "localhost",
    "ServicePort": 5050,
    "ServiceHealthCheck": "https://localhost:5050/api/HealthCheck",
    "ConsulAddress": "http://127.0.0.1:8500"
  },

OK ,这样我们的服务在启动时就会自动注册到Consul了.

至于HealthCheck,代码如下,其实是直接返回了Ok(),即可。

using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace EasyShop.UserService.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class HealthCheckController:ControllerBase
    {
        /// 
        /// 健康检查地址
        /// 
        /// 
        public IActionResult HealthCheck()
        {
            return Ok();
        }
    }
}

其他服务的配置过程一样,不在赘述,

网关

若服务实例可以正常被Consul发现,接下来就需要修改网关下的Ocelot.json文件,由Consul提供服务实例地址,而不是直接在json文件中配置。

添加nuget包。

 
 
 
 

Ocelot.json 修改后如下。

{
  // 转发路由,数组中的每个元素都是某个服务的一组路由转发规则
  "Routes": [
    {
      "ServiceName": "UserService", //对应consul配置的ServiceName
      // Uri方案,http、https
      "DownstreamScheme": "https",
      // 下游(服务提供方)服务路由模板
      "DownstreamPathTemplate": "/api/user/{path}",
      // 上游(客户端,服务消费方)请求路由模板
      "UpstreamPathTemplate": "/user/{path}",
      "UpstreamHttpMethod": [ "Get", "Post" ],

      "LoadBalancerOptions": {
        "Type": "RoundRobin" //轮询     
      },
      "UseServiceDiscovery": true,
      "RateLimitOptions": {
        "ClientWhitelist": [ "admin" ], // 白名单
        "EnableRateLimiting": true, // 是否启用限流
        "Period": "1s", // 统计时间段:1s, 5m, 1h, 1d
        "PeriodTimespan": 15, // 多少秒之后客户端可以重试
        "Limit": 2 // 在统计时间段内允许的最大请求数量
      },
      "QoSOptions": {
        "ExceptionsAllowedBeforeBreaking": 2, // 允许多少个异常请求
        "DurationOfBreak": 15000, // 熔断的时间,单位为毫秒
        "TimeoutValue": 5000 // 如果下游请求的处理时间超过多少则视如该请求超时
      },
      "FileCacheOptions": { // cache response data - ttl: 10s   10秒内相同url请求直接返回缓存数据
        "TtlSeconds": 10,
        "Region": ""
      }
      //,身份认证
      //"AuthenticationOptions": {
      //  "AuthenticationProviderKey": "ApiGatewayKey",
      //  "AllowedScopes": [ "UserService" ]
      //}
    }
  ],
  "GlobalConfiguration": {
    "BaseUrl": "https://localhost:44335",
    "ReRouteIsCaseSensitive": false,
    "ServiceDiscoveryProvider": {
      "Host": "localhost",
      "Port": 8500,
      "Type": "Consul" //由Consul提供服务发现
    },
    "RateLimitOptions": {
      "DisableRateLimitHeaders": false, // Http头  X-Rate-Limit 和 Retry-After 是否禁用
      "QuotaExceededMessage": "Too many requests, are you OK?", // 当请求过载被截断时返回的消息
      "HttpStatusCode": 999, // 当请求过载被截断时返回的http status
      "ClientIdHeader": "client_id" // 用来识别客户端的请求头,默认是 ClientId
    }
  }
}

Routes是一个数组,可以配置多个服务实例。在配置里我们可以看到有这么一个配置。"UseServiceDiscovery": true ,这就表示采用服务发现的地址。而在GlobalConfiguration里,配置了Consul的地址。

Startup.cs 修改如下

  public void ConfigureServices(IServiceCollection services)
        {
            //允许跨域请求
            services.AddCors(options =>
            {
                //this defines a CORS policy called "default"
                options.AddPolicy("default", policy =>
                {
                    policy.WithOrigins("http://localhost:8088")
                        .AllowAnyHeader()
                        .AllowAnyMethod();
                });
            });
            services.AddOcelot(Configuration).AddConsul().AddPolly();
        }

和之前的区别在于,之前只引入了 Ocelot,而这次还引入了Consul和Polly。 Configure配置不变。

项目地址:https://gitee.com/limeng66/easy-shop

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/909460.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号