/// <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);
        }
Esempio n. 2
0
        /// <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);
            }
        }
Esempio n. 4
0
        /// <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}");
        }
Esempio n. 10
0
        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);
        }
Esempio n. 11
0
        /// <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);
            }
        }
Esempio n. 12
0
        /// <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);
            }
        }
Esempio n. 13
0
        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);
            }
        }