NetCore Consul动态伸缩+Ocelot 网关 缓存 自定义缓存 + 限流、熔断、超时 等服务治理 + ids4鉴权
网关 OcelotGeteway
网关 Ocelot配置文件
{//===========================单地址多实例==负载均衡==Consul= 实现动态伸缩============================"Routes": [{// 上游 》》 接受的请求//上游请求方法,可以设置特定的 HTTP 方法列表或设置空列表以允许其中任何方法"UpstreamHttpMethod": [ "Get", "Post" ],"UpstreamPathTemplate": "/P5001/{url}", //下游》》对接受的请求 进行转发//下游路径模板"DownstreamPathTemplate": "/api/{url}","DownstreamScheme": "http",//支持Consul的服务发现 的配置 就是下面的 GlobalConfiguration配置"UseServiceDiscovery": true,//consul的服务名称 "ServiceName": "Zen",//能负载均衡,但是不能动态伸缩 consul"LoadBalancerOptions": {//RoundRobin>>轮询 LeastConnection >>最少连接数的服务器 NoLoadBalance"Type": "RoundRobin"}}],"GlobalConfiguration": {//网关对外地址"BaseUrl": "Http://localhost:6299","ServiceDiscoveryProvider": {"Schema": "https","Host": "127.0.0.1","Port": 8500,"Type": "Consul" //由consul提供服务发现,每次请求去consul} }
}
网关以webapi 为例
using Ocelot.DependencyInjection;
using Ocelot.Middleware;
using Ocelot.Provider.Consul;namespace OcelotGateway
{public class Program{public static void Main(string[] args){var builder = WebApplication.CreateBuilder(args);// Add services to the container.//配置文件数据源builder.Configuration.AddJsonFile("Configuration.json", true,true);builder.Services.AddControllers();// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbucklebuilder.Services.AddEndpointsApiExplorer();builder.Services.AddSwaggerGen();builder.Services.AddOcelot().AddConsul();var app = builder.Build();// Configure the HTTP request pipeline.if (app.Environment.IsDevelopment()){app.UseSwagger();app.UseSwaggerUI();}//接受请求,转发app.UseOcelot(); //app.UseHttpsRedirection();//app.UseAuthorization();//app.MapControllers();app.Run();}}
}
实际的提供服务的程序 以webapi为例
ConsulHelper
public static class ConsulHelper{/// <summary>/// Consul注册/// </summary>/// <param name="configuration"></param>public static void ConsulRegist(this IConfiguration configuration){//找ConsulConsulClient client = new ConsulClient(c => {c.Address = new Uri("http://localhost:8500");c.Datacenter = "dc1";});string ip = string.IsNullOrWhiteSpace(configuration["ip"]) ? "localhost" : configuration["ip"];int port = string.IsNullOrWhiteSpace(configuration["weight"]) ? 1 : int.Parse(configuration["port"]);int weight = string.IsNullOrWhiteSpace(configuration["weight"]) ? 1 : int.Parse(configuration["weight"]);client.Agent.ServiceRegister(new AgentServiceRegistration(){//唯一的 ID = "service" + Guid.NewGuid(),//分组Name = "Zen",Address = ip,Port = port,Tags = new string[] { weight.ToString() },//心跳Check = new AgentServiceCheck(){//间隔多久一次Interval = TimeSpan.FromSeconds(12),//控制器HTTP = $"http://{ip}:{port}/Api/Health/Index",//检测等等时间Timeout = TimeSpan.FromSeconds(5),//失败后多久移除DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(120)}});//命令行参数获取Console.WriteLine($"注册成功:{ip}{port}-weight:{weight}");}}
Program 中
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using Microsoft.OpenApi.Models;
using System.Net;
using System.Text;namespace WebAPI
{public class Program{public static void Main(string[] args){var builder = WebApplication.CreateBuilder(args);// Add services to the container.builder.Services.AddControllers();// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbucklebuilder.Services.AddEndpointsApiExplorer();builder.Services.AddSwaggerGen(options=>{options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme{Description = "请录入Token,格式:Bearer xxxx Bearer 后面必须有个空格",Name = "Authorization",In = ParameterLocation.Header,Type = SecuritySchemeType.ApiKey,BearerFormat = "JWT",Scheme = "Bearer"});//添加安全要求options.AddSecurityRequirement(new OpenApiSecurityRequirement {{new OpenApiSecurityScheme{Reference =new OpenApiReference{Type = ReferenceType.SecurityScheme,Id ="Bearer"}},new string[]{ }}});});// 开启Bearer 认证builder.Services.AddAuthentication("Bearer") // 配置 JWT Bearer 选项.AddJwtBearer("Bearer", option =>{option.Authority = "https://localhost:2025";option.TokenValidationParameters = new TokenValidationParameters{// 验证发行者//ValidateIssuer = true,// 验证受众ValidateAudience = false,// 验证令牌有效期//ValidateLifetime = true,// 验证签名密钥//ValidateIssuerSigningKey = true,// 发行者//ValidIssuer = builder.Configuration["TokenParameter:Issuer"],// 受众// ValidAudience = builder.Configuration["JokenParameter:Audience"],// 签名密钥//IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["TokenParameter:Secret"])),//AudienceValidator = (m, n, z) =>//{// //自定义验证逻辑// return true;//}};});builder.Services.AddAuthorization(options =>{options.AddPolicy(name: "ApiScope", configurePolicy: policy =>{//需要认证的用户policy.RequireAuthenticatedUser();policy.RequireClaim("scope", "sample_api");});});var app = builder.Build();// Configure the HTTP request pipeline.if (app.Environment.IsDevelopment()){app.UseSwagger();app.UseSwaggerUI();}app.MapWhen(context => context.Request.Path.Equals("/api/Health/Index"),applicationBuilder => applicationBuilder.Run(async context =>{Console.WriteLine($"This is Health Check");context.Response.StatusCode = (int)HttpStatusCode.OK;await context.Response.WriteAsync("OK");}));app.UseAuthentication();app.UseAuthorization();app.MapControllers();//程序启动时执行 ------ 且只执行一次app.Configuration.ConsulRegist();app.Run();}}
}
1、启动Consul
consul agent -dev
参考资料
2、启动webapi实际的服务
dotnet run --urls=“http://:2501" --port=2501 --ip=“localhost” --weight=2
dotnet run --urls="http://:2502” --port=2502 --ip=“localhost” --weight=2
dotnet run --urls=“http://*:2503” --port=2503 --ip=“localhost” --weight=2
3、启动网关 Ocelot
dotnet run --urls=“http://localhost:6299”
源码
网关Ocelot + Cache 缓存
》》Ocelot program
using Ocelot.DependencyInjection;
using Ocelot.Middleware;
using Ocelot.Provider.Consul;
using Ocelot.Cache.CacheManager;
namespace OcelotGateway
{public class Program{public static void Main(string[] args){var builder = WebApplication.CreateBuilder(args);// Add services to the container.//配置文件数据源builder.Configuration.AddJsonFile("Configuration.json", true,true);builder.Services.AddControllers();// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbucklebuilder.Services.AddEndpointsApiExplorer();builder.Services.AddSwaggerGen();builder.Services.AddOcelot().AddConsul().AddCacheManager(x => {x.WithDictionaryHandle();//字典缓存});var app = builder.Build();// Configure the HTTP request pipeline.if (app.Environment.IsDevelopment()){app.UseSwagger();app.UseSwaggerUI();}//接受请求,转发app.UseOcelot(); //app.UseHttpsRedirection();//app.UseAuthorization();//app.MapControllers();app.Run();}}
}
》》》Ocelot 的配置文件
//缓存针对具体那个路由的
{"Routes": [{"UpstreamPathTemplate": "/T/{url}", //上游 网关地址 "UpstreamHttpMethod": [], // 空代表任意方式 【“Get” ,"Post"】"DownstreamPathTemplate": "/api/{url}", //服务地址>>真实的提供服务的"DownstreamSchema": "Http","UseServiceDiscovery": true, //开启服务发现 "ServiceName": "Zen", //Consul 服务名称"LoadBalancerOptions": {"Type": "RoundRobin" //轮询 LeastConnection 》最少连接数的服务器 NoLoadBalance 不负载},//鉴权//"AuthenticationOptins": {// "AuthenticationProviderKey": "UserGatewayKey",// "AllowedScope": []//},"FileCacheOptions": {"TtlSeconds": 15, //Ttl Time To live"Region": "UserCache" //可以调用Api缓存清理}}], "GlobalConfiguration": {//网关对外地址"BaseUrl": "Http://localhost:6299","ServiceDiscoveryProvider": {"Schema": "https","Host": "127.0.0.1","Port": 8500,"Type": "Consul" //由consul提供服务发现,每次请求去consul}//"ServiceDiscoveryProvider": {// "Host": "localhost",// "Port": 8500,// "Type": "PollConsul", //由consul提供服务发现// "PollingInterval": 1000 //轮询consul 频率毫秒--down掉是不知道的// //“Token":"footoken"/ /需要ACL的话//}}
}
自定义缓存
》》》
using Consul;
using Ocelot.Cache;namespace OcelotGateway.OcelotExtend
{/// <summary>/// 自定义的缓存扩展/// </summary>public class CustomCacheExtend : IOcelotCache<CachedResponse>{private readonly ILogger<CustomCacheExtend> logger;public CustomCacheExtend(ILogger<CustomCacheExtend> logger){this.logger = logger;}/// <summary>/// 存放缓存数据的字典,当然可以缓存在Redis 、Mongodb/// 可以提取出去 /// </summary>private class CacheDataModel{public required CachedResponse CachedResponse { get; set; }public DateTime Timeout { get; set; }public string Region { get; set; }}private static Dictionary<string,CacheDataModel> CustomCacheExtendDictionay=new Dictionary<string,CacheDataModel>();/// <summary>/// 没做过期处理,所以需要/// </summary>/// <param name="key"></param>/// <param name="value"></param>/// <param name="ttl"></param>/// <param name="region"></param>public void Add(string key, CachedResponse value, TimeSpan ttl, string region){this.logger.LogWarning($" This is {nameof(CustomCacheExtend)}.{nameof(Add)}");//CustomCacheExtendDictionay.Add(key, new CacheDataModel()//{// CachedResponse = value,// Region = region,// Timeout = DateTime.Now.Add(ttl)//});CustomCacheExtendDictionay[key] = new CacheDataModel(){CachedResponse = value,Region = region,Timeout = DateTime.Now.Add(ttl)};//throw new NotImplementedException();}public void AddAndDelete(string key, CachedResponse value, TimeSpan ttl, string region){throw new NotImplementedException();}public void ClearRegion(string region){this.logger.LogWarning($"This is {nameof(CustomCacheExtend)}.{nameof(ClearRegion)}");var keyList=CustomCacheExtendDictionay.Where(kv=>kv.Value.Region.Equals(region)).Select(kv=>kv.Key);foreach (var key in keyList){CustomCacheExtendDictionay.Remove(key);}//throw new NotImplementedException();}public CachedResponse Get(string key, string region){this.logger.LogWarning($"This is {nameof(CustomCacheExtend)}.{nameof(Get)}");if (CustomCacheExtendDictionay.ContainsKey(key)&& CustomCacheExtendDictionay[key] != null&& CustomCacheExtendDictionay[key].Timeout > DateTime.Now&& CustomCacheExtendDictionay[key].Region.Equals(region)){return CustomCacheExtendDictionay[key].CachedResponse;}elsereturn null;//throw new NotImplementedException();}public bool TryGetValue(string key, string region, out CachedResponse value){throw new NotImplementedException();}}
}
网关 Ocelot 服务治理》》 限流
{"Routes": [{"DownstreamPathTemplate": "/api/{url}", //服务地址 --url 变量"DownstreamSchema": "http","UpstreamPathTemplate": "/T/{url}", //网关地址 --url变量"UpstreamHttpMethod": [ "Get", "Post" ],"UseServiceDiscovery": true,"ServiceName": "zen", //Consul 服务名称"LoadBalancerOptions": {"Type": "RoundRobin" //轮询},"RateLimitOptions": {"ClientWhitelist": [ "xx", "yy" ], //白名单 ClientId 区分大小写"EnableRateLimiting": true,//过期时间"Period": "5m", //1s ,5m.1h,1d"PeriodTimespan": 30, //多少秒之后客户端可以重试"Limit": 5 //统计时间段内允许的最大请求数量},//"AuthenticationOptions": {// "AuthenticationProviderKey": "UserGatewayKey",// "AllowedScopes": []//},//"QoSOptions": {// "ExceptionsAllowedBeforeBreaking": 3, //允许多少异常请求// "DurationOfBreak": 10000, //熔断的时间 单位 ms// "TimeoutValue": 2000 //单位ms 如果下游请求的处理时间超过多少则自如将请求设置为超时 默认90s//},//"FileCacheOptions": {// "TtlSeconds": 15,// "Region": "UserCache" //可以调用Api清理//}}],"GlobalConfiguration": {//网关对外地址"BaseUrl": "Http://localhost:6299","ServiceDiscoveryProvider": {"Schema": "https","Host": "127.0.0.1","Port": 8500,"Type": "Consul" //由consul提供服务发现,每次请求去consul},"RateLimitOptions": {"QuotaExceededMessage": "Too Many requests , maybe later ? ", //当请求过载被截断时返回的消息"HttpStatusCode": 666 ,//当请求过载被截断时返回的http status"ClientIdHeader": "Client_id" //用来识别客户端的请求头 , 默认是 ClientId}}
}
源码
Ocelot 配置文件
{===========================单地址======================================"Routes": [ { // 上游 》》 接受的请求 //上游请求方法,可以设置特定的 HTTP 方法列表或设置空列表以允许其中任何方法 "UpstreamHttpMethod": [ "Get", "Post" ], "UpstreamPathTemplate": "/T5726/{url}", //下游》》对接受的请求 进行转发 //下游路径模板 "DownstreamPathTemplate": "/api/{url}", "DownstreamScheme": "http", "DownstreamHostAndPorts": [ { "Host": "localhost", "Port": 1005 } ] }]//===========================单地址====鉴权==================================//"Routes": [// {// // 上游 》》 接受的请求// //上游请求方法,可以设置特定的 HTTP 方法列表或设置空列表以允许其中任何方法// "UpstreamHttpMethod": [ "Get", "Post" ],// "UpstreamPathTemplate": "/xx/{url}",// //下游》》对接受的请求 进行转发// //下游路径模板// "DownstreamPathTemplate": "/api/{url}",// "DownstreamScheme": "http",// "DownstreamHostAndPorts": [// {// "Host": "localhost",// "Port": 1005// }// ],// "AuthenticationOptins": {// "AuthenticationProviderKey": "UserGatewayKey",// "AllowedScopes": []// }// }//]//===========================单地址====全匹配=================================//"Routes": [// {// // 上游 》》 接受的请求// //上游请求方法,可以设置特定的 HTTP 方法列表或设置空列表以允许其中任何方法// "UpstreamHttpMethod": [ "Get", "Post" ],// //冲突的还可以加权重 Priority// "UpstreamPathTemplate": "/{url}",// //下游》》对接受的请求 进行转发// //下游路径模板// "DownstreamPathTemplate": "/{url}",// "DownstreamScheme": "http",// "DownstreamHostAndPorts": [// {// "Host": "localhost",// "Port": 1005// }// ]// }//]========================多地址多实例===路由冲突+权重匹配======================================//"Routes": [// {// // 上游 》》 接受的请求// //上游请求方法,可以设置特定的 HTTP 方法列表或设置空列表以允许其中任何方法// "UpstreamHttpMethod": [ "Get", "Post" ],// "UpstreamPathTemplate": "/{url}",// "Priority": 1, //默认是0 // //下游》》对接受的请求 进行转发// //下游路径模板// "DownstreamPathTemplate": "/{url}",// "DownstreamScheme": "http",// "DownstreamHostAndPorts": [// {// "Host": "localhost",// "Port": 1005// }// ]// },// {// // 上游 》》 接受的请求// //上游请求方法,可以设置特定的 HTTP 方法列表或设置空列表以允许其中任何方法// "UpstreamHttpMethod": [ "Get", "Post" ],// "UpstreamPathTemplate": "/{url}",// "Priority": 1, //默认是0 // //下游》》对接受的请求 进行转发// //下游路径模板// "DownstreamPathTemplate": "/{url}",// "DownstreamScheme": "http",// "DownstreamHostAndPorts": [// {// "Host": "localhost",// "Port": 1006// }// ]// }//]===========================路由冲突+权重匹配======================================//"Routes": [// {// // 上游 》》 接受的请求// //上游请求方法,可以设置特定的 HTTP 方法列表或设置空列表以允许其中任何方法// "UpstreamHttpMethod": [ "Get", "Post" ],// "UpstreamPathTemplate": "/{url}",// "Priority": 1, //默认是0 // //下游》》对接受的请求 进行转发// //下游路径模板// "DownstreamPathTemplate": "/{url}",// "DownstreamScheme": "http",// "DownstreamHostAndPorts": [// {// "Host": "localhost",// "Port": 1005// }// ]// },// {// // 上游 》》 接受的请求// //上游请求方法,可以设置特定的 HTTP 方法列表或设置空列表以允许其中任何方法// "UpstreamHttpMethod": [ "Get", "Post" ],// "UpstreamPathTemplate": "/{url}",// "Priority": 1, //默认是0 // //下游》》对接受的请求 进行转发// //下游路径模板// "DownstreamPathTemplate": "/{url}",// "DownstreamScheme": "http",// "DownstreamHostAndPorts": [// {// "Host": "localhost",// "Port": 1006// }// ]// }//]//===========================单地址多实例==负载均衡===============================//"Routes": [// {// // 上游 》》 接受的请求// //上游请求方法,可以设置特定的 HTTP 方法列表或设置空列表以允许其中任何方法// "UpstreamHttpMethod": [ "Get", "Post" ],// "UpstreamPathTemplate": "/P5001/{url}",// //能负载均衡,但是不能动态伸缩 consul// "LoadBalancerOptions": {// //RoundRobin>>轮询 LeastConnection >>最少连接数的服务器 NoLoadBalance// "Type": "RoundRobin"// },// //"LoadBalancerOptions": {// // //粘粘性// // "Type": "CookieStickySessions",// // "Key": "Asp.Net_SessionId",// // "Expiry": 180000// //},// //下游》》对接受的请求 进行转发// //下游路径模板// "DownstreamPathTemplate": "/api/{url}",// "DownstreamScheme": "http",// //无法动态伸缩 ==》consul 可以 // "DownstreamHostAndPorts": [// {// "Host": "localhost",// "Port": 1005// },// {// "Host": "localhost",// "Port": 1006// },// {// "Host": "localhost",// "Port": 1007// }// ]// } //]//===========================单地址多实例==负载均衡==Consul= 实现动态伸缩============================//"Routes": [// {// // 上游 》》 接受的请求// //上游请求方法,可以设置特定的 HTTP 方法列表或设置空列表以允许其中任何方法// "UpstreamHttpMethod": [ "Get", "Post" ],// "UpstreamPathTemplate": "/P5001/{url}",// //"LoadBalancerOptions": {// // //粘粘性// // "Type": "CookieStickySessions",// // "Key": "Asp.Net_SessionId",// // "Expiry": 180000// //},// //下游》》对接受的请求 进行转发// //下游路径模板// "DownstreamPathTemplate": "/api/{url}",// "DownstreamScheme": "http",// //支持Consul的服务发现 的配置 就是下面的 GlobalConfiguration配置// "UseServiceDiscovery": true,// //consul的服务名称 // "ServiceName": "Zen",// //能负载均衡,但是不能动态伸缩 consul// "LoadBalancerOptions": {// //RoundRobin>>轮询 LeastConnection >>最少连接数的服务器 NoLoadBalance// "Type": "RoundRobin"// }// }//],//"GlobalConfiguration": {// //网关对外地址// "BaseUrl": "Http://localhost:6299",// "ServiceDiscoveryProvider": {// "Schema": "https",// "Host": "127.0.0.1",// "Port": 8500,// "Type": "Consul" //由consul提供服务发现,每次请求去consul// }// //"ServiceDiscoveryProvider": {// // "Host": "localhost",// // "Port": 8500,// // "Type": "PollConsul", //由consul提供服务发现// // "PollingInterval": 1000 //轮询consul 频率毫秒--down掉是不知道的// // //“Token":"footoken"/ /需要ACL的话// //}//}//********************************Consul + Cache 缓存 ***************************//"Routes": [// {// "UpstreamPathTemplate": "/T/{url}", //上游 网关地址 // "UpstreamHttpMethod": [], // 空代表任意方式 【“Get” ,"Post"】// "DownstreamPathTemplate": "/api/{url}", //服务地址>>真实的提供服务的// "DownstreamSchema": "Http",// "UseServiceDiscovery": true, //开启服务发现 // "ServiceName": "Zen", //Consul 服务名称// "LoadBalancerOptions": {// "Type": "RoundRobin" //轮询 LeastConnection 》最少连接数的服务器 NoLoadBalance 不负载// },// //鉴权// //"AuthenticationOptins": {// // "AuthenticationProviderKey": "UserGatewayKey",// // "AllowedScope": []// //},// "FileCacheOptions": {// "TtlSeconds": 15, //Ttl Time To live// "Region": "UserCache" //可以调用Api缓存清理// }// }//], //"GlobalConfiguration": {// //网关对外地址// "BaseUrl": "Http://localhost:6299",// "ServiceDiscoveryProvider": {// "Schema": "https",// "Host": "127.0.0.1",// "Port": 8500,// "Type": "Consul" //由consul提供服务发现,每次请求去consul// }// //"ServiceDiscoveryProvider": {// // "Host": "localhost",// // "Port": 8500,// // "Type": "PollConsul", //由consul提供服务发现// // "PollingInterval": 1000 //轮询consul 频率毫秒--down掉是不知道的// // //“Token":"footoken"/ /需要ACL的话// //}//}//**************************单地址 + Ids4****************************8//"Routes": [// {// "DownstreamPathTemplate": "/api/{url}", // 服务地址 --url变量// "DownstreamSchema": "http",// "DownstreamHostAndPorts": [// {// "Host": "127.0.0.1",// "Port": 5726, //服务端口// }// ],// "UpstreamPathTemplate": "/T/{url}", //官网 地址 --url变量// "UpstreamHttpMethod": [ "Get", "Post" ],// "AuthenticationOptions": {// "AuthenticationProviderKey": "UserGatewayKey",// "AllowedScopes": []// }// }//]//************************** 超时 限流 熔断 降级 Consul Polly ********************"Routes": [{"DownstreamPathTemplate": "/api/{url}", //服务地址 --url 变量"DownstreamSchema": "http","UpstreamPathTemplate": "/T/{url}", //网关地址 --url变量"UpstreamHttpMethod": [ "Get", "Post" ],"UseServiceDiscovery": true,"ServiceName": "zen", //Consul 服务名称"LoadBalancerOptions": {"Type": "RoundRobin" //轮询},"RateLimitOptions": {"ClientWhitelist": [ "xx", "yy" ], //白名单 ClientId 区分大小写"EnableRateLimiting": true,//过期时间"Period": "5m", //1s ,5m.1h,1d"PeriodTimespan": 30, //多少秒之后客户端可以重试"Limit": 5 //统计时间段内允许的最大请求数量},//"AuthenticationOptions": {// "AuthenticationProviderKey": "UserGatewayKey",// "AllowedScopes": []//},//"QoSOptions": {// "ExceptionsAllowedBeforeBreaking": 3, //允许多少异常请求// "DurationOfBreak": 10000, //熔断的时间 单位 ms// "TimeoutValue": 2000 //单位ms 如果下游请求的处理时间超过多少则自如将请求设置为超时 默认90s//},//"FileCacheOptions": {// "TtlSeconds": 15,// "Region": "UserCache" //可以调用Api清理//}}],"GlobalConfiguration": {//网关对外地址"BaseUrl": "Http://localhost:6299","ServiceDiscoveryProvider": {"Schema": "https","Host": "127.0.0.1","Port": 8500,"Type": "Consul" //由consul提供服务发现,每次请求去consul},"RateLimitOptions": {"QuotaExceededMessage": "Too Many requests , maybe later ? ", //当请求过载被截断时返回的消息"HttpStatusCode": 666 ,//当请求过载被截断时返回的http status"ClientIdHeader": "Client_id" //用来识别客户端的请求头 , 默认是 ClientId}}
}
Ocelot + ids4 鉴权
源码
相关文章:
NetCore Consul动态伸缩+Ocelot 网关 缓存 自定义缓存 + 限流、熔断、超时 等服务治理 + ids4鉴权
网关 OcelotGeteway 网关 Ocelot配置文件 {//单地址多实例负载均衡Consul 实现动态伸缩"Routes": [{// 上游 》》 接受的请求//上游请求方法,可以设置特定的 HTTP 方法列表或设置空列表以允许其中任何方法"UpstreamHttpMethod": [ "Get", &quo…...
【进度条实现】Python中tqdm使用示例
tqdm 是 Python 中一个非常流行的进度条库,可以快速为循环或长时间运行的任务添加进度提示。以下是 tqdm 的常见用法和示例: 1. 安装 pip install tqdm2. 基本用法 在循环中使用 最简单的用法是用 tqdm 包装一个可迭代对象(如列表、range …...
Chirpy3D:用于创意 3D 鸟类生成的连续部分潜在特征
Chirpy3D框架可以将细粒度的2D图像理解提升至3D生成的全新境界。当前的3D生成方法往往只关注于重构简单的对象,缺乏细致的特征和创造性。Chirpy3D通过结合多视角扩散模型和连续的部件潜在空间,能够生成全新且合理的3D鸟类模型。该系统不仅能够保持细致的…...
李飞飞团队 S1 与 DeepSeek R1 技术对比
李飞飞团队 S1 与 DeepSeek R1 技术对比 李飞飞团队的 S1 模型和 DeepSeek R1 模型都是在 AI 推理领域具有重要影响力的模型,它们在技术原理、性能表现和训练成本等方面存在一些差异。 技术原理 S1 模型:S1 模型采用了监督微调(SFT…...
LeetCode 3444.使数组包含目标值倍数的最小增量
给你两个数组 nums 和 target 。 在一次操作中,你可以将 nums 中的任意一个元素递增 1 。 返回要使 target 中的每个元素在 nums 中 至少 存在一个倍数所需的 最少操作次数 。 示例 1: 输入:nums [1,2,3], target [4] 输出:…...
Node.js 中模块化
随着软件开发项目的规模和复杂性的增加,如何有效地组织代码、提高可维护性和促进团队协作成为了一个重要的课题。Node.js 提供了强大的模块系统,使得开发者能够将代码分割成独立的、可重用的模块,从而简化大型应用的开发过程。本文将详细介绍…...
jdk8新特性
目录 1 lambda表达式 1.1 类型推断 1.2 局部变量限制 2 函数式接口 2.1 Predicate 函数式接口 2.2 Supplier函数式接口 2.3 Consumer函数式接口 2.4 Function函数式接口 2.5 Runnable函数式接口 3 方法引用和构造器引用 3.1 对象方法引用 3.2 静态方法引用 3.3 构造方法引用 4 …...
ZooKeeper 和 Dubbo 的关系:技术体系与实际应用
引言 在现代微服务架构中,服务治理和协调是至关重要的环节。ZooKeeper 和 Dubbo 是两个在分布式系统中常用的技术工具,它们之间有着紧密的联系。本文将详细探讨 ZooKeeper 和 Dubbo 的关系,从基础概念、技术架构、具体实现到实际应用场景&am…...
ESP32-S3模组上跑通esp32-camera(43)
接前一篇文章:ESP32-S3模组上跑通esp32-camera(42) 一、OV5640初始化 2. 相机初始化及图像传感器配置 上一回继续对reset函数的后一段代码进行解析。为了便于理解和回顾,再次贴出reset函数源码,在components\esp32-camera\sensors\ov5640.c中,如下: static int reset…...
解决bad SQL grammar []; nested exception is java.sql.SQLSyntaxErrorException
解决Spring Boot中MySQL数据库报错“Bad SQL Grammar”的问题 目录 解决Spring Boot中MySQL数据库报错“Bad SQL Grammar”的问题 问题描述解决步骤解决方案结论附:MySql常用配置参数及使用场景 在使用Spring Boot连接MySQL数据库时,有时候会遇到“B…...
NCV4275CDT50RKG 车规级LDO线性电压调节器芯片——专为新能源汽车设计的高可靠性电源解决方案
产品概述: NCV4275CDT50RKG 是一款符合 AEC-Q100 车规认证的高性能LDO(低压差线性稳压器),专为新能源汽车的严苛工作环境设计。该芯片支持 输出调节为 5.0 V 或 3.3 V,最大输出电流达 450mA,具备超低静态电流…...
DeepSeek Window本地私有化部署
前言 最近大火的国产AI大模型Deepseek大家应该都不陌生。除了在手机上安装APP或通过官网在线体验,其实我们完全可以在Windows电脑上进行本地部署,从而带来更加便捷的使用体验。 之前也提到过,本地部署AI模型有很多好处,比如&…...
镜头放大倍率和像素之间的关系
相互独立的特性 镜头放大倍率:主要取决于镜头的光学设计和结构,决定了镜头对物体成像时的缩放程度,与镜头的焦距等因素密切相关。比如,微距镜头具有较高的放大倍率,能将微小物体如昆虫、花朵细节等放大成像࿰…...
【RabbitMQ重试】重试三次转入死信队列
以下是基于RabbitMQ死信队列实现消息重试三次后转存的技术方案: 方案设计要点 队列定义改造(核心参数配置) Bean public Queue auditQueue() {Map<String, Object> args new HashMap<>();args.put("x-dead-letter-exchan…...
【一文读懂】卫星轨道的轨道参数(六根数)和位置速度矢量转换及其在终端距离、相对速度和多普勒频移计算中的应用
卫星轨道的六根数参数及其在终端距离、相对速度和多普勒频移计算中的应用 卫星轨道运动的描述离不开开普勒六要素(也称为六根数参数),它们完整地刻画了一颗卫星在引力场中的轨道信息。本文将介绍这六个参数的意义,并探讨如何利用…...
车载诊断框架 --- 使用CAPL脚本实现诊断测试吧(中)
我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 简单,单纯,喜欢独处,独来独往,不易合同频过着接地气的生活,除了生存温饱问题之外,没有什么过多的欲望,表面看起来很高冷,内心热情,如果你身…...
Lockdir加密忘记密码:解锁数据恢复之道
Lockdir加密忘记密码现象解析 Lockdir作为一款知名的文件夹加密软件,因其强大的加密功能和便捷的操作体验而广受用户好评。然而,当谈及Lockdir加密忘记密码这一情况时,不少用户却面露难色。Lockdir加密忘记密码,简而言之…...
SQL优化方式
避免select *:开发中禁止使用select * 。它会增加查询解析器成本,无法走索引覆盖而产生回表操作,还会增加网络消耗,浪费CPU和内存资源,应指定具体查询字段。小表驱动大表:关联查询时,用数据量小…...
java项目之基于推荐算法的图书购物网站源码(ssm+mybatis+mysql)
风定落花生,歌声逐流水,大家好我是风歌,混迹在java圈的辛苦码农。今天要和大家聊的是一款基于ssm的基于推荐算法的图书购物网站项目。项目源码以及部署相关请联系风歌,文末附上联系信息 。 项目简介: 基于推荐算法的…...
java中的线程安全
线程安全的定义 线程安全:一个类或方法在多线程环境下可以被多个线程同时访问,而不会导致数据的不一致或错误。 线程不安全:一个类或方法在多线程环境下不能被多个线程同时访问,否则可能导致数据的不一致或错误。线程安全的实现 线…...
day44 QT核心机制
头文件: #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include<QLabel> //标签类头文件 #include<QPushButton> //按钮类头文件 #include<QLineEdit> //行编辑器类头文件QT_BEGIN_NAMESPACE namespace Ui { class Widget; } …...
字节跳动后端一面
📍1. Gzip压缩技术详解 Gzip是一种流行的无损数据压缩格式,它使用DEFLATE算法来减少文件大小,广泛应用于网络传输和文件存储中以提高效率。 🚀 使用场景: • 网站优化:通过压缩HTML、CSS、JavaScript文件来…...
WebSocket推送数据快,条数多导致前端卡顿问题解决
WebSocket推送数据快,条数多导致前端卡顿问题解决 前言方案优化消息频率使用高效的数据格式Protobuf 和 MessagePack的对比 启用压缩前端性能优化 WebSocket使用注意事项连接管理处理断开连接负载均衡监控和维护日志记录定期维护安全最佳实践限流 最后 前言 在项目…...
android动态设置是否允许应用卸载
摘要:通过广播设置全局参数控制应用是否允许卸载,全局参数在Launcher和PackageInstaller两个模块中使用到。此功能可用于MDM后台控制是否允许设备卸载应用。 1. 静态注册广播 由于系统安装和卸载的功能集中在PackageInstaller模块中,为了更…...
【C/C++】每日温度 [ 栈的应用 ] 蓝桥杯/ACM备赛
数据结构考点:栈 题目描述: 给定一个整数数组 temperatures ,表示每天的温度,返回一个数组 answer ,其中 answer[i] 是指对于第 i 天,下一个更高温度出现在几天后。如果气温在这之后都不会升高࿰…...
开启蓝耘之旅:DeepSeek R1 模型在智算平台的起步教程
----------------------------------------------------------我的个人主页-------------------- 动动你的手指----------------------------------------点赞👍 收藏❤--------------------------------------------------------------- 引言 在深度学习的广袤领…...
基于SpringBoot+Vue实现航空票务管理系统
作者简介:Java领域优质创作者、CSDN博客专家 、CSDN内容合伙人、掘金特邀作者、阿里云博客专家、51CTO特邀作者、多年架构师设计经验、多年校企合作经验,被多个学校常年聘为校外企业导师,指导学生毕业设计并参与学生毕业答辩指导,…...
基于改进型灰狼优化算法(GWO)的无人机路径规划
内容: 基于改进型灰狼优化算法的无人机轨迹规划 GWO是一种群体智能优化算法,模仿灰狼的社会等级和狩猎行为。原始的GWO有一些局限性,比如容易陷入局部最优,收敛速度慢等,所以改进型的GWO可能通过不同的策略来优化这些…...
高级记事本 Sublime Text 下载与使用教程:附百度网盘地址
一、引言 在编程和文本编辑领域,Sublime Text 被誉为一款功能强大的高级记事本。它以其轻量级、高效、多语言支持等特点,深受开发者和文本工作者的喜爱。本文将详细介绍 Sublime Text 的下载方法、安装步骤、使用技巧,并提供百度网盘下载地址…...
4G核心网的演变与创新:从传统到虚拟化的跨越
4G核心网 随着移动通信技术的不断发展,4G核心网已经经历了从传统的硬件密集型架构到现代化、虚拟化网络架构的重大转型。这一演变不仅提升了网络的灵活性和可扩展性,也为未来的5G、物联网(LOT)和边缘计算等技术的发展奠定了基础。…...
Jmeter快速实操入门
以下操作需要提前安装了JDK(JDK版本要Java8),并且配置了环境变量。 1、下载Jmeter,下载连接。选择zip版本,解压即可。 2、解压后的文件目录如下。 3、进入bin文件夹,双击ApacheJMeter,运行Jmeter。 4、在测…...
JavaScript中的防抖与节流:提升性能的关键技巧 (1)
文章目录 JavaScript 中的防抖与节流:提升性能的关键技巧一、防抖(Debounce)1.1 概念1.2 应用场景1.3 代码实现 二、节流(Throttle)2.1 概念2.2 应用场景2.3 代码实现2.3.1 时间戳方式2.3.2 定时器方式 三、防抖与节流…...
Java数据类型转换(自动转换和强制转换)
数据类型的转换,分为自动转换和强制转换。自动转换是程序在执行过程中“悄然”进行的转换,不需要用户提前声明,一般是从位数低的类型向位数高的类型转换;强制类型转换则必须在代码中声明,转换顺序不受限制。 自动数据…...
【大数据技术】Spark分布式实现词频统计(hadoop+python+spark)
Spark分布式实现词频统计(hadooppythonspark) 搭建完全分布式高可用大数据集群(VMwareCentOSFinalShell) 搭建完全分布式高可用大数据集群(HadoopMapReduceYarn) 本机PyCharm远程连接CentOS虚拟机&#x…...
UMLS初探
什么是UMLS UMLS(Unified Medical Language System,统一医学语言系统),简单来说就是将不同的医学标准统一到一套体系的系统,主要为了医疗系统的统一而构建出的。 UMLS的主要组成部分 Metathesaurus:一个…...
Redis持久化机制详解
为什么需要持久化 Redis通常被作为缓存使用,但是Redis一旦宕机,内存中的数据全部丢失,可能会导致数据库崩溃。如果是从数据库中恢复这些数据就会存在频繁访问数据库和读取速度慢的问题。所以redis实现数据的持久化,是至关重要的。…...
Python 鼠标轨迹 - 防止游戏检测
一.简介 鼠标轨迹算法是一种模拟人类鼠标操作的程序,它能够模拟出自然而真实的鼠标移动路径。 鼠标轨迹算法的底层实现采用C/C语言,原因在于C/C提供了高性能的执行能力和直接访问操作系统底层资源的能力。 鼠标轨迹算法具有以下优势: 模拟…...
PB-DW-数据窗口-降级-从12.5降级到9.0
PB 数据窗口从125降级到90 供参考,有哪些属性仍然需要删除,请在评论区留言。谢谢。 如果您有更好的工具,能分享给我一份的话,就更好了,感谢。 12.5数据窗口降级9.01- release 12.5; 更改为 release 9;2- 第二行的 d…...
Logo语言的测试开发
Logo语言的测试开发 引言 随着编程教育的不断发展,学习编程的门槛逐渐降低,各种编程语言应运而生。其中,Logo语言作为一种经典的教育编程语言,在培养儿童的逻辑思维和解决问题的能力方面,发挥了重要的作用。本文将深…...
位图的深入解析:从数据结构到图像处理与C++实现
在学习优选算法课程的时候,博主学习位运算了解到位运算的这个概念,之前没有接触过,就查找了相关的资料,丰富一下自身,当作课外知识来了解一下。 位图(Bitmap)是一种用于表示图像的数据结构&…...
Faveo Helpdesk存在目录遍历漏洞(CVE-2024-37700)
免责声明: 本文旨在提供有关特定漏洞的深入信息,帮助用户充分了解潜在的安全风险。发布此信息的目的在于提升网络安全意识和推动技术进步,未经授权访问系统、网络或应用程序,可能会导致法律责任或严重后果。因此,作者不对读者基于本文内容所采取的任何行为承担责任。读者在…...
【Pytorch函数】PyTorch随机数生成全解析 | torch.rand()家族函数使用指南
🌟 PyTorch随机数生成全解析 | torch.rand()家族函数使用指南 🌟 📌 一、核心函数参数详解 PyTorch提供多种随机数生成函数(注意:无直接torch.random()函数),以下是常用函数及参数:…...
ML.NET库学习004:ML.NET基础知识复盘
文章目录 ML.NET库学习004:ML.NET基础知识复盘背景简单的 ML.NET 应用程序代码工作流机器学习模型基础进阶 ML.NET 架构构建管道训练模型使用模型 数据模型和架构模型部署 ML.NET库学习004:ML.NET基础知识复盘 学了几个小项目,发现好多方法莫…...
2. UVM的基本概念和架构
文章目录 前言1. UVM的基本概念1.1 UVM的核心组件1.2 UVM的基本架构1.3 UVM的工作流程 2. UVM的架构2.1 UVM的层次结构2.2 UVM的组件交互 3. 总结 前言 首先,得确定UVM的基本概念和架构包含哪些关键部分。我回忆起UVM的核心组件,比如uvm_component、uvm…...
算法10--哈希
哈希 原理经典例题[1. 两数之和](https://leetcode.cn/problems/two-sum/description/)[面试题 01.02. 判定是否互为字符重排](https://leetcode.cn/problems/check-permutation-lcci/description/)[217. 存在重复元素](https://editor.csdn.net/md?not_checkout1&spm1015…...
磁盘文件删除后恢复
磁盘文件删除后,文件数据并未立即消失,只是文件系统的指针被移除,标记该空间为可覆盖。要恢复文件,可以尝试以下方法: 1. 使用数据恢复软件 Recuva:适合Windows,能恢复多种文件类型。PhotoRec…...
STM32 CUBE Can调试
STM32 CUBE Can调试 1、CAN配置2、时钟配置3、手动添加4、回调函数5、启动函数和发送函数6、使用方法(采用消息队列来做缓存)7、数据不多在发送函数中获取空邮箱发送,否则循环等待空邮箱 1、CAN配置 2、时钟配置 3、手动添加 需要注意的是STM32CUBE配置的代码需要再…...
【大模型】Ubuntu下安装ollama,DeepSseek-R1:32b的本地部署和运行
1 ollama 的安装与设置 ollama官网链接:https://ollama.com/ 在左上角的【Models】中展示了ollama支持的模型在正中间的【Download】中课可以下载支持平台中的安装包。 其安装和模型路径配置操作流程如下: ollama的安装 这里选择命令安装curl -fsSL …...
Goland 内存逃逸问题
内存逃逸是什么? 在go语言中,内存分配存在两个方式:堆分配;栈分配。 栈分配:是在函数调用时为局部变量分配内存,当函数返回时,这些内存会自动释放。 堆分配:通过 new 或者 make 函…...
我们来学人工智能 -- 本地部署DeepSeek
本地部署DeepSeek 题记思考正题结语 题记 时不待我AI会淘汰各领域一些岗位AI可以精简部门,DP白菜价的落地,2025年会更加明显会AI的淘汰不会AI的第四次工业革命将在中国爆发 全产业链多年数字化建设以DP为代表的全球领先白菜价人工智能在各行各业的普及 …...