当前位置: 首页 > news >正文

校园网站建设多少钱电子商务运营实务中网站开发流程

校园网站建设多少钱,电子商务运营实务中网站开发流程,4在线做网站,亚马逊电商平台入口作者#xff1a;非有 一、限流 1.1 为什么要进行限流#xff1f; 1.瞬时流量过高#xff0c;服务被压垮#xff1f; 2.恶意用户高频光顾#xff0c;导致服务器宕机#xff1f; 3.消息消费过快#xff0c;导致数据库压力过大#xff0c;性能下降甚至崩溃#xff1f…作者非有 一、限流 1.1 为什么要进行限流 1.瞬时流量过高服务被压垮 2.恶意用户高频光顾导致服务器宕机 3.消息消费过快导致数据库压力过大性能下降甚至崩溃 …… 1.2 什么是限流 限流是对某一时间窗口内的请求数进行限制保持系统的可用性和稳定性防止因流量暴增而导致的系统运行缓慢或宕机。 在高并发系统中出于系统保护角度考虑通常会对流量进行限流。 在分布式系统中高并发场景下为了防止系统因突然的流量激增而导致的崩溃同时保证服务的高可用性和稳定性限流是最常用的手段。 1.3 有哪些限流算法 常见的四种限流算法分别是固定窗口算法、滑动窗口算法、漏桶算法、令牌桶算法。 二、限流算法 2.1 固定窗口 实现原理 固定窗口又称固定窗口又称计数器算法Fixed Window限流算法是最简单的限流算法。 实现原理在指定周期内累加访问次数当访问次数达到设定的阈值时触发限流策略当进入下一个时间周期时进行访问次数的清零。如图所示我们要求 3 秒内的请求不要超过 150 次 代码实现 public class FixedWindowRateLimiter { Logger logger LoggerFactory.getLogger(FixedWindowRateLimiter.class); //时间窗口大小单位毫秒 long windowSize; //允许通过的请求数 int maxRequestCount; //当前窗口通过的请求数 AtomicInteger counter new AtomicInteger(0); //窗口右边界 long windowBorder; public FixedWindowRateLimiter(long windowSize, int maxRequestCount) { this.windowSize windowSize; this.maxRequestCount maxRequestCount; this.windowBorder System.currentTimeMillis() windowSize; } public synchronized boolean tryAcquire() { long currentTime System.currentTimeMillis(); if (windowBorder currentTime) { logger.info(window reset); do { windowBorder windowSize; } while (windowBorder currentTime); counter new AtomicInteger(0); }if (counter.intValue() maxRequestCount) { counter.incrementAndGet(); logger.info(tryAcquire success); return true; } else { logger.info(tryAcquire fail); return false; } }} 复制代码 优缺点 优点实现简单容易理解 缺点 1.限流不够平滑。例如限流是每秒 3 个在第一毫秒发送了 3 个请求达到限流窗口剩余时间的请求都将会被拒绝体验不好。 2.无法处理窗口边界问题。因为是在某个时间窗口内进行流量控制所以可能会出现窗口边界效应即在时间窗口的边界处可能会有大量的请求被允许通过从而导致突发流量。即如果第 2 到 3 秒内产生了 150 次请求而第 3 到 4 秒内产生了 150 次请求那么其实在第 2 秒到第 4 秒这两秒内就已经发生了 300 次请求了远远大于我们要求的 3 秒内的请求不要超过 150 次这个限制如下图所示 2.2 滑动窗口 实现原理 滑动窗口为固定窗口的改良版解决了固定窗口在窗口切换时会受到两倍于阈值数量的请求。在滑动窗口算法中窗口的起止时间是动态的窗口的大小固定。这种算法能够较好地处理窗口边界问题但是实现相对复杂需要记录每个请求的时间戳。 实现原理滑动窗口在固定窗口的基础上将时间窗口进行了更精细的分片将一个窗口分为若干个等份的小窗口每次仅滑动一小块的时间。每个小窗口对应不同的时间点拥有独立的计数器当请求的时间点大于当前窗口的最大时间点时则将窗口向前平移一个小窗口将第一个小窗口的数据舍弃第二个小窗口变成第一个小窗口当前请求放在最后一个小窗口整个窗口的所有请求数相加不能大于阈值。其中Sentinel 就是采用滑动窗口算法来实现限流的。如图所示 核心步骤 1.把 3 秒钟划分为 3 个小窗每个小窗限制请求不能超过 50 秒。 2.比如我们设置3 秒内不能超过 150 个请求那么这个窗口就可以容纳 3 个小窗并且随着时间推移往前滑动。每次请求过来后都要统计滑动窗口内所有小窗的请求总量。 代码实现 public class SlidingWindowRateLimiter { Logger logger LoggerFactory.getLogger(FixedWindowRateLimiter.class); //时间窗口大小单位毫秒 long windowSize; //分片窗口数 int shardNum; //允许通过的请求数 int maxRequestCount; //各个窗口内请求计数 int[] shardRequestCount; //请求总数 int totalCount; //当前窗口下标 int shardId; //每个小窗口大小毫秒 long tinyWindowSize; //窗口右边界 long windowBorder;public SlidingWindowRateLimiter(long windowSize, int shardNum, int maxRequestCount) { this.windowSize windowSize; this.shardNum shardNum; this.maxRequestCount maxRequestCount; this.shardRequestCount new int[shardNum]; this.tinyWindowSize windowSize / shardNum; this.windowBorder System.currentTimeMillis(); } public synchronized boolean tryAcquire() { long currentTime System.currentTimeMillis(); if (windowBorder currentTime) { logger.info(window reset); do { shardId (shardId) % shardNum; totalCount - shardRequestCount[shardId]; shardRequestCount[shardId] 0; windowBorder tinyWindowSize; } while (windowBorder currentTime); }if (totalCount maxRequestCount) { logger.info(tryAcquire success:{}, shardId); shardRequestCount[shardId]; totalCount; return true; } else { logger.info(tryAcquire fail); return false; } }} 复制代码 优缺点 优点解决了固定窗口算法的窗口边界问题避免突发流量压垮服务器。 缺点还是存在限流不够平滑的问题。例如限流是每秒 3 个在第一毫秒发送了 3 个请求达到限流剩余窗口时间的请求都将会被拒绝体验不好。 2.3 漏桶算法 实现原理 漏桶限流算法是一种常用的流量整形Traffic Shaping和流量控制Traffic Policing的算法它可以有效地控制数据的传输速率以及防止网络拥塞。 主要的作用 a.控制数据注入网络的速度。 b.平滑网络上的突发流量 实现原理 漏桶是一个很形象的比喻外部请求就像是水一样不断注入水桶中而水桶已经设置好了最大出水速率漏桶会以这个速率匀速放行请求而当水超过桶的最大容量后则被丢弃。不管上面的水流速度有多块漏桶水滴的流出速度始终保持不变。消息中间件就采用的漏桶限流的思想。如图所示 核心步骤 a.一个固定容量的漏桶按照固定速率出水处理请求 b.当流入水请求数量的速度过大会直接溢出请求数量超过限制则直接拒绝。 c.桶里的水请求不够则无法出水桶内没有请求则不处理。 代码实现 public class LeakyBucketRateLimiter { Logger logger LoggerFactory.getLogger(LeakyBucketRateLimiter.class); //桶的容量 int capacity; //桶中现存水量 AtomicInteger water new AtomicInteger(); //开始漏水时间 long leakTimestamp; //水流出的速率即每秒允许通过的请求数 int leakRate;public LeakyBucketRateLimiter(int capacity, int leakRate) { this.capacity capacity; this.leakRate leakRate; }public synchronized boolean tryAcquire() { //桶中没有水 重新开始计算 if (water.get() 0) { logger.info(start leaking); leakTimestamp System.currentTimeMillis(); water.incrementAndGet(); return water.get() capacity; } //先漏水计算剩余水量 long currentTime System.currentTimeMillis(); int leakedWater (int) ((currentTime - leakTimestamp) / 1000 * leakRate); logger.info(lastTime:{}, currentTime:{}. LeakedWater:{}, leakTimestamp, currentTime, leakedWater); //可能时间不足则先不漏水 if (leakedWater ! 0) { int leftWater water.get() - leakedWater; //可能水已漏光。设为0 water.set(Math.max(0, leftWater)); leakTimestamp System.currentTimeMillis(); } logger.info(剩余容量:{}, capacity - water.get()); if (water.get() capacity) { logger.info(tryAcquire sucess); water.incrementAndGet(); return true; } else { logger.info(tryAcquire fail); return false; } }} 复制代码 优缺点 优点 1.平滑流量。由于漏桶算法以固定的速率处理请求可以有效地平滑和整形流量避免流量的突发和波动类似于消息队列的削峰填谷的作用。 2.防止过载。当流入的请求超过桶的容量时可以直接丢弃请求防止系统过载。 缺点 1.无法处理突发流量由于漏桶的出口速度是固定的无法处理突发流量。例如即使在流量较小的时候也无法以更快的速度处理请求。 2.可能会丢失数据如果入口流量过大超过了桶的容量那么就需要丢弃部分请求。在一些不能接受丢失请求的场景中这可能是一个问题。 3.不适合速率变化大的场景如果速率变化大或者需要动态调整速率那么漏桶算法就无法满足需求。 4.资源利用率不管当前系统的负载压力如何所有请求都得进行排队即使此时服务器的负载处于相对空闲的状态这样会造成系统资源的浪费。 由于漏桶的缺陷比较明显所以在实际业务场景中使用的比较少。 2.4 令牌算法 实现原理 令牌桶算法是基于漏桶算法的一种改进主要在于令牌桶算法能够在限制服务调用的平均速率的同时还能够允许一定程度内的突发调用。 实现原理 1.系统以固定的速率向桶中添加令牌 2.当有请求到来时会尝试从桶中移除一个令牌如果桶中有足够的令牌则请求可以被处理或数据包可以被发送 3.如果桶中没有令牌那么请求将被拒绝 4.桶中的令牌数不能超过桶的容量如果新生成的令牌超过了桶的容量那么新的令牌会被丢弃。 5.令牌桶算法的一个重要特性是它能够应对突发流量。当桶中有足够的令牌时可以一次性处理多个请求这对于需要处理突发流量的应用场景非常有用。但是又不会无限制的增加处理速率导致压垮服务器因为桶内令牌数量是有限制的。 如图所示 代码实现 Guava 中的 RateLimiter 就是基于令牌桶实现的可以直接拿来使用。 优缺点 优点 1.可以处理突发流量令牌桶算法可以处理突发流量。当桶满时能够以最大速度处理请求。这对于需要处理突发流量的应用场景非常有用。 2.限制平均速率在长期运行中数据的传输率会被限制在预定义的平均速率即生成令牌的速率。 3.灵活性与漏桶算法相比令牌桶算法提供了更大的灵活性。例如可以动态地调整生成令牌的速率。 缺点 1.可能导致过载如果令牌产生的速度过快可能会导致大量的突发流量这可能会使网络或服务过载。 2.需要存储空间令牌桶需要一定的存储空间来保存令牌可能会导致内存资源的浪费。 3.实现稍复杂相比于计数器算法令牌桶算法的实现稍微复杂一些。 三、应用实践 Guava 中的 RateLimiter 就是基于令牌桶实现的可以直接拿来使用。所有整个实践是基于 Guava 的应用。 3.1 引入依赖 dependency groupIdcom.google.guava/groupId artifactIdguava/artifactId version32.1.3-jre/version/dependency 复制代码 3.2 API 直接使用 固定产生令牌 Test public void acquireTest() { //每秒固定生成5个令牌 RateLimiter rateLimiter RateLimiter.create(5); for (int i 0; i 10; i) { double time rateLimiter.acquire(); logger.info(等待时间{}s, time); } } 复制代码 结果 可以看到每 200ms 左右产生一个令牌并放行请求也就是 1 秒放行 5 个请求使用 RateLimiter 能够很好的实现单机的限流。 同时产生多个令牌 那么再回到我们前面提到的突发流量情况令牌桶是怎么解决的呢RateLimiter 中引入了一个预消费的概念。 申请令牌的数量不同不会影响这个申请令牌这个动作本身的响应时间acquire(1)和 acquire(1000)这两个请求会消耗同样的时间返回结果但是会影响下一个请求的响应时间。 如果一个消耗大量令牌的任务到达空闲的 RateLimiter会被立即批准执行但是当下一个请求进来时将会额外等待一段时间用来支付前一个请求的时间成本。 至于为什么要这么做通过举例来引申一下。当一个系统处于空闲状态时突然来了 1 个需要消耗 100 个令牌的任务那么白白等待 100 秒是毫无意义的浪费资源行为那么可以先允许它执行并对后续请求进行限流时间上的延长以此来达到一个应对突发流量的效果。 Test public void acquireSmoothly() { RateLimiter rateLimiter RateLimiter.create(5, 3, TimeUnit.SECONDS); long startTimeStamp System.currentTimeMillis(); for (int i 0; i 15; i) { double time rateLimiter.acquire(); logger.info(等待时间:{}s, 总时间:{}ms, time, System.currentTimeMillis() - startTimeStamp); } } 复制代码 结果: 可以看到令牌发放时间从最开始的 500ms 多逐渐缩短在 3 秒后达到了 200ms 左右的匀速发放。 总的来说基于令牌桶实现的 RateLimiter 功能还是非常强大的在限流的基础上还可以把请求平均分散在各个时间段内因此在单机情况下它是使用比较广泛的限流组件。 3.3 AOP 切面 第一步创建注解 Retention(RetentionPolicy.RUNTIME)Target({ElementType.METHOD})Documentedpublic interface Limit { // 资源主键 String key() default ; //最多访问次数,代表请求总数量 double permitsPerSeconds(); // 时间即timeout时间内,只允许有permitsPerSeconds个请求总数量访问超过的将被限制不能访问 long timeout(); //时间类型 TimeUnit timeUnit() default TimeUnit.MILLISECONDS;//提示信息 String msg() default 系统繁忙,请稍后重试;} 复制代码 第二步AOP 切面实现 AspectComponentpublic class LimitAspect { Logger logger LoggerFactory.getLogger(LimitAspect.class); private final MapString, RateLimiter limitMap Maps.newConcurrentMap();Around(annotation(com.alibaba.xxx.xxx.annotation.Limit)) public Object around(ProceedingJoinPoint joinPoint) throws Throwable { MethodSignature signature (MethodSignature) joinPoint.getSignature(); Method method signature.getMethod(); //拿limit的注解 Limit limit method.getAnnotation(Limit.class); if (limit ! null) { // key作用不同的接口不同的流量控制 String key limit.key(); RateLimiter rateLimiter; //验证缓存是否有命中key if (!limitMap.containsKey(key)) { //创建令牌桶 rateLimiter RateLimiter.create(limit.permitsPerSeconds()); limitMap.put(key, rateLimiter); logger.info(新建了令牌桶{},容量{}, key, limit.permitsPerSeconds()); } rateLimiter limitMap.get(key); //拿令牌 boolean acquire rateLimiter.tryAcquire(limit.timeout(), limit.timeUnit()); //拿不到令牌直接返回异常信息 if (!acquire) { logger.debug(令牌桶{},获取令牌失败, key); throw new RuntimeException(limit.msg()); } } return joinPoint.proceed(); }} 复制代码 第三步应用 Limit(key query,permitsPerSeconds 1,timeout 1,msg 触发接口限流请重试) 复制代码 第四步使用位置详解 若是放在 http 的 mapping 接口上返回如下 { timestamp: 2023-12-07 11:21:47, status: 500, error: Internal Server Error, path: /table/query} 复制代码 若是放在 service 服务的接口上返回如下 { code: -1, message: 触发接口限流请重试, data: fail} 复制代码 四、总结 本文介绍的实现方式属于应用级限制应用级限流方式只是单应用内的请求限流不能进行全局限流。假设将应用部署到多台机器我们需要分布式限流和接入层限流来解决这个问题。 总的来说要保证系统的抗压能力限流是一个必不可少的环节虽然可能会造成某些用户的请求被丢弃但相比于突发流量造成的系统宕机来说这些损失一般都在可以接受的范围之内。前面也说过限流可以结合熔断、降级一起使用多管齐下保证服务的可用性与健壮性。 相关资料 [01] 源码解析:高性能限流器 Guava RateLimiter https://zhuanlan.zhihu.com/p/358822328?utm_id0 [02] 拦截器版:使用 Guava 实现限流器 https://zhuanlan.zhihu.com/p/38100340
http://www.zqtcl.cn/news/561815/

