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

jq动画效果网站济南专业的网站建设公司

jq动画效果网站,济南专业的网站建设公司,php建站视频教程,app开发比较好的公司目录 1.简介1.1.为什么需要限流?1.2.限流和熔断有什么区别#xff1f;1.3.限流和削峰有什么区别#xff1f;1.4 缓存#xff0c;降级#xff0c;限流简介 2.应用级限流2.1 控制并发数量2.2 控制访问速率2.2.1 令牌桶算法2.2.2 漏桶算法 3.分布式限流4.交流群 1.简介 接口… 目录 1.简介1.1.为什么需要限流?1.2.限流和熔断有什么区别1.3.限流和削峰有什么区别1.4 缓存降级限流简介 2.应用级限流2.1 控制并发数量2.2 控制访问速率2.2.1 令牌桶算法2.2.2 漏桶算法 3.分布式限流4.交流群 1.简介 接口限流是对某一时间窗口内的请求数进行限制以保持系统的可用性和稳定性防止因流量暴增而导致的系统运行缓慢或宕机。此外接口限流也可以通过限制每个用户或每个接口调用的频率和并发数来控制对服务资源的访问。 1.1.为什么需要限流? 大量正常用户高频访问导致服务器宕机 恶意用户高频访问导致服务器宕机 网页爬虫 ,对于这些情况我们需要对用户的访问进行限流访问 1.2.限流和熔断有什么区别 限流发生在流量进来之前超过的流量进行限制。 熔断是一种应对故障的机制发生在流量进来之后如果系统发生故障或者异常熔断会自动切断请求防止故障进一步扩展导致服务雪崩。 1.3.限流和削峰有什么区别 削峰是对流量的平滑处理通过缓慢地增加请求的处理速率来避免系统瞬时过载。 削峰大概就是水库把流量储存起来慢慢流限流大概就是闸口拒绝超出的流量。 1.4 缓存降级限流简介 缓存 缓存的目的是提升系统访问速度和增大系统处理容量降级 降级是当服务出现问题或者影响到核心流程时需要暂时屏蔽掉待高峰或者问题解决后再打开限流 限流的目的是通过对并发访问/请求进行限速或者对一个时间窗口内的请求进行限速来保护系统一旦达到限制速率则可以拒绝服务、排队或等待、降级等处理 2.应用级限流 2.1 控制并发数量 在Java中可以使用信号量Semaphore机制来控制并发数量。信号量是一个计数器用于限制对共享资源的访问。以下是一个使用信号量机制控制并发数量的示例 import java.util.concurrent.Semaphore; public class ConcurrencyControlExample { private static final int MAX_CONCURRENT_THREADS 5; // 最大并发线程数 private static Semaphore semaphore new Semaphore(MAX_CONCURRENT_THREADS); public static void main(String[] args) { for (int i 0; i 10; i) { new Thread(new WorkerThread( i)).start(); } } static class WorkerThread implements Runnable { private String command; public WorkerThread(String s) { this.command s; } Override public void run() { try { // 获取信号量如果信号量为0则当前线程需要等待 semaphore.acquire(); // 执行任务 System.out.println(Thread.currentThread().getName() 开始处理 command); processCommand(); System.out.println(Thread.currentThread().getName() 结束处理 command); } catch (InterruptedException e) { e.printStackTrace(); } finally { // 释放信号量允许其他线程获取信号量并执行任务 semaphore.release(); } } private void processCommand() { try { Thread.sleep(2000); // 模拟耗时任务 } catch (InterruptedException e) { e.printStackTrace(); } } } }2.2 控制访问速率 在工程实践中常见的是使用令牌桶算法来实现这种模式常用的限流算法有两种漏桶算法和令牌桶算法。 2.2.1 令牌桶算法 如图所示令牌桶算法的原理是系统会以一个恒定的速度往桶里放入令牌而如果请求需要被处理则需要先从桶里获取一个令牌当桶里没有令牌可取时则拒绝服务令牌桶算法通过发放令牌根据令牌的rate频率做请求频率限制容量限制等。 在Wikipedia上令牌桶算法是这么描述的 1、每过1/r秒桶中增加一个令牌。 2、桶中最多存放b个令牌如果桶满了新放入的令牌会被丢弃。 3、当一个n字节的数据包到达时消耗n个令牌然后发送该数据包。 4、如果桶中可用令牌小于n则该数据包将被缓存或丢弃。 令牌桶控制的是一个时间窗口内通过的数据量在API层面我们常说的QPS、TPS正好是一个时间窗口内的请求量或者事务量只不过时间窗口限定在1s罢了。以一个恒定的速度往桶里放入令牌而如果请求需要被处理则需要先从桶里获取一个令牌当桶里没有令牌可取时则拒绝服务。令牌桶的另外一个好处是可以方便的改变速度一旦需要提高速率则按需提高放入桶中的令牌的速率。 在我们的工程实践中通常使用Google开源工具包Guava提供的限流工具类RateLimiter来实现控制速率该类基于令牌桶算法来完成限流非常易于使用而且非常高效。如我们不希望每秒的任务提交超过1个 public static void main(String[] args) {String start new SimpleDateFormat(yyyy-MM-dd HH:mm:ss).format(new Date());RateLimiter limiter RateLimiter.create(1.0); // 这里的1表示每秒允许处理的量为1个for (int i 1; i 10; i) {double waitTime limiter.acquire(i);// 请求RateLimiter, 超过permits会被阻塞System.out.println(cutTime System.currentTimeMillis() call execute: i waitTime: waitTime);}String end new SimpleDateFormat(yyyy-MM-dd HH:mm:ss).format(new Date());System.out.println(start time: start);System.out.println(end time: end);}首先通过RateLimiter.create(1.0);创建一个限流器参数代表每秒生成的令牌数通过limiter.acquire(i);来以阻塞的方式获取令牌令牌桶算法允许一定程度的突发允许消费未来的令牌所以可以一次性消费i个令牌当然也可以通过tryAcquire(int permits, long timeout, TimeUnit unit)来设置等待超时时间的方式获取令牌如果超timeout为0则代表非阻塞获取不到立即返回支持阻塞或可超时的令牌消费。 从输出来看RateLimiter支持预消费比如在acquire(5)时等待时间是4秒是上一个获取令牌时预消费了3个两排固需要等待3*1秒然后又预消费了5个令牌以此类推。 ateLimiter通过限制后面请求的等待时间来支持一定程度的突发请求(预消费)在使用过程中需要注意这一点Guava有两种限流模式一种为稳定模式(SmoothBursty:令牌生成速度恒定平滑突发限流)一种为渐进模式(SmoothWarmingUp:令牌生成速度缓慢提升直到维持在一个稳定值平滑预热限流) 两种模式实现思路类似主要区别在等待时间的计算上。 SmoothBursty 模式RateLimiter limiter RateLimiter.create(5); RateLimiter.create(5)表示桶容量为5且每秒新增5个令牌即每隔200毫秒新增一个令牌limiter.acquire()表示消费一个令牌如果当前桶中有足够令牌则成功返回值为0如果桶中没有令牌则暂停一段时间比如发令牌间隔是200毫秒则等待200毫秒后再去消费令牌这种实现将突发请求速率平均为了固定请求速率。SmoothWarmingUp模式RateLimiter limiter RateLimiter.create(5,1000, TimeUnit.MILLISECONDS); 创建方式RateLimiter.create(doublepermitsPerSecond, long warmupPeriod, TimeUnit unit)permitsPerSecond表示每秒新增的令牌数warmupPeriod表示在从冷启动速率过渡到平均速率的时间间隔。速率是梯形上升速率的也就是说冷启动时会以一个比较大的速率慢慢到平均速率然后趋于平均速率梯形下降到平均速率。可以通过调节warmupPeriod参数实现一开始就是平滑固定速率。 注RateLimiter控制的是速率Samephore控制的是并发量。RateLimiter的原理就是令牌桶它主要由许可发出的速率来定义如果没有额外的配置许可证将按每秒许可证规定的固定速度分配许可将被平滑地分发若请求超过permitsPerSecond则RateLimiter按照每秒 1/permitsPerSecond 的速率释放许可。注意:RateLimiter适用于单体应用且RateLimiter不保证公平性访问。 使用上述方式使用RateLimiter的方式不够优雅自定义注解AOP的方式实现(适用于单体应用)详细见下面代码 自定义注解 import java.lang.annotation.*;/*** 自定义注解可以不包含属性成为一个标识注解*/ Inherited Documented Target({ElementType.METHOD, ElementType.FIELD, ElementType.TYPE}) Retention(RetentionPolicy.RUNTIME) public interface RateLimitAspect {}自定义切面类 import com.google.common.util.concurrent.RateLimiter; import com.test.cn.springbootdemo.util.ResultUtil; import net.sf.json.JSONObject; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component;import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletResponse; import java.io.IOException;Component Scope Aspect public class RateLimitAop {Autowiredprivate HttpServletResponse response;private RateLimiter rateLimiter RateLimiter.create(5.0); //比如说我这里设置并发数为5Pointcut(annotation(com.test.cn.springbootdemo.aspect.RateLimitAspect))public void serviceLimit() {}Around(serviceLimit())public Object around(ProceedingJoinPoint joinPoint) {Boolean flag rateLimiter.tryAcquire();Object obj null;try {if (flag) {obj joinPoint.proceed();//这个方法用于执行原来的方法或继续原来的控制流程。}else{String result JSONObject.fromObject(ResultUtil.success1(100, failure)).toString();output(response, result);}} catch (Throwable e) {e.printStackTrace();}System.out.println(flag flag ,obj obj);return obj;}public void output(HttpServletResponse response, String msg) throws IOException {response.setContentType(application/json;charsetUTF-8);ServletOutputStream outputStream null;try {outputStream response.getOutputStream(); //这行代码获取了与当前HTTP响应关联的输出流并将其赋值给outputStream变量。outputStream.write(msg.getBytes(UTF-8));//这部分将转换后的字节数组写入到之前获取的输出流中这意味着数据将被发送到客户端。} catch (IOException e) {e.printStackTrace();} finally {outputStream.flush();outputStream.close();}} }测试controller import com.test.cn.springbootdemo.aspect.RateLimitAspect; import com.test.cn.springbootdemo.util.ResultUtil; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody;Controller public class TestController {ResponseBodyRateLimitAspectRequestMapping(/test)public String test(){return ResultUtil.success1(1001, success).toString();}2.2.2 漏桶算法 漏桶算法思路很简单水请求先进入到漏桶里漏桶以一定的速度出水当水流入速度过大会直接溢出可以看出漏桶算法能强行限制数据的传输速率。 对于很多应用场景来说除了要求能够限制数据的平均传输速率外还要求允许某种程度的突发传输。这时候漏桶算法可能就不合适了令牌桶算法更为适合。 算法实现 import lombok.extern.slf4j.Slf4j; import org.junit.Test; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicInteger;// 漏桶 限流 Slf4j public class LeakBucketLimiter {// 计算的起始时间private static long lastOutTime System.currentTimeMillis();// 流出速率 每秒 2 次private static int leakRate 2;// 桶的容量private static int capacity 2;//剩余的水量private static AtomicInteger water new AtomicInteger(0);//返回值说明// false 没有被限制到// true 被限流public static synchronized boolean isLimit(long taskId, int turn) {// 如果是空桶就当前时间作为漏出的时间if (water.get() 0) {lastOutTime System.currentTimeMillis();water.addAndGet(1);return false;}// 执行漏水int waterLeaked ((int) ((System.currentTimeMillis() - lastOutTime) / 1000)) * leakRate;// 计算剩余水量int waterLeft water.get() - waterLeaked;water.set(Math.max(0, waterLeft));// 重新更新leakTimeStamplastOutTime System.currentTimeMillis();// 尝试加水,并且水还未满 放行if ((water.get()) capacity) {water.addAndGet(1);return false;} else {// 水满拒绝加水 限流return true;}}//线程池用于多线程模拟测试private ExecutorService pool Executors.newFixedThreadPool(10);Testpublic void testLimit() {// 被限制的次数AtomicInteger limited new AtomicInteger(0);// 线程数final int threads 2;// 每条线程的执行轮数final int turns 20;// 线程同步器CountDownLatch countDownLatch new CountDownLatch(threads);long start System.currentTimeMillis();for (int i 0; i threads; i) {pool.submit(() - {try {for (int j 0; j turns; j) {long taskId Thread.currentThread().getId();boolean intercepted isLimit(taskId, j);if (intercepted) {// 被限制的次数累积limited.getAndIncrement();}Thread.sleep(200);}} catch (Exception e) {e.printStackTrace();}//等待所有线程结束countDownLatch.countDown();});}try {countDownLatch.await();} catch (InterruptedException e) {e.printStackTrace();}float time (System.currentTimeMillis() - start) / 1000F;//输出统计结果log.info(限制的次数为 limited.get() ,通过的次数为 (threads * turns - limited.get()));log.info(限制的比例为 (float) limited.get() / (float) (threads * turns));log.info(运行的时长为 time);} }3.分布式限流 分布式限流 自定义注解拦截器Redis实现限流 (单体和分布式均适用全局限流) 自定义注解 Inherited Documented Target({ElementType.FIELD,ElementType.TYPE,ElementType.METHOD}) Retention(RetentionPolicy.RUNTIME) public interface AccessLimit {int limit() default 5; int sec() default 5; }拦截器 public class AccessLimitInterceptor implements HandlerInterceptor {Autowiredprivate RedisTemplateString, Integer redisTemplate; //使用RedisTemplate操作redisOverridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {if (handler instanceof HandlerMethod) {HandlerMethod handlerMethod (HandlerMethod) handler;Method method handlerMethod.getMethod();if (!method.isAnnotationPresent(AccessLimit.class)) {return true;}AccessLimit accessLimit method.getAnnotation(AccessLimit.class);if (accessLimit null) {return true;}int limit accessLimit.limit();int sec accessLimit.sec();String key IPUtil.getIpAddr(request) request.getRequestURI();Integer maxLimit redisTemplate.opsForValue().get(key);if (maxLimit null) {redisTemplate.opsForValue().set(key, 1, sec, TimeUnit.SECONDS); //set时一定要加过期时间} else if (maxLimit limit) {redisTemplate.opsForValue().set(key, maxLimit 1, sec, TimeUnit.SECONDS);} else {output(response, 请求太频繁!);return false;}}return true;}public void output(HttpServletResponse response, String msg) throws IOException {response.setContentType(application/json;charsetUTF-8);ServletOutputStream outputStream null;try {outputStream response.getOutputStream();outputStream.write(msg.getBytes(UTF-8));} catch (IOException e) {e.printStackTrace();} finally {outputStream.flush();outputStream.close();}}Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {}Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {} }controller: Controller RequestMapping(/activity) public class AopController {ResponseBodyRequestMapping(/seckill)AccessLimit(limit 4,sec 10) //加上自定义注解即可public String test (HttpServletRequest request,RequestParam(value username,required false) String userName){//TODO somethings……return hello world !;} }配置文件 /*springmvc的配置文件中加入自定义拦截器*/ mvc:interceptorsmvc:interceptormvc:mapping path/**/bean classcom.pptv.activityapi.controller.pointsmall.AccessLimitInterceptor//mvc:interceptor /mvc:interceptors4.交流群 后端专属技术群 我建了一个后端专属技术群欢迎从事编程开发、技术招聘HR进群也欢迎大家分享自己公司的内推信息相互帮助一起进步 文明发言以交流技术、职位内推、行业探讨为主 资源共享共同进步
http://www.zqtcl.cn/news/775852/

