首页 > 其他分享 >05_NET中使用Ocelot网关(负载均衡、限流、认证)

05_NET中使用Ocelot网关(负载均衡、限流、认证)

时间:2024-04-15 14:56:27浏览次数:23  
标签:网关 http 请求 05 builder 限流 Ocelot localhost

Ocelot是一个用.NET Core实现并且开源的API网关,它功能强大,包括了:路由、请求聚合、服务发现、认证、鉴权、限流熔断、并内置了负载均衡器与Service Fabric、Butterfly Tracing集成。而且这些功能都只需要简单的配置即可完成。

官网:GitHub - ThreeMammals/Ocelot: .NET API Gateway

Welcome to Ocelot 23.2 — Ocelot 23.2 documentation

安装包:Ocelot,命令:Install-Package Ocelot

简单使用:

1.首先两个WebApi服务,Service1和Service2用于测试

Service1:

[ApiController]
[Route("[controller]/[action]")]
public class UserController:ControllerBase
{
    [HttpGet]
    public List<UserInfo> GetUsers([FromQuery] UserBo bo)
    {
        List<UserInfo> result = new()
        {
            new(){Id = 1,NickName = "张三"},
            new(){Id = 2,NickName = "李四"}
        };
        return result;
    }

    [HttpGet]
    public string GetStr()
    {
        return "hello world,gateway,server1";
    }
}

Service2:

[ApiController]
[Route("[controller]/[action]")]
public class UserController:ControllerBase
{
    [HttpGet]
    public List<UserInfo> GetUsers([FromHeader]  long userId)
    {
        List<UserInfo> result = new()
        {
            new(){Id = 3,NickName = "王五"},
            new(){Id = 4,NickName = "赵六"}
        };
        return result;
    }
    
    [HttpGet]
    public string GetStr()
    {
        return "hello world,gateway,server2";
    }
}

 

2.添加一个空的Web项目Ocelot,添加Ocelot安装包。

2.1.添加ocelot.json的配置文件。

Program.cs修改

var builder = WebApplication.CreateBuilder(args);

// 添加配置文件,optional:文件是否可选,reloadOnChange:如果文件发生更改,是否应重载配置。
builder.Configuration.AddJsonFile("ocelot.json", optional: false, reloadOnChange: true);
// 添加Ocelot 服务
builder.Services.AddOcelot(builder.Configuration);var app = builder.Build();
// 会阻断当前项目自己的 /controller/action 路由
app.UseOcelot().Wait();


app.Run();

 

2.2.ocelot.json配置 ( 不推荐这么使用 )

{
  //这里注意,以前是ReRoutes现在是Routes
  "Routes": [
    {
      //Upstream表示上游请求,即客户端请求到API Gateway的请求
      "UpstreamPathTemplate": "/s1/{url}", //请求路径模板
      "UpstreamHttpMethod": [ "Get", "Post" ], //请求方法数组

      //"UseServiceDiscovery": true, //启用服务发现

      //Downstream表示下游请求,即API Gateway转发的目标服务地址
      "DownstreamPathTemplate": "/{url}", //下游请求地址模板
      "DownstreamScheme": "https", //请求协议,目前应该是支持http和https

      //A***************指定单个转发地址
      "DownstreamHostAndPorts": [ //请求服务地址,可以有多个
        {
          "Host": "localhost",
          "Port": 5146
        }
      ]
    },
    {
      "UpstreamPathTemplate": "/s2/{url}",  
      "UpstreamHttpMethod": [ "Get", "Post" ], 
       
      "DownstreamPathTemplate": "/{url}",  
      "DownstreamScheme": "https",  

      "DownstreamHostAndPorts": [  
        {
          "Host": "localhost",
          "Port": 5211
        }
      ]
    }
  ],
  "GlobalConfiguration": {
    "BaseUrl": "http://localhost:5063" //网关地址
  }
}

启动服务:启动两个服务和网关

测试:http://localhost:5063/s1/user/getusers  和  http://localhost:5063/s2/user/getusers

 

--------------------------------------------------------漂亮的分割线-----------------------------------------------------------------------------

模板介绍:

