IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> 学习笔记---- Ocelot中使用Consul+Polly+JWT实现简单的服务发现与治理以及身份认证 -> 正文阅读

[网络协议]学习笔记---- Ocelot中使用Consul+Polly+JWT实现简单的服务发现与治理以及身份认证

前言:上一篇中实现了consul的服务注册与发现,现在可以把网关系统进行一次升级改造,实现简单的服务发现与治理以及身份认证

一,Consul服务发现的引用与配置


1,使用NuGet安装Ocelot.Provider.Consul:

2,使用Startup.cs进行注册:

public void ConfigureServices(IServiceCollection services)
        {
            
            //添加ocelot服务
            services.AddOcelot()
                    //服务发现
                    .AddConsul();
                  
        }


3,修改ocelot.json配置文件:

{
  "Routes": [
    {
      /*下游地址*/
      "DownstreamPathTemplate": "/product/{xx}",
      /*请求方式*/
      "DownstreamScheme": "http",
      /*服务名称*/
      "ServiceName": "productsevrice",
      /*下游服务的主机和端口*/
      //"DownstreamHostAndPorts": [
      //  {
      //    "Host": "localhost",
      //    "Port": 4001
      //  },
      //  {
      //    "Host": "localhost",
      //    "Port": 4002
      //  }
      //], 
      /*上游路径地址*/
      "UpstreamPathTemplate": "/api/product/{xx}",
      "UpstreamHttpMethod": [ "Get", "Post", "Put", "Delete" ], /*请求方式*/
      /*负载均衡:RoundRobin - 循环访问,
        NoLoadBalancer - 从配置或服务发现中获取第一个可用服务,
       "LeastConnection" 请求最少的服务发送新请求,
        CookieStickySessions - 使用 cookie 将所有请求粘贴到特定服务器
      "*/
      "LoadBalancerOptions": {
        "Type": "LeastConnection" /*请求最少的服务发送新请求*/
      }
      
    }
  ],
  "GlobalConfiguration": {
    /*ocelot网关将要运行的地址*/
    "BaseUrl": "http://localhost:4000",
    "ServiceDiscoveryProvider": {
      "Scheme": "http",
      "Host": "localhost",
      "Port": 8500,
      "Type": "Consul"
    }
  }
}


?

??使用consul服务发现相关配置,在全局GlobalConfiguration增加ServiceDiscoveryProvider, 移除DownstreamHostAndPorts节点。

二,Polly服务治理的引用与配置

服务治理是为了提高服务质量以及可用性,缓存,限流,熔断,负载均衡等等都算,实际使用中按需实现即可
1,超时/熔断:
超时即网关请求服务时的最长响应时间,熔断某个服务的请求异常次数达到一定量时不对其继续请求
(1)添加Ocelot.Provider.Polly
(2)修改Startup配置??

  public void ConfigureServices(IServiceCollection services)
        {
            
            //添加ocelot服务
            services.AddOcelot()
                    //服务发现
                    .AddConsul()
                   //添加Polly(防止熔断)
                    .AddPolly();
        }

(3)修改Ocelot.json
?

      /*熔断/超时 
      超时就是网关请求服务时可容忍的最长响应时间。
      熔断的意思就是当请求某个服务的异常次数达到一定量时,
      那么网关在一定时间内就不再对这个服务发起请求了,直接熔断*/
      "QoSOptions": {
        "ExceptionsAllowedBeforeBreaking": 3, //发生错误的次数
        "DurationOfBreak": 10000, //熔断时间
        "TimeoutValue": 5000 //请求超过 5 秒,它将自动超时。
      }

2,缓存/限流

?(1) 添加 Ocelot.Cache.CacheManager

?(2)修改配置:

       public void ConfigureServices(IServiceCollection services)
        {
            
            //添加ocelot服务
            services.AddOcelot()
                    //服务发现
                    .AddConsul()
                   //添加Polly(防止熔断)
                   .AddPolly()
                   //添加缓存,限流
                   .AddCacheManager(x =>
                   {
                       x.WithDictionaryHandle();
                   });
        }

