1.重复开店被限流,再换网线电脑,还有用吗?

2.使用 Nginx 限流

3.分布式解决方案之:限流

重复开店被限流,再换网线电脑,还有用吗?

电脑系统限流-电脑网络限流了怎么办怎么恢复限流

不用,太麻烦,又浪费钱。

有两点 。1. 现在在一台电脑上认证过店铺的再认证新店铺有一定的几率不会通过, 会提示安全问题。 大家深受其害。! 这个倒不是大问题, 用朋友没有注册过店铺的电脑 一认证立马通过。 2 。 严重违规的店铺在电脑上会 有记录, 这点就是洗系统也没用。 我洗过系统。 所以你除非卖的是正品之类没有违规的,那么你就可以继续使用。 要是还卖那些容易被查的东西,那么最好换个, 因为你这个电脑系统被监控住的。

使用 Nginx 限流

Nginx不仅可以做Web服务器、做反向代理、负载均衡,还可以做限流系统。此处我们就Nginx为例,介绍一下如何配置一个限流系统。

Nginx使用的限流算法是漏桶算法。

(1)安装Nginx。

如果你的Linux是Ubuntu或Debian,使用apt-get安装,在命令行中输入以下命令:

如果是CentOS,使用yum安装,在命令行中输入以下命令:

(2)找到Nginx所使用的配置文件所在的位置。在Ubuntu和Debian是在如下位置:

而CentOS则是在如下位置:

(3)在块中,配置基础的限流配置:

其中4到8行定义的是一个服务器接口。而第2行和第6行配合完成了一个限流设置,下面解释一下这两行做的事情:

limit_req_zone命令在Nginx的配置文件中专门用于定义限流,它必须被放在块中,否则无法生效,因为该命令只在中被定义。

该字段包含三个参数:

第一个参数,就是键(key),即值$binary_remote_addr所在的位置,它代表的是我们的限流系统限制请求所用的键。

此处,我们使用了$binary_remote_addr,它是Nginx内置的一个值,代表的是客户端的IP地址的二进制表示。因此换言之,我们的示例配置,是希望限流系统以客户端的IP地址为键进行限流。

对Nginx有经验的读者可能还知道有一个Nginx内置值为binary_remote_addr是Nginx的社区推荐用值,因为它是二进制表达,占用的空间一般比字符串表达的$remote_addr要短一些,在寸土寸金的限流系统中尤为重要。

第二个参数是限流配置的共享内存占用(zone)。为了性能优势,Nginx将限流配置放在共享内存中,供所有Nginx的进程使用,因为它占用的是内存,所以我们希望开发者能够指定一个合理的、既不浪费又能存储足够信息的空间大小。根据实践经验,1MB的空间可以储存16000个IP地址。

该参数的语法是用冒号隔开的两个部分,第一部分是给该部分申请的内存一个名字,第二部分是我们希望申请的内存大小。

因此,在该声明中,我们声明了一个名叫mylimit(我的限制)的内存空间,然后它的大小是10M,即可以存储160000个IP地址,对于实验来说足够了。

第三个配置就是访问速率(rate)了,格式是用左斜杠隔开的请求数和时间单位。这里的访问速率就是最大速率,因此10r/s就是每秒10个请求。通过这台Nginx服务器访问后端服务器的请求速率无法超过每秒10个请求。

注意到第5行声明了一个位置/test/,因此我们第6行的配置就是针对这个的,通俗地说,我们在第6行的配置是针对特定API的,这个API就是路径为/test/的API,而其真正路径就是第8行声明的 ://backend 。注意,这个URL是不存在的,实际操作中,读者需要将它换成你已经开发好的业务逻辑所在的位置,Nginx在这里的作用只是一个反向代理,它自己本身没有。

第6行中,我们使用limit_req命令,声明该API需要一个限流配置,而该限流配置所在位置(zone)就是mylimit。

这样一来,所有发往该API的请求会先读到第6行的限流配置,然后根据该限流配置mylimit的名称找到声明在第2行的参数,然后决定该请求是否应该被拒绝。

但是这样还不够。不要忘了,Nginx使用的漏桶算法,不是时间窗口算法,我们前文介绍中说过,漏桶算法是有两个参数可以配置的!

(4)配置峰值。Nginx漏桶算法的峰值属性在API中设置。参数名为burst。如下:

在第6行中,我们只需要在声明limit_req的同时,指定burst就可以了,此处我们指定burst为20,即漏桶算法中我们的“桶”最多可以接受20个请求。

这样一个Nginx的限流系统就配置完毕了,但实际操作中,我们还可能需要很多别的功能,下面笔者就介绍几个很有用的配置技巧。

