/// <summary> /// 校验完整的限流规则 /// </summary> /// <param name="rateLimitOptions"></param> /// <returns></returns> private bool CheckRateLimitResult(List <AhphClientRateLimitOptions> rateLimitOptions) { bool result = true; if (rateLimitOptions != null && rateLimitOptions.Count > 0) { //校验策略 foreach (var op in rateLimitOptions) { AhphClientRateLimitCounter counter = new AhphClientRateLimitCounter(); //分别对每个策略校验 var enablePrefix = _option.RedisKeyPrefix + "RateLimitRule"; var key = AhphOcelotHelper.ComputeCounterKey(enablePrefix, op.ClientId, op.Period, op.RateLimitPath); var periodTimestamp = AhphOcelotHelper.ConvertToSecond(op.Period); lock (_processLocker) { var rateLimitCounter = _clientRateLimitCounter.Get(key, enablePrefix); if (rateLimitCounter.HasValue) { //提取当前的计数情况 //请求次数增长 var totalRequests = rateLimitCounter.Value.TotalRequests + 1; // 深拷贝 counter = new AhphClientRateLimitCounter(rateLimitCounter.Value.Timestamp, totalRequests); } else { // 写入限流策略 _clientRateLimitCounter.Add(key, counter, TimeSpan.FromSeconds(periodTimestamp), enablePrefix); } } if (counter.TotalRequests > op.Limit) { // 更新请求记录,并标记为失败 result = false; } if (counter.TotalRequests > 1 && counter.TotalRequests <= op.Limit) { // 更新缓存配置信息 //获取限流剩余时间 var cur = (int)(counter.Timestamp.AddSeconds(periodTimestamp) - DateTime.UtcNow).TotalSeconds; _clientRateLimitCounter.Add(key, counter, TimeSpan.FromSeconds(cur), enablePrefix); } } } return(result); }
/// <summary> /// 设置配置信息 /// </summary> /// <param name="internalConfiguration">配置信息</param> /// <returns></returns> public Response AddOrReplace(IInternalConfiguration internalConfiguration) { var key = _options.RedisOcelotKeyPrefix + nameof(InternalConfiguration); _ocelotCache.Add(key, (InternalConfiguration)internalConfiguration, TimeSpan.FromSeconds(_options.CacheTime), ""); return(new OkResponse()); }
/// <summary> /// 校验当前的请求地址客户端是否有权限访问 /// </summary> /// <param name="clientid">客户端ID</param> /// <param name="path">请求地址</param> /// <returns></returns> public async Task <bool> CheckClientAuthenticationAsync(string clientid, string path) { var enablePrefix = _options.RedisKeyPrefix + "ClientAuthentication"; var key = AhphOcelotHelper.ComputeCounterKey(enablePrefix, clientid, "", path); var cacheResult = _ocelotCache.Get(key, enablePrefix); if (cacheResult != null) {//提取缓存数据 return(cacheResult.Role); } else { //重新获取认证信息 var result = await _clientAuthenticationRepository.ClientAuthenticationAsync(clientid, path); //TODO:for test result = true; //添加到缓存里 _ocelotCache.Add(key, new ClientRoleModel() { CacheTime = DateTime.Now, Role = result }, TimeSpan.FromMinutes(_options.ClientAuthorizationCacheTime), enablePrefix); return(result); } }
/// <summary> /// 设置配置信息 /// </summary> /// <param name="internalConfiguration">配置信息</param> /// <returns></returns> public Response AddOrReplace(IInternalConfiguration internalConfiguration) { var key = CzarCacheRegion.InternalConfigurationRegion; _ocelotCache.Add(key, (InternalConfiguration)internalConfiguration, TimeSpan.FromSeconds(_options.CzarCacheTime), ""); return(new OkResponse()); }
CheckClientRateLimitAsync(string clientid, string path) { var region = _option.RedisKeyPrefix + "CheckClientRateLimitAsync"; var key = region + clientid + path; var cacheResult = _rateLimitRuleCache.Get(key, region); if (cacheResult != null) { //提取缓存数据 return(cacheResult.RateLimit, cacheResult.RateLimitOptions); } else { //重新获取限流策略 var result = await _clientRateLimitRepository.CheckClientRateLimitAsync(clientid, path); _rateLimitRuleCache.Add(key, new RateLimitRuleModel() { RateLimit = result.RateLimit, RateLimitOptions = result.rateLimitOptions }, TimeSpan.FromSeconds(_option.ClientRateLimitCacheTime), region); return(result); } }
public async Task Process(HttpContext context, Func <HttpContext, Task> next) { var downstreamRoute = context.Items.DownstreamRoute(); if (!downstreamRoute.IsCached) { await next.Invoke(context); return; } try { var downstreamRequest = context.Items.DownstreamRequest(); var downstreamUrlKey = $"{downstreamRequest.Method}-{downstreamRequest.OriginalString}"; var downStreamRequestCacheKey = _cacheGenerator.GenerateRequestCacheKey(downstreamRequest); _logger.LogDebug("Started checking cache for {Url}", downstreamUrlKey); var cached = _outputCache.Get(downStreamRequestCacheKey, downstreamRoute.CacheOptions.Region); if (cached != null) { _logger.LogDebug("cache entry exists for {Url}. Data length {length}", downstreamUrlKey, cached.Body?.Length ?? 0); context.Response.ContentType = MediaTypeNames.Application.Json; context.Items.UpsertDownstreamResponse(CreateHttpResponseMessage(cached)); _logger.LogDebug("finished returned cached response for {Url}", downstreamUrlKey); return; } _logger.LogDebug("no response cached for {Url}", downstreamUrlKey); await next.Invoke(context); // prevent caching errors var downstreamResponse = context.Items.DownstreamResponse(); if (downstreamResponse == null || (int)downstreamResponse.StatusCode >= 400) { _logger.LogDebug("there was a pipeline error for {Url}", downstreamUrlKey); return; } cached = await CreateCachedResponse(downstreamResponse); _outputCache.Add(downStreamRequestCacheKey, cached, TimeSpan.FromSeconds(downstreamRoute.CacheOptions.TtlSeconds), downstreamRoute.CacheOptions.Region); _logger.LogDebug("finished response added to cache for {Url}. Data length {length}", downstreamUrlKey, cached?.Body?.Length ?? 0); } catch (Exception e) { _logger.LogError(e, e.Message); throw; } }
/// <summary> /// 检验是否启用限流规则 /// </summary> /// <param name="path">请求地址</param> /// <returns></returns> private async Task <bool> CheckReRouteRuleAsync(string path) { var region = CzarCacheRegion.ClientRoleModelRegion; var key = path; var cacheResult = _ocelotCache.Get(key, region); if (cacheResult != null) {//提取缓存数据 return(cacheResult.Role); } else {//重新获取限流策略 var result = await _clientRateLimitRepository.CheckReRouteRuleAsync(path); _ocelotCache.Add(key, new ClientRoleModel() { CacheTime = DateTime.Now, Role = result }, TimeSpan.FromSeconds(_options.CzarCacheTime), region); return(result); } }
/// <summary> /// 校验是否设置了路由白名单 /// </summary> /// <param name="clientid">客户端ID</param> /// <param name="path">请求地址</param> /// <returns></returns> private async Task <bool> CheckClientReRouteWhiteListAsync(string clientid, string path) { var region = _option.RedisKeyPrefix + "CheckClientReRouteWhiteListAsync"; var key = region + clientid + path; var cacheResult = _ocelotCache.Get(key, region); if (cacheResult != null) {//提取缓存数据 return(cacheResult.Role); } else {//重新获取限流策略 var result = await _clientRateLimitRepository.CheckClientReRouteWhiteListAsync(clientid, path); _ocelotCache.Add(key, new ClientRoleModel() { CacheTime = DateTime.Now, Role = result }, TimeSpan.FromSeconds(_option.ClientRateLimitCacheTime), region); return(result); } }
public async Task Invoke(HttpContext httpContext) { var downstreamRoute = httpContext.Items.DownstreamRoute(); if (!downstreamRoute.IsCached) { await _next.Invoke(httpContext); return; } var downstreamRequest = httpContext.Items.DownstreamRequest(); var downstreamUrlKey = $"{downstreamRequest.Method}-{downstreamRequest.OriginalString}"; string downStreamRequestCacheKey = _cacheGenerator.GenerateRequestCacheKey(downstreamRequest); Logger.LogDebug($"Started checking cache for {downstreamUrlKey}"); var cached = _outputCache.Get(downStreamRequestCacheKey, downstreamRoute.CacheOptions.Region); if (cached != null) { Logger.LogDebug($"cache entry exists for {downstreamUrlKey}"); var response = CreateHttpResponseMessage(cached); SetHttpResponseMessageThisRequest(httpContext, response); Logger.LogDebug($"finished returned cached response for {downstreamUrlKey}"); return; } Logger.LogDebug($"no resonse cached for {downstreamUrlKey}"); await _next.Invoke(httpContext); if (httpContext.Items.Errors().Count > 0) { Logger.LogDebug($"there was a pipeline error for {downstreamUrlKey}"); return; } var downstreamResponse = httpContext.Items.DownstreamResponse(); cached = await CreateCachedResponse(downstreamResponse); _outputCache.Add(downStreamRequestCacheKey, cached, TimeSpan.FromSeconds(downstreamRoute.CacheOptions.TtlSeconds), downstreamRoute.CacheOptions.Region); Logger.LogDebug($"finished response added to cache for {downstreamUrlKey}"); }
public async Task Invoke(HttpContext context) { if (!DownstreamRoute.ReRoute.IsCached) { await _next.Invoke(context); return; } var downstreamUrlKey = DownstreamRequest.RequestUri.OriginalString; _logger.LogDebug("started checking cache for {downstreamUrlKey}", downstreamUrlKey); var cached = _outputCache.Get(downstreamUrlKey); if (cached != null) { _logger.LogDebug("cache entry exists for {downstreamUrlKey}", downstreamUrlKey); SetHttpResponseMessageThisRequest(cached); _logger.LogDebug("finished returned cached response for {downstreamUrlKey}", downstreamUrlKey); return; } _logger.LogDebug("no resonse cached for {downstreamUrlKey}", downstreamUrlKey); await _next.Invoke(context); _logger.LogDebug("succesfully called next middleware"); if (PipelineError) { _logger.LogDebug("there was a pipeline error for {downstreamUrlKey}", downstreamUrlKey); return; } var response = HttpResponseMessage; _outputCache.Add(downstreamUrlKey, response, TimeSpan.FromSeconds(DownstreamRoute.ReRoute.FileCacheOptions.TtlSeconds)); _logger.LogDebug("finished response added to cache for {downstreamUrlKey}", downstreamUrlKey); }
/// <summary> /// 根据模板地址获取RPC请求方法 /// </summary> /// <param name="UpUrl">上游模板</param> /// <returns></returns> public async Task <RemoteInvokeMessage> GetRemoteMethodAsync(string UpUrl) { var region = CzarCacheRegion.RemoteInvokeMessageRegion; var key = UpUrl; var cacheResult = _ocelotCache.Get(key, region); if (cacheResult != null) {//提取缓存数据 return(cacheResult); } else { cacheResult = await _rpcRepository.GetRemoteMethodAsync(UpUrl); _ocelotCache.Add(key, cacheResult, TimeSpan.FromSeconds(_options.CzarCacheTime), region); return(cacheResult); } }
/// <summary> /// 根据模板地址获取RPC请求方法 /// </summary> /// <param name="UpUrl">上游模板</param> /// <returns></returns> public async Task <RemoteInvokeMessage> GetRemoteMethodAsync(string UpUrl) { var region = _options.RedisKeyPrefix + "GetRemoteMethodAsync"; var key = region + UpUrl; var cacheResult = _ocelotCache.Get(key, region); if (cacheResult != null) {//提取缓存数据 return(cacheResult); } else { cacheResult = await _rpcRepository.GetRemoteMethodAsync(UpUrl); _ocelotCache.Add(key, cacheResult, TimeSpan.FromSeconds(_options.ClientRateLimitCacheTime), region); return(cacheResult); } }
public async Task Invoke(DownstreamContext context) { if (!context.DownstreamReRoute.IsCached) { await _next.Invoke(context); return; } var downstreamUrlKey = $"{context.DownstreamRequest.Method.Method}-{context.DownstreamRequest.RequestUri.OriginalString}"; _logger.LogDebug("started checking cache for {downstreamUrlKey}", downstreamUrlKey); var cached = _outputCache.Get(downstreamUrlKey, context.DownstreamReRoute.CacheOptions.Region); if (cached != null) { _logger.LogDebug("cache entry exists for {downstreamUrlKey}", downstreamUrlKey); var response = CreateHttpResponseMessage(cached); SetHttpResponseMessageThisRequest(context, response); _logger.LogDebug("finished returned cached response for {downstreamUrlKey}", downstreamUrlKey); return; } _logger.LogDebug("no resonse cached for {downstreamUrlKey}", downstreamUrlKey); await _next.Invoke(context); if (context.IsError) { _logger.LogDebug("there was a pipeline error for {downstreamUrlKey}", downstreamUrlKey); return; } cached = await CreateCachedResponse(context.DownstreamResponse); _outputCache.Add(downstreamUrlKey, cached, TimeSpan.FromSeconds(context.DownstreamReRoute.CacheOptions.TtlSeconds), context.DownstreamReRoute.CacheOptions.Region); _logger.LogDebug("finished response added to cache for {downstreamUrlKey}", downstreamUrlKey); }
/// <summary> /// 校验客户端限流规则 /// </summary> /// <param name="clientid">客户端ID</param> /// <param name="path">请求地址</param> /// <returns></returns> private async Task <(bool RateLimit, List <CzarClientRateLimitOptions> rateLimitOptions)> CheckClientRateLimitAsync(string clientid, string path) { var region = CzarCacheRegion.RateLimitRuleModelRegion; var key = clientid + path; var cacheResult = _rateLimitRuleCache.Get(key, region); if (cacheResult != null) {//提取缓存数据 return(cacheResult.RateLimit, cacheResult.rateLimitOptions); } else {//重新获取限流策略 var result = await _clientRateLimitRepository.CheckClientRateLimitAsync(clientid, path); _rateLimitRuleCache.Add(key, new RateLimitRuleModel() { RateLimit = result.RateLimit, rateLimitOptions = result.rateLimitOptions }, TimeSpan.FromSeconds(_options.CzarCacheTime), region); return(result); } }