Ocelot.json配置修改:

 /*缓存*/
      "FileCacheOptions": {
        "TtlSeconds": 5, //过期时间
        "Region": "productcache"
      },
      /*限流*/
      "RateLimitOptions": {
        "ClientWhitelist": [ "SuperClient" ], //白名单中的客户端可以不受限流的影响
        "EnableRateLimiting": true, //是否限流
        "Period": "5s", //限流的单位时间
        "PeriodTimespan": 2, //请求上限多少秒后可以重试
        "Limit": 1 //定义的时间内可以发出的最大请求数
      }

最后修改完成之后的Ocelot.json:

{
  "Routes": [
    {
      /*下游地址*/
      "DownstreamPathTemplate": "/product/{xx}",
      /*请求方式*/
      "DownstreamScheme": "http",
      /*服务名称*/
      "ServiceName": "productsevrice",
      /*下游服务的主机和端口*/
      //"DownstreamHostAndPorts": [
      //  {
      //    "Host": "localhost",
      //    "Port": 4001
      //  },
      //  {
      //    "Host": "localhost",
      //    "Port": 4002
      //  }
      //], 
      /*上游路径地址*/
      "UpstreamPathTemplate": "/api/product/{xx}",
      "UpstreamHttpMethod": [ "Get", "Post", "Put", "Delete" ], /*请求方式*/
      /*负载均衡:RoundRobin - 循环访问,
        NoLoadBalancer - 从配置或服务发现中获取第一个可用服务,
       "LeastConnection" 请求最少的服务发送新请求,
        CookieStickySessions - 使用 cookie 将所有请求粘贴到特定服务器
      "*/
      "LoadBalancerOptions": {
        "Type": "LeastConnection" /*请求最少的服务发送新请求*/
      },
      /*缓存*/
      "FileCacheOptions": {
        "TtlSeconds": 5, //过期时间
        "Region": "productcache"
      },
      /*限流*/
      "RateLimitOptions": {
        "ClientWhitelist": [ "SuperClient" ], //白名单中的客户端可以不受限流的影响
        "EnableRateLimiting": true, //是否限流
        "Period": "5s", //限流的单位时间
        "PeriodTimespan": 2, //请求上限多少秒后可以重试
        "Limit": 1 //定义的时间内可以发出的最大请求数
      },
      /*熔断/超时 
      超时就是网关请求服务时可容忍的最长响应时间。
      熔断的意思就是当请求某个服务的异常次数达到一定量时,
      那么网关在一定时间内就不再对这个服务发起请求了,直接熔断*/
      "QoSOptions": {
        "ExceptionsAllowedBeforeBreaking": 3, //发生错误的次数
        "DurationOfBreak": 10000, //熔断时间
        "TimeoutValue": 5000 //请求超过 5 秒,它将自动超时。
      }
    },
    {
      "DownstreamPathTemplate": "/order/{xx}",
      /*请求方式*/
      "DownstreamScheme": "http",
      /*下游服务的主机和端口*/
      "ServiceName": "orderservice",
      "LoadBalancerOptions": {
        "Type": "LeastConnection"
      },
      "UpstreamPathTemplate": "/api/order/{xx}",
      "UpstreamHttpMethod": [ "Get", "Post" ]
    }
  ],
  "GlobalConfiguration": {
    /*ocelot网关将要运行的地址*/
    "BaseUrl": "http://localhost:4000",
    "ServiceDiscoveryProvider": {
      "Scheme": "http",
      "Host": "localhost",
      "Port": 8500,
      "Type": "Consul"
    },
    "RateLimitOptions": {
      "DisableRateLimitHeaders": false, //是否禁用X-Rate-Limit和Retry-After标头
      "QuotaExceededMessage": "{\"res_code\":\"999\",\"res_msg\":\"请求中\"}", //请求达到上限时返回
      "HttpStatusCode": 999, //HTTP状态代码
      "ClientIdHeader": "Test"
    }
  }
}