{
  "DownstreamPathTemplate": "/",
  "UpstreamPathTemplate": "/",
  "UpstreamHttpMethod": [
    "Get",
    "Post"
  ],
  "AddHeadersToRequest": {},
  "AddClaimsToRequest": {},
  "RouteClaimsRequirement": {},
  "AddQueriesToRequest": {},
  "RequestIdKey": "",
  "FileCacheOptions": {
    "TtlSeconds": 0,
    "Region": ""
  },
  "ReRouteIsCaseSensitive": false,
  "ServiceName": "",
  "DownstreamScheme": "http",
  "DownstreamHostAndPorts": [
    {
      "Host": "localhost",
      "Port": 51876
    }
  ],
  "QoSOptions": {
    "ExceptionsAllowedBeforeBreaking": 0,
    "DurationOfBreak": 0,
    "TimeoutValue": 0
  },
  "LoadBalancer": "",
  "RateLimitOptions": {
    "ClientWhitelist": [],
    "EnableRateLimiting": false,
    "Period": "",
    "PeriodTimespan": 0,
    "Limit": 0
  },
  "AuthenticationOptions": {
    "AuthenticationProviderKey": "",
    "AllowedScopes": []
  },
  "HttpHandlerOptions": {
    "AllowAutoRedirect": true,
    "UseCookieContainer": true,
    "UseTracing": true
  },
  "UseServiceDiscovery": false
}

 

Downstream是下游服务配置
UpStream是上游服务配置
Aggregates 服务聚合配置
ServiceName, LoadBalancer, UseServiceDiscovery 配置服务发现
AuthenticationOptions 配置服务认证
RouteClaimsRequirement 配置Claims鉴权
RateLimitOptions为限流配置
FileCacheOptions 缓存配置
QosOptions 服务质量与熔断
DownstreamHeaderTransform头信息转发
DownstreamPathTemplate:下游模板
DownstreamScheme:下游服务http schema
DownstreamHostAndPorts:下游服务的地址,如果使用LoadBalancer的话这里可以填多项
UpstreamPathTemplate: 上游也就是用户输入的请求Url模板
UpstreamHttpMethod: 上游请求http方法,可使用数组

 

--------------------------------------------------------漂亮的分割线-----------------------------------------------------------------------------

负载均衡

当下游服务有多个结点的时候,我们可以在DownstreamHostAndPorts中进行配置。

{
  "Routes": [
    {
      "UpstreamPathTemplate": "/s/{url}",
      "UpstreamHttpMethod": [ "Get","Post" ],
      "LoadBalancerOptions": {
        "Type": "RoundRobin"
      },
      "DownstreamPathTemplate": "/{url}",
      "DownstreamScheme": "http",
      "DownstreamHostAndPorts": [
        {
          "Host": "localhost",
          "Port": 5146
        },
        {
          "Host": "localhost",
          "Port": 5211
        }
      ]
    }
  ],
  "GlobalConfiguration": {
    "BaseUrl": "http://localhost:5063"
  }
}

LoadBalancerOptions:
LeastConnection – 将请求发往最空闲的那个服务器
RoundRobin – 轮流发送
NoLoadBalance – 总是发往第一个请求或者是服务发现

测试:http://localhost:5063/s/user/getusers

--------------------------------------------------------漂亮的分割线-----------------------------------------------------------------------------

限流

对请求进行限流可以防止下游服务器因为访问过载而崩溃。非常优雅的实现,我们只需要在路由下加一

些简单的配置即可以完成。

{
  "Routes": [
    {
      "UpstreamPathTemplate": "/s/{url}",
      "UpstreamHttpMethod": [ "Get", "Post" ],
      "LoadBalancerOptions": {
        "Type": "RoundRobin"
      },

      // 限流配置
      "RateLimitOptions": {
        "ClientWhitelist": [],      //白名单,不会被限流,为空表示访问的都被限流
        "EnableRateLimiting": true, //是否被开启
        "Period": "1s",             //1秒钟超过了Limit定义的会抛异常
        "PeriodTimespan": 1,        //超过一秒后才可以重新请求
        "Limit": 1
      },
      "DownstreamPathTemplate": "/{url}",
      "DownstreamScheme": "http",
      "DownstreamHostAndPorts": [
        {
          "Host": "localhost",
          "Port": 5146
        },
        {
          "Host": "localhost",
          "Port": 5211
        }
      ]
    }
  ],
  "GlobalConfiguration": {
    "BaseUrl": "http://localhost:5063",
    "RateLimitOptions": {
      "DisableRateLimitHeaders": false,
      "QuotaExceededMessage": "你被限流了..........",
      "HttpStatusCode": 999,  //发生异常返回转态码
      "ClientIdHeader": "ClientId"
    }
  }
}

DisableRateLimitHeaders Http头 X-Rate-Limit 和 Retry-After 是否禁用
QuotaExceedMessage 当请求过载被截断时返回的消息
HttpStatusCode 当请求过载被截断时返回的http status , 默认为429(too many requests)
ClientIdHeader 用来识别客户端的请求头,默认是 ClientId

 

--------------------------------------------------------漂亮的分割线-----------------------------------------------------------------------------

认证

添加一个WebApi项目(AuthenticationCente),用于获取Token,不知道怎么用JWT 的可以去查资料或 02_Web Api使用Jwt - 野码 - 博客园 (cnblogs.com)

 