相关文章:

  • 淘宝导购网站模版上海网站推广软件
  • 做影视网站引流湖北响应式网站建设费用
  • 网站统计cnzz网站空间有哪些
  • 泉州微信网站开发公司wordpress头像解决
  • 湛江网站建设皆选小罗24专业网站建设 福田
  • 厦门哪些做鲜花的网站门户网站开发设计报告
  • asp.net网站设计分工天津网站开发贴吧
  • 做多语言网站教程南宁vi设计公司
  • 百度联盟 网站备案wordpress 吾爱破解
  • 山西省建设厅网站首页网络营销推广为什么效果不好
  • 建材做网站好吗长沙做网站微联讯点不错
  • 建设小型网站分类门户网站系统
  • 文化馆网站数字化建设介绍138ip地址查询网站
  • 卖汽车的网站怎么做的建设服装网站的论文
  • 网络推广哪个网站好网站建设最低多少钱
  • 怎么在自己电脑做网站北京赛车网站开发
  • 门户网站内容wordpress上下页
  • 长安做英文网站营销型网站搭建
  • 网站开发交接清单seo排名优化方法
  • 各学院二级网站建设通报wordpress注册评论
  • 南通公司做网站无人在线完整免费高清观看
  • 廊坊网站推广局域网网站建设的步骤过程
  • 如何在工信部网站注册简易网页设计代码
  • 做石油系统的公司网站做艺术品展览的网站
  • 枣庄公司网站建设珠海蓝迪装饰设计工程有限公司
  • 广州企业网站营销电话成都网站建设制作设计
  • 求个网站带图片素材域名及密码登录域名管理网站
  • 文交所网站开发wordpress页面编辑插件
  • 丹徒网站建设价格做矿产公司的网站
  • 北京的制作网站的公司在哪里软件程序员