三,JWT的引用配置与认证
1 ,第一步老规矩Nugget 获取JWT

2,添加了一个帮助类:

public class JWtHelper
    {
          /*生成token*/
        public static string JwtEncrypt(string phone, string uid, string openid, string encrypt_key)
        {
            var token = "";
            try
            {

                var claims = new[] {
                    new Claim("openid", openid),
                    new Claim("phone", phone),
                    new Claim("uid", uid),};
                var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(encrypt_key));
                var credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
                var jwtToken = new JwtSecurityToken("MER", "API", claims, expires: DateTime.Now.AddYears(1), signingCredentials: credentials);
                token = new JwtSecurityTokenHandler().WriteToken(jwtToken);
            }
            catch (Exception)
            {

                throw;
            }
            return token;

        }
        /*解析token*/
        public static string JwtDecrypt(string token, string encrypt_key)
        {
            var josn = "";
            try
            {
                var param = new TokenValidationParameters
                {
                    ValidateIssuerSigningKey = true,
                    IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(encrypt_key)),
                    ValidateIssuer = true,
                    ValidIssuers = new string[] { "ASD123", "MER"},
                    ValidateAudience = true,
                    ValidAudience = "API",
                    ValidateLifetime = true,
                    ClockSkew = TimeSpan.FromMinutes(5)
                };
                SecurityToken security;
                var principal = new JwtSecurityTokenHandler().ValidateToken(token, param, out security);
                if (principal != null)
                {

                    var exp = principal.Claims.FirstOrDefault(c => c.Type.Equals("exp"))?.Value;
                    var uid = principal.Claims.FirstOrDefault(c => c.Type.Equals("uid"))?.Value;
                    var phone = principal.Claims.FirstOrDefault(c => c.Type.Equals("phone"))?.Value;
                    var openid = principal.Claims.FirstOrDefault(c => c.Type.Equals("openid"))?.Value;
                    josn = JsonConvert.SerializeObject(new { openid, phone, uid, exp });
                }

            }
            catch (Exception ex)
            {

                return null;
            }
            return josn;

        }


    }

ps:这个帮助类只是为了看看效果,测试类随便编写能不能再生产环境使用自行考虑。
?

3,添加Jwt中间件

 public class JwtSafeMiddleware
    {

        private readonly RequestDelegate _next;
        public IConfiguration _configuration;
        public JwtSafeMiddleware(RequestDelegate next, IConfiguration configuration)
        {
            _next = next;
            _configuration = configuration;
        }

        public async Task Invoke(HttpContext context)
        {
            //请求不走jwt校验的一种方式:识别url
            //if(!context.Request.Path.Value.StartsWith("/auth")) 

            context.Response.ContentType = "application/json";

            if (context.Request.Method == "GET" || context.Request.Method == "POST")
            {
                string token = context.Request.Headers["token"].FirstOrDefault();
                if (string.IsNullOrEmpty(token))
                {
                    context.Response.StatusCode = 401; //401未授权              
                    var json = JsonConvert.SerializeObject(new { res_code = 401, res_msg = "token为空!" });
                    await context.Response.WriteAsync(json);
                    return;
                }
                //校验auth的正确性
                var result = JWtHelper.JwtDecrypt(token, _configuration["SecretKey"]);
                if (result == "expired")
                {
                    context.Response.StatusCode = 666; 
                    var json = JsonConvert.SerializeObject(new { res_code = 666, res_msg = "参数已经过期!" });
                    await context.Response.WriteAsync(json);
                    return;
                }                
                else
                {
                    //校验通过
                }

            }
            await _next.Invoke(context);
        }
    }

最后在Startup中的Configure方法注册:app.UseMiddleware<JwtSafeMiddleware>();

下一篇 微服务中的CAP

--------to be continue?--------


?

?

  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2021-11-28 11:37:38  更:2021-11-28 11:38:02 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年7日历 -2024/7/6 7:52:17-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码