相对于传统的漏桶算法慢吞吞地转发请求的缺陷,Nginx实现了一种漏桶算法的优化版,允许开发者指定快速转发,而且还不影响正常的限流功能。开发者只需要在指定limit_req的一行中指定burst之后指定另一个参数nodelay,就可以在请求总数没有超过burst指定值的情况下,迅速转发所有请求了。如下所示:

您可能会担忧:这种情况下,会不会出现所有请求都被快速转发,然后接下来又有没有超过burst数量的请求出现,再次被快速转发,就好像固定窗口算法的漏洞一样,从而超过我们本来希望它能限制到的上限数量呢?答案是不会。Nginx的快速转发是这样实现的:

举例而言,配置如上所示,如在某个瞬时有25个请求进入系统,Nginx会先转发20个(或21个,取决于瞬时情况),然后拒绝剩下的4个请求,并将当前桶中数量标为0,然后接下来的每100毫秒,缓慢恢复1个空位。

这样我们可以看到,Nginx既做到了快速转发消息,又不会让后端服务器承担过多的流量。

限流系统会提前拒绝请求,因此,我们在业务服务器上是肯定看不到这些请求的。如我们收到一个报告说某用户在使用网站的时候出现错误,但是我们在业务服务器上又找不到相关的日志,我们如何确定是不是限流造成的呢?

只有限流系统的日志才能说明问题。因此,我们需要Nginx打印出它拒绝掉的请求的信息。但同时,Nginx打印的限流日志默认是错误(error),如果我们设置了一个基于日志错误扫描的警报,它扫到的限流错误,真的是我们希望给自己发警报的情况吗?

配置请求的位置就在中,使用的命令是limit_req_log_level,如下:

在第7行中,我们将Nginx的日志改为了警告(warn)。

限流的HTTP标准响应状态码是429,但是如果读者拿上述的配置文件直接去测试,会发现Nginx返回的是503(服务不可用)。到底应该返回什么状态码,是一个偏程序哲学的问题,此处我们不讨论,我们只讨论:如何让Nginx返回我们指定的状态码?

答案也是在同一个中,它的配置命令是limit_req_status,然后我们指定它为429即可:

除了以上功能以外,Nginx还支持很多复杂先进的限流功能,可以访问 s://docs.nginx/nginx/admin-guide/security-controls/controlling-access-proxied-/ 作进一步的了解。

分布式解决方案之:限流

限流在日常生活中限流很常见,例如去有些景区玩,每天售卖的门票数是有限的,例如 2000 张,即每天最多只有 2000 个人能进去游玩。那在我们工程上限流是什么呢?限制的是 「流」,在不同场景下「流」的定义不同,可以是 每秒请求数、每秒事务处理数、网络流量 等等。通常意义我们说的限流指代的是限制到达系统的并发请求数,使得系统能够正常的处理部分用户的请求,来保证系统的稳定性。

日常的业务上有类似秒杀活动、双十一大促或者突发新闻等场景,用户的流量突增,后端服务的处理能力是有限的,如果不能处理好突发流量,后端服务很容易就被打垮。另外像爬虫之类的不正常流量,我们对外暴露的服务都要以最大恶意为前提去防备调用者。我们不清楚调用者会如何调用我们的服务,设某个调用者开几十个线程一天二十四小时疯狂调用你的服务,如果不做啥处理咱服务基本也玩完了,更胜者还有ddos攻击。

对于很多第三方开放平台来说,不仅仅要防备不正常流量,还要保证的公平利用,一些接口不可能一直都被一个客户端占着,也需要保证其他客户端能正常调用。

计数器限流也就是最简单的限流算法就是计数限流了。例如系统能同时处理 100 个请求,保存一个计数器,处理了一个请求,计数器就加一,一个请求处理完毕之后计数器减一。每次请求来的时候看看计数器的值,如果超过阈值就拒绝。计数器的值要是存内存中就算单机限流算法,如果放在第三方存储里(例如Redis中)集群机器访问就算分布式限流算法。

一般的限流都是为了限制在指定时间间隔内的访问量,因此还有个算法叫固定窗口。

它相比于计数限流主要是多了个时间窗口的概念,计数器每过一个时间窗口就重置。规则如下:

这种方式也会面临一些问题,例如固定窗口临界问题:设系统每秒允许 100 个请求,设第一个时间窗口是 0-1s,在第 0.55s 处一下次涌入 100 个请求,过了 1 秒的时间窗口后计数清零,此时在 1.05 s 的时候又一下次涌入100个请求。虽然窗口内的计数没超过阈值,但是全局来看在 0.55s-1.05s 这 0.1 秒内涌入了 200 个请求,这其实对于阈值是 100/s 的系统来说是无法接受的。

