Ejemplo n.º 1
0
        public async Task OnRequestSuccessAsync(HttpResponse response)
        {
            var httpMessage = response.HttpResponseMessage;

            Uri requestUri = httpMessage.RequestMessage.RequestUri;

            string[] paths = requestUri.AbsolutePath.Split('/');
            string   key   = GetCacheKey(paths[2], paths[3]);

            if (httpMessage.Headers.Contains(LimitHeader))
            {
                var ratelimit = new Ratelimit();
                if (httpMessage.Headers.TryGetValues(RemainingHeader, out var values))
                {
                    ratelimit.Remaining = int.Parse(values.FirstOrDefault());
                }

                if (httpMessage.Headers.TryGetValues(LimitHeader, out var limitValues))
                {
                    ratelimit.Limit = int.Parse(limitValues.FirstOrDefault());
                }

                if (httpMessage.Headers.TryGetValues(ResetHeader, out var resetValues))
                {
                    ratelimit.Reset = int.Parse(resetValues.FirstOrDefault());
                }

                if (httpMessage.Headers.TryGetValues(GlobalHeader, out var globalValues))
                {
                    ratelimit.Global = int.Parse(globalValues.FirstOrDefault());
                }

                await cache.UpsertAsync(key, ratelimit);
            }
        }
Ejemplo n.º 2
0
        public void IsRatelimited()
        {
            var rateLimit = new Ratelimit
            {
                Remaining = 5,
                Reset     = (DateTimeOffset.Now + TimeSpan.FromSeconds(1)).ToUnixTimeSeconds()
            };

            Assert.False(Ratelimit.IsRatelimited(rateLimit));

            rateLimit.Remaining = 0;

            Assert.True(Ratelimit.IsRatelimited(rateLimit));

            rateLimit.Global    = 0;
            rateLimit.Remaining = 3;

            Assert.True(Ratelimit.IsRatelimited(rateLimit));

            rateLimit.Global    = null;
            rateLimit.Remaining = 0;
            rateLimit.Reset     = 0;

            Assert.False(Ratelimit.IsRatelimited(rateLimit));
        }
Ejemplo n.º 3
0
        public static void Main(string[] args)
        {
            //using (var ws = new WebSocket("wss://stream.binance.com:9443/ws"))
            //{
            //    var count = 0;
            //    ws.OnMessage += (sender, e) =>
            //    {
            //        Console.WriteLine(e.Data);
            //        count++;
            //        if (count == 2) ws.Close();

            //    };
            //    ws.OnOpen += (sender, e) => Console.WriteLine("连接成功!");
            //    ws.SetProxy("http://127.0.0.1:10809", "", "");
            //    ws.Connect();
            //    //ws.Send(@"{ ""method"": ""SUBSCRIBE"", ""params"": [ ""btcusdt@bookTicker""], ""id"": 1 }");
            //    ws.Send(@"{ ""method"": ""SUBSCRIBE"", ""params"": [ ""!miniTicker@arr""], ""id"": 1 }");
            //    //ws.Send(@"{ ""method"": ""SUBSCRIBE"", ""params"": [ ""btcusdt@kline_4h""], ""id"": 1 }");
            //    //ws.Close();
            //    Console.ReadKey(true);
            //}


            var ratelimit = new Ratelimit()
            {
                rateLimitType = "REQUEST_WEIGHT",
                interval      = "MINUTE",
                intervalNum   = 1,
                limit         = 1200
            };

            PreloadResource.ExchangeInfo            = new ExchangeInfo();
            PreloadResource.ExchangeInfo.rateLimits = new Ratelimit[] { ratelimit };

            //while (true)
            //{
            //    var random = new Random();
            //    var r = random.Next(50);
            //    RequestLimitUtil.RequestBlock(r);
            //    Thread.Sleep(1000);
            //}


            var tslist = new List <Task>();

            for (int i = 0; i < 1000; i++)
            {
                var ts = new Task(() =>
                {
                    var random = new Random();
                    var r      = random.Next(50);
                    RequestLimitUtil.RequestBlock(r);
                });
                tslist.Add(ts);
                ts.Start();
            }

            Console.ReadLine();
        }
Ejemplo n.º 4
0
        public async Task <bool> CanStartRequestAsync(RequestMethod method, string requestUri)
        {
            string key = GetCacheKey(requestUri.Split('/')[0], requestUri.Split('/')[1]);

            Ratelimit rateLimit = await cache.GetAsync <Ratelimit>(key);

            rateLimit.Remaining--;

            await cache.UpsertAsync(key, rateLimit);

            return(!rateLimit.IsRatelimited());
        }