相关文章:

  • 公司请人做的网站打不开网页游戏大厅都有哪些
  • 网投网站制作中国建设教育协会报名网站
  • 做外贸需要做网站吗上海中建建筑设计院有限公司
  • 网站源代码免费下载苏州seo网络优化公司
  • 建网站跟建网店的区别pico笔克品牌介绍
  • 网站设计小技巧西安网站建设网站
  • 做听书网站怎么做网站留言板带后台模板
  • 石家庄网站建设王道下拉棒厦门橄榄网站建设
  • 赤峰网站建设培训建筑资格证书查询官网
  • 共和县公司网站建设seo网络推广招聘
  • 网站怎样做外链百度网站地图提交
  • 瑞安联科网站建设中国做网站公司排名
  • jsp网站开发详解 赵增敏jsp网站首页怎么做
  • 有哪些可以做图的网站啊莱芜金点子广告电子版2024
  • 免费营销型网站模版南宁比较有好的网站制作公司
  • 做外贸上什么网站什么什么设计英文网站
  • 嘿客免费网站建设网站对联图片
  • 一件代发48个货源网站韶关最新消息
  • 网站都需要备案吗安徽建设通网站
  • 外包公司 网站建设 深圳电子商务公司设计网站建设
  • 怎么添加网站背景音乐定制建站
  • 西安网站建设和推广公司php企业网站开发实训报告
  • 市网站制作番禺绿叶居
  • 网站漂浮物怎么做电子商务网站开发实训体会
  • 电商网站建设定制济南网站建设及推广
  • 网站标签化wordpress 输出评论内容 函数
  • 明星个人网站设计汕头网络推广公司
  • 深圳有哪些做网站公司好武夷山建设局网站
  • 怎么设立网站赚广告费一个网站可以做多少关键字
  • 网站刚建好怎么做能让百度收录成都定制网站建