网关项目(Ocelot)中的Program.cs调整

var builder = WebApplication.CreateBuilder(args);

// 添加配置文件
builder.Configuration.AddJsonFile("ocelot.json", optional: false, reloadOnChange: true);


#region 认证
//身份认证--如何鉴权 
builder.Services.AddAuthentication(options =>
{
    /options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
    //取出私钥
    var secretByte = Encoding.UTF8.GetBytes(builder.Configuration["JWT:SecretKey"]);
    options.TokenValidationParameters = new TokenValidationParameters()
    {
        //验证发布者
        ValidateIssuer = true,
        ValidIssuer = builder.Configuration["JWT:Issuer"],
        //验证接收者
        ValidateAudience = true,
        ValidAudience = builder.Configuration["JWT:Audience"],
        //ValidateIssuerSigningKey= true,//是否验证SigningKey
        //验证是否过期
        ValidateLifetime = true,
        //验证私钥
        IssuerSigningKey = new SymmetricSecurityKey(secretByte)
    };
});
#endregion

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

var app = builder.Build();

app.UseAuthentication();
app.UseAuthorization();

// 会阻断当前项目自己的 /controller/action 路由
app.UseOcelot().Wait();


app.Run();

修改ocelot.json配置

{
  "Routes": [
    {
      "UpstreamPathTemplate": "/s/{url}",
      "UpstreamHttpMethod": [ "Get", "Post" ],
      "LoadBalancerOptions": {
        "Type": "RoundRobin"
      },

      // 限流配置
      "RateLimitOptions": {
        "ClientWhitelist": [], //白名单,不会被限流,为空表示访问的都被限流
        "EnableRateLimiting": true, //是否被开启
        "Period": "1s", //1秒钟超过了Limit定义的会抛异常
        "PeriodTimespan": 1, //超过一秒后才可以重新请求
        "Limit": 1
      },
      "AuthenticationOptions": { //认证
        "AuthenticationProviderKey": "Bearer",
        "AllowedScopes": []
      },
      "DownstreamPathTemplate": "/{url}",
      "DownstreamScheme": "http",
      "DownstreamHostAndPorts": [
        {
          "Host": "localhost",
          "Port": 5146
        },
        {
          "Host": "localhost",
          "Port": 5211
        }
      ]
    }
  ],
  "GlobalConfiguration": {
    "BaseUrl": "http://localhost:5063",
    "RateLimitOptions": {
      "DisableRateLimitHeaders": false,
      "QuotaExceededMessage": "你被限流了..........",
      "HttpStatusCode": 999,  //发生异常返回转态码
      "ClientIdHeader": "ClientId"
    }
  }
}

然后service1和Service2方法上添加[Authorize] 

测试:http://localhost:5063/s/user/getusers 请求头带上Token

 

--------------------------------------------------------漂亮的分割线-----------------------------------------------------------------------------

子服务获取参数

外部服务调用子服务,走网关。

参数对象

public class UserInfo
{
    [FromHeader]
    public int UserId{ get; set; }

    public string NickName { get; set; }
}

 

子服务要接收userId

    [HttpGet]
    public List<UserInfo> GetUsers([FromHeader] long userInfo)
    {
        List<UserInfo> result = new()
        {
            new(){UserId = 1,NickName = "张三"},
            new(){UserId = 2,NickName = "李四"}
        };
        return result;
    }

 

上游请求中添加报头,请在ocelot.json中的路由 GlobalConfiguration 配置中中添加以下内容:

{
  "Routes": [
    {
      "UpstreamPathTemplate": "/s/{url}",
      "UpstreamHttpMethod": [ "Get", "Post" ],
      "LoadBalancerOptions": {
        "Type": "RoundRobin"
      },

      // 限流配置
      "RateLimitOptions": {
        "ClientWhitelist": [], //白名单,不会被限流,为空表示访问的都被限流
        "EnableRateLimiting": true, //是否被开启
        "Period": "1s", //1秒钟超过了Limit定义的会抛异常
        "PeriodTimespan": 1, //超过一秒后才可以重新请求
        "Limit": 1
      },
      "AuthenticationOptions": { //认证
        "AuthenticationProviderKey": "Bearer",
        "AllowedScopes": []
      },
      "DownstreamPathTemplate": "/{url}",
      "DownstreamScheme": "http",
      "DownstreamHostAndPorts": [
        {
          "Host": "localhost",
          "Port": 5146
        },
        {
          "Host": "localhost",
          "Port": 5211
        }
      ]
    }
  ],
  //全局
  "GlobalConfiguration": {
    "BaseUrl": "http://localhost:5063",
    "RateLimitOptions": {
      "DisableRateLimitHeaders": false,
      "QuotaExceededMessage": "你被限流了..........",
      "HttpStatusCode": 999, //发生异常返回转态码
      "ClientIdHeader": "ClientId"
    },
    "UpstreamHeaderTransform": {
      "UserId": "{UserId}"
    }
  }
}