Ejemplo n.º 5
0
        public void Test()
        {
            var ratelimit = new Ratelimit()
            {
                rateLimitType = "REQUEST_WEIGHT",
                interval      = "MINUTE",
                intervalNum   = 1,
                limit         = 1200
            };

            LoadedResource.ExchangeInfo.rateLimits = new Ratelimit[] { ratelimit };

            while (true)
            {
                var random = new Random();
                var r      = random.Next(50);
                RequestLimitUtil.RequestBlock(r);
                Thread.Sleep(1000);
            }
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Configures the database and sets it up
        /// </summary>
        public override void AfterConfigure()
        {
            // If we share the database with another queue, share the connection as well
            lock (_lock)
                foreach (var m in _modules)
                {
                    if (m.Value.ConnectionClass == this.ConnectionClass && m.Value.ConnectionString == this.ConnectionString)
                    {
                        m_con = m.Value.m_con;
                        break;
                    }
                }

            // Initialize
            base.AfterConfigure();

            // The CLI will help us a little bit
            if (string.IsNullOrWhiteSpace(this.SelfUrl))
            {
                this.SelfUrl = Environment.GetEnvironmentVariable("CEEN_SELF_HTTPS_URL");
            }
            if (string.IsNullOrWhiteSpace(this.SelfUrl))
            {
                this.SelfUrl = Environment.GetEnvironmentVariable("CEEN_SELF_HTTP_URL");
            }

            if (string.IsNullOrWhiteSpace(this.SelfUrl))
            {
                throw new Exception($"The QueueModule needs to know the server url to call back to, please set the {nameof(SelfUrl)} variable");
            }

            // Remove trailing slashes to make it easier to concatenate strings
            this.SelfUrl = this.SelfUrl.Trim().TrimEnd('/');

            if (string.IsNullOrWhiteSpace(Name))
            {
                throw new Exception("The name of the queue cannot be empty");
            }
            if (string.IsNullOrWhiteSpace(SecureHeaderName))
            {
                throw new Exception("The secure header name cannot be empty");
            }
            if (string.IsNullOrWhiteSpace(Ratelimit))
            {
                throw new Exception("The rate limit value cannot be empty");
            }
            if (string.IsNullOrWhiteSpace(RetryBackoff))
            {
                throw new Exception("The retry backoff value cannot be empty");
            }
            if (MaxRetries <= 0)
            {
                throw new Exception("Invalid max retry count");
            }

            // Assign a random value
            if (string.IsNullOrWhiteSpace(SecureHeaderValue))
            {
                SecureHeaderValue = Guid.NewGuid().ToString();
            }

            var rl = Ratelimit.Split(new char[] { '/' }, 2);

            if (rl.Length != 2 || rl[0].Length < 1 || rl[1].Length < 1)
            {
                throw new Exception("Unable to parse the ratelimit");
            }
            if (rl[1][0] < '0' || rl[1][0] > '9')
            {
                rl[1] = '1' + rl[1];
            }

            m_ratelimitcount  = int.Parse(rl[0]);
            m_ratelimitWindow = ParseUtil.ParseDuration(rl[1]);
            if (m_ratelimitWindow.Ticks <= 0 || m_ratelimitcount <= 0)
            {
                throw new Exception("Invalid rate limit");
            }

            var rb = RetryBackoff.Split(new char[] { ';' }, 3);
            var re = new System.Text.RegularExpressions.Regex(@"(?<mode>[exp|lin|exponential|linear])\w+(?<rate>.+)");

            // Only have the exp/lin, compute start and limit
            if (rb.Length == 1)
            {
                var m = re.Match(rb[0]);
                if (!m.Success)
                {
                    throw new Exception("Unable to parse the backoff");
                }
                var duration = m.Groups["rate"].Value;
                var ps       = ParseUtil.ParseDuration(duration);
                rb = new string[] { duration, rb[0], $"{ps.TotalSeconds * MaxRetries}s" };
            }
            else if (rb.Length == 2)
            {
                // First is exp/lin, last is limit, compute start
                var m = re.Match(rb[0]);
                if (m.Success)
                {
                    rb = new string[] { m.Groups["rate"].Value, rb[0], rb[1] };
                }
                // Second is exp/lin, first is start, compute last
                else
                {
                    m = re.Match(rb[1]);
                    if (!m.Success)
                    {
                        throw new Exception("Unable to parse the backoff");
                    }

                    var duration = m.Groups["rate"].Value;
                    var ps       = ParseUtil.ParseDuration(duration);
                    rb = new string[] { rb[0], rb[1], $"{ps.TotalSeconds * MaxRetries}s" };
                }
            }

            var mx = re.Match(rb[1]);

            if (!mx.Success)
            {
                throw new Exception("Unable to parse the backoff");
            }

            m_initialbackoff     = ParseUtil.ParseDuration(rb[0]);
            m_maximumbackoff     = ParseUtil.ParseDuration(rb[2]);
            m_additionalbackoff  = ParseUtil.ParseDuration(mx.Groups["rate"].Value);
            m_exponentialBackoff = mx.Groups["mode"].Value.StartsWith("exp", true, System.Globalization.CultureInfo.InvariantCulture);

            if (m_initialbackoff.Ticks < 0 || m_maximumbackoff.Ticks < 0 || m_additionalbackoff.Ticks < 0)
            {
                throw new Exception("Invalid back-off values");
            }

            m_ratelimiter = new RateLimit(m_ratelimitcount, m_ratelimitWindow);

            lock (_lock)
                _modules.Add(Name, this);

            // Activate the runner
            SignalRunner();
        }