为了解决这个问题,业界又提出另外一种限流算法,即滑动窗口限流。

滑动窗口限流解决固定窗口临界值的问题,可以保证在任意时间窗口内都不会超过阈值。相对于固定窗口,滑动窗口除了需要引入计数器之外还需要记录时间窗口内每个请求到达的时间点,因此对内存的占用会比较多。

规则如下,设时间窗口为 1 秒:

但是滑动窗口和固定窗口都无法解决短时间之内集中流量的冲击问题。 我们所想的限流场景是: 每秒限制 100 个请求。希望请求每 10ms 来一个,这样我们的流量处理就很平滑,但是真实场景很难控制请求的频率,因为可能就算我们设置了1s内只能有100个请求,也可能存在 5ms 内就打满了阈值的情况。当然对于这种情况还是有变型处理的,例如设置多条限流规则。不仅限制每秒 100 个请求,再设置每 10ms 不超过 2 个,不过带来的就是比较差的用户体验。

而漏桶算法,可以解决时间窗口类的痛点,使得流量更加平滑。

如下图所示,水滴持续滴入漏桶中,底部定速流出。如果水滴滴入的速率大于流出的速率,当存水超过桶的大小的时候就会溢出。

规则如下:

水滴对应的就是请求。

与线程池实现的方式方式如出一辙。

面对突发请求,服务的处理速度和平时是一样的,这并非我们实际想要的。我们希望的是在突发流量时,在保证系统平稳的同时,也要尽可能提升用户体验,也就是能更快地处理并响应请求,而不是和正常流量一样循规蹈矩地处理。

而令牌桶在应对突击流量的时候,可以更加的“激进”。

令牌桶其实和漏桶的原理类似,只不过漏桶是定速地流出,而令牌桶是定速地往桶里塞入令牌,然后请求只有拿到了令牌才能通过,之后再被服务器处理。

当然令牌桶的大小也是有限制的,设桶里的令牌满了之后,定速生成的令牌会丢弃。

规则:

令牌桶的原理与JUC的Semaphore 信号量很相似,信号量可控制某个被同时访问的个数,其实和拿令牌思想一样,不同的是一个是拿信号量,一个是拿令牌。信号量用完了返还,而令牌用了不归还,因为令牌会定时再填充。

对比漏桶算法可以看出 令牌桶更适合应对突发流量 ,如桶内有 100 个令牌,那么这100个令牌可以马上被取走,而不像漏桶那样匀速的消费。不过上面批量获取令牌也会致使一些新的问题出现,比如导致一定范围内的限流误差,举个例子你取了 10 个此时不用,等下一秒再用,那同一时刻集群机器总处理量可能会超过阈值,所以现实中使用时,可能不会去考虑redis频繁读取问题,转而直接用一次获取一个令牌的方式,具体用哪种策略还是要根据真实场景而定。

1、计数器 VS 固定窗口 VS 滑动窗口

2、漏桶算法 VS 令牌桶算法

总的来说

单机限流和分布式限流本质上的区别在于 “阈值” 存放的位置,单机限流就是“阀值”存放在单机部署的服务/内存中,但我们的服务往往是集群部署的,因此需要多台机器协同提供限流功能。像上述的计数器或者时间窗口的算法,可以将计数器存放至 Redis 等分布式 K-V 存储中。又如滑动窗口的每个请求的时间记录可以利用 Redis 的 zset 存储,利用 ZREMRANGEBYSCORE 删除时间窗口之外的数据,再用 ZCARD 计数,

可以看到,每个限流都有个阈值,这个阈值如何定是个难点。定大了服务器可能顶不住,定小了就“误杀”了,没有利用最大化,对用户体验不好。一般的做法是限流上线之后先预估个大概的阈值,然后不执行真正的限流操作,而是取日志记录方式,对日志进行分析查看限流的效果,然后调整阈值,推算出集群总的处理能力,和每台机子的处理能力(方便扩缩容)。然后将线上的流量进行重放,测试真正的限流效果,最终阈值确定,然后上线。

其实真实的业务场景很复杂,需要限流的条件和很多,每个限流要求还不一样。

一般而言,我们不需要自己实现限流算法来达到限流的目的,不管是接入层限流还是细粒度的接口限流,都有现成的轮子使用,其实现也是用了上述我们所说的限流算法。

具体的使用还是很简单的,有兴趣的同学可以自行搜索,对内部实现感兴趣的同学可以下个源码看看,学习下生产级别的限流是如何实现的。

限流具体应用到工程还是有很多点需要考虑的,并且限流只是保证系统稳定性中的一个环节,还需要配合降级、熔断等相关内容。