测试:http://localhost:5063/s/user/getusers

Params:NickName--->1234

Headers:UserId--->2233

Auth:你的Token

标签:网关,http,请求,05,builder,限流,Ocelot,localhost
From: https://www.cnblogs.com/MingQiu/p/18135695

相关文章

  • 洛谷题单指南-数学基础问题-P4057 [Code+#1] 晨跑
    原题链接:https://www.luogu.com.cn/problem/P4057题意解读:给定三个数,计算其最小公倍数。解题思路:三个数a、b、clcm(a,b,c)=lcm(lcm(a,b),c)100分代码:#include<bits/stdc++.h>usingnamespacestd;typedeflonglongLL;LLa,b,c;LLgcd(LLa,LLb){i......
  • 物联网浏览器(IoTBrowser)-Java快速对接施耐德网络IO网关
     前一段时间有个Java技术栈的朋友联系到我,需要快速对接现有的无人值守称重系统,这里的对接是指替代现有系统,而非软件层面的对接,也就是利用现有的硬件开发一套替代现有软件的自动化系统。主要设备包括地磅秤、道闸、红外对射传感器、摄像头、小票打印、LED显示屏等等,全程使用LED......
  • "(UE4Editor.exe中)处有未经处理的异常:0xC0000005:读取位置0x0000000000000000时发生
    报错情况:使用ue4.27Slate编写Widget时想通过获取Worl(通过本地PlayerController获取)来实现“设置定时任务为在音乐结束后自动触发函数”的功能ps:定时执行函数代码 解决方法:使用GWorld替换掉通过第0号PlayerController获取世界 原因分析:(由于本人校验较少,暂做以下估计)在......
  • httprunner 4.x学习 - 05校验(validate)
    前言HttpRunner4.x内置了丰富的校验结果的方式校验方式assert缩写说明equal"eq","equals","equal"相等less_than"lt","less_than"小于less_or_equals"le","less_or_equals"小于或等于greater_than"......
  • 《线性代数的本质》笔记(04-附注1-05)
    04-矩阵乘法与线性变换复合的联系问:如何描述连续两个线性变换?答:先左乘一个矩阵,再左乘一个。如果我们用一个矩阵来描述这个复合过程,那么这个矩阵应该等于两个矩阵的乘积,这就是矩阵的乘法。如何理解上图:把右侧矩阵M2看作看作第一次变换后的\(\hat{i}\)向量和\(\hat{j}\)向量,......
  • 05_QT网络编程之TCP通信
    QT网络编程之TCP通信QT的网络编程:​ 网络编程有TCP和UDP。TCP编程需要用到俩个类:QTcpServer和QTcpSocket本节课目标:​ 完成一个TCP服务器和一个客户端。TcpServerwidget.ui<?xmlversion="1.0"encoding="UTF-8"?><uiversion="4.0"><class>Widget</class>......
  • MySQL 8 显示错误代码2058
    在使用mysql-uroot-P3307-proot和SQLyong连接MySQL时报错1.在MySQL8.3CommandLineClient登录点击查看代码Enterpassword:****WelcometotheMySQLmonitor.Commandsendwith;or\g.YourMySQLconnectionidis14Serverversion:8.3.0MySQLCommunitySer......
  • 2059:【例3.11】买笔
    2059:【例3.11】买笔时间限制:1000ms      内存限制:65536KB提交数:61425   通过数: 33243【题目描述】期末来临了,班长小Q决定将剩余班费x�元钱,用于购买若干支钢笔奖励给一些学习好、表现好的同学。已知商店里有三种钢笔,它们的单价为66元、55元和44元。小Q想......
  • EL1205 电子工程实践
    免责声明:本评估简报中提供的信息在发布时是正确的。在不太可能的情况下,任何变化如有必要,将通过电子邮件进行明确沟通,并分发新版评估简报。学年:2023/24评估简介:课程电子工程学士(荣誉)模块代码:EL1205课程名称:电子工程实践简报标题:设计与构建:RS232字符生成器评估类型:课程此评估包包括......
  • 记录协助Javaer硬件快速开发过程之Web技术栈对接施耐德网络IO网关
    前一段时间有个Java技术栈的朋友联系到我,需要快速对接现有的无人值守称重系统,这里的对接是指替代现有系统,而非软件层面的对接,也就是利用现有的硬件开发一套替代现有软件的自动化系统。主要设备包括地磅秤、道闸、红外对射传感器、摄像头、小票打印、LED显示屏等等,全程使用LED显示......