Spring Cloud (四、服务熔断降级-HyStrix)
spring cloud
概述
分布式系统面临的问题
复杂分布式体系结构中的应用程序有数十个依赖关系,每个依赖关系在某些时候将不可避免地失败。
服务雪崩
多个微服务之间调用的时候,假设微服务A调用微服务B和微服务C,微服务B和微服务C又调用其它的微服务,这就是所谓的“扇出”。如果扇出的链路上某个微服务的调用响应时间过长或者不可用,对微服务A的调用就会占用越来越多的系统资源,进而引起系统崩溃,所谓的“雪崩效应”.
对于高流量的应用来说,单一的后端依赖可能会导致所有服务器上的所有资源都在几秒钟内饱和。比失败更糟糕的是,这些应用程序还可能导致服务之间的延迟增加,备份队列,线程和其他系统资源紧张,导致整个系统发生更多的级联故障。这些都表示需要对故障和延迟进行隔离和管理,以便单个依赖关系的失败,不能取消整个应用程序或系统。
所以,
通常当你发现一个模块下的某个实例失败后,这时候这个模块依然还会接收流量,然后这个有问题的模块还调用了其他的模块,这样就会发生级联故障,或者叫雪崩。
如何使用HyStrix解决问题
Hystrix是一个用于处理分布式系统的延迟和容错的开源库,在分布式系统里,许多依赖不可避免的会调用失败,比如超时、异常等,Hystrix能够保证在一个依赖出问题的情况下,不会导致整体服务失败,避免级联故障,以提高分布式系统的弹性。
“断路器”本身是一种开关装置,当某个服务单元发生故障之后,通过断路器的故障监控(类似熔断保险丝),向调用方返回一个符合预期的、可处理的备选响应(FallBack),而不是长时间的等待或者抛出调用方无法处理的异常,这样就保证了服务调用方的线程不会被长时间、不必要地占用,从而避免了故障在分布式系统中的蔓延,乃至雪崩。
HyStrix能做什么:
- 服务降级
- 服务熔断
- 接近实时的监控
官网资料:
https://github.com/Netflix/Hystrix/wiki/How-To-Use
目前Hystrix官宣,停更进维
,后续使用resilience4j代替,但是国内厂商大部分使用的都是sentienl,后续会进行sentienl的教学。
Hystrix重要概念
服务降级
哪些情况会出发降级,程序运行异常、超时、服务熔断触发服务降级、线程池/信号量打满也会导致服务降级等等…
这时,我们不让客户端等待并立刻返回一个友好提示:“服务器忙,请稍后再试。”。
服务熔断
类比保险丝达到最大服务访问后,直接拒绝访问,拉闸限电,然后调用服务降级的方法并返回友好提示,服务的降级->进而熔断->恢复调用链路。
熔断机制概述
熔断机制是应对雪崩效应的一种微服务链路保护机制。当扇出链路的某个微服务出错不可用或者响应时间太长时,
会进行服务的降级,进而熔断该节点微服务的调用,快速返回错误的响应信息。
当检测到该节点微服务调用响应正常后,恢复调用链路。
在Spring Cloud框架里,熔断机制通过Hystrix实现。Hystrix会监控微服务间调用的状况,
当失败的调用到一定阈值,缺省是5秒内20次调用失败,就会启动熔断机制。熔断机制的注解是@HystrixCommand。
https://martinfowler.com/bliki/CircuitBreaker.html
服务限流
秒杀高并发等操作,严禁一窝蜂的过来拥挤,大家排队,一秒钟N个,有序进行。
hystrix案例-服务降级
新建cloud-provider-hystrix-payment8001项目
POM
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>com.atguigu.springcloud</groupId><artifactId>cloud2020</artifactId><version>1.0-SNAPSHOT</version></parent><artifactId>cloud-provider-hystrix-payment8001</artifactId><packaging>jar</packaging><dependencies><!--hystrix--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-hystrix</artifactId></dependency><!--eureka client--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency><!--web--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency><dependency><!-- 引入自己定义的api通用包,可以使用Payment支付Entity --><groupId>com.atguigu.springcloud</groupId><artifactId>cloud-api-commons</artifactId><version>${project.version}</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><scope>runtime</scope><optional>true</optional></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies></project>
YML
server:port: 8001spring:application:name: cloud-provider-hystrix-paymenteureka:client:register-with-eureka: truefetch-registry: trueservice-url:#defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eurekadefaultZone: http://eureka7001.com:7001/eureka
主启动
package com.atguigu.springcloud;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;/*** @auther untifa* @create 2024-12-20 10:01:27*/
@SpringBootApplication
@EnableEurekaClient //本服务启动后会自动注册进eureka服务中
@EnableCircuitBreaker
public class PaymentHystrixMain8001
{public static void main(String[] args){SpringApplication.run(PaymentHystrixMain8001.class,args);}
}
@EnableCircuitBreaker,主启动加上这个注解,启用服务降级
业务类
package com.atguigu.springcloud.service;import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import org.springframework.stereotype.Service;import java.util.concurrent.TimeUnit;/****/
@Service
public class PaymentService {/*** 正常访问,不会报错* @param id* @return*/public String paymentInfo_OK(Integer id) {return "线程池:" + Thread.currentThread().getName() + " paymentInfo_OK,id: " + id;}/*** 超时访问,演示降级* @param id* @return*/@HystrixCommand(fallbackMethod = "paymentInfo_TimeOutHandler" , commandProperties ={ @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds" , value = "3000")})public String paymentInfo_TimeOut(Integer id) {try {TimeUnit.SECONDS.sleep(5);} catch (InterruptedException e) {throw new RuntimeException(e);}return "线程池:" + Thread.currentThread().getName() + " paymentInfo_TimeOut,id: " + id;}public String paymentInfo_TimeOutHandler(Integer id){return "/(ㄒoㄒ)/调用支付接口超时或异常:\t"+ "\t当前线程池名字" + Thread.currentThread().getName();}}
业务类启用@HystrixCommand注解,报异常后如何处理,一旦调用服务方法失败并抛出了错误信息后,会自动调用@HystrixCommand标注好的fallbackMethod调用类中的指定方法。
package com.atguigu.springcloud.controller;import com.atguigu.springcloud.service.PaymentService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;@RestController
@Slf4j
public class PaymentController {@Resourceprivate PaymentService paymentService;@Value("${server.port}")private String serverPort;@GetMapping("/payment/hystrix/ok/{id}")public String paymentInfo_OK(@PathVariable("id") Integer id) {String result = paymentService.paymentInfo_OK(id);log.info("*****result->" + result);return result;}@GetMapping("/payment/hystrix/timeout/{id}")public String paymentInfo_TimeOut(@PathVariable("id") Integer id) {String result = paymentService.paymentInfo_TimeOut(id);log.info("*****result->" + result);return result;}}
测试案例:
由于timeout请求sleep了5秒,但是设置了3秒超时进行服务降级,所以超时后直接调用fallback方法进行返回了。
新建cloud-consumer-feign-hystrix-order80,模拟客户端调用服务端,客户端应该也要有自己的熔断降级保护措施。
POM
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>com.atguigu.springcloud</groupId><artifactId>cloud2020</artifactId><version>1.0-SNAPSHOT</version></parent><artifactId>cloud-consumer-feign-hystrix-order80</artifactId><dependencies><!--openfeign--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId></dependency><!--hystrix--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-hystrix</artifactId></dependency><!--eureka client--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency><!-- 引入自己定义的api通用包,可以使用Payment支付Entity --><dependency><groupId>com.atguigu.springcloud</groupId><artifactId>cloud-api-commons</artifactId><version>${project.version}</version></dependency><!--web--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency><!--一般基础通用配置--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><scope>runtime</scope><optional>true</optional></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies></project>
YML
server:port: 80eureka:client:register-with-eureka: falseservice-url:defaultZone: http://eureka7001.com:7001/eureka/feign:hystrix:enabled: true
主启动
package com.atguigu.springcloud;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
import org.springframework.cloud.openfeign.EnableFeignClients;/*** @auther zzyy* @create 2020-02-04 16:32*/
@SpringBootApplication
@EnableFeignClients
@EnableHystrix
public class OrderHystrixMain80
{public static void main(String[] args){SpringApplication.run(OrderHystrixMain80.class,args);}
}
使用@EnableHystrix 注解,启用熔断降级保护功能
业务类
package com.atguigu.springcloud.service;import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;/*** @auther zzyy* @create 2020-02-20 11:55*/
@Component
@FeignClient(value = "CLOUD-PROVIDER-HYSTRIX-PAYMENT" ,fallback = PaymentFallbackService.class)
public interface PaymentHystrixService
{@GetMapping("/payment/hystrix/ok/{id}")public String paymentInfo_OK(@PathVariable("id") Integer id);@GetMapping("/payment/hystrix/timeout/{id}")public String paymentInfo_TimeOut(@PathVariable("id") Integer id);
}
定义一个接口,指定调用CLOUD-PROVIDER-HYSTRIX-PAYMENT服务相关方法的降级方法(@FeignClient(value = “CLOUD-PROVIDER-HYSTRIX-PAYMENT” ,fallback = PaymentFallbackService.class))
package com.atguigu.springcloud.service;import org.springframework.stereotype.Component;/*** @auther zzyy* @create 2020-02-20 18:22*/
@Component
public class PaymentFallbackService implements PaymentHystrixService
{@Overridepublic String paymentInfo_OK(Integer id){return "-----PaymentFallbackService fall back-paymentInfo_OK ,o(╥﹏╥)o";}@Overridepublic String paymentInfo_TimeOut(Integer id){return "-----PaymentFallbackService fall back-paymentInfo_TimeOut ,o(╥﹏╥)o";}
}
PaymentHystrixService接口的实现,注意@Component注解一定要加上,否则springcloud无法发现此组件
package com.atguigu.springcloud.controller;import com.atguigu.springcloud.service.PaymentHystrixService;
import com.netflix.hystrix.contrib.javanica.annotation.DefaultProperties;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;/*** @auther zzyy* @create 2020-02-20 11:57*/
@RestController
@Slf4j
@DefaultProperties(defaultFallback = "payment_Global_FallbackMethod")
public class OrderHystirxController
{@Resourceprivate PaymentHystrixService paymentHystrixService;@GetMapping("/consumer/payment/hystrix/ok/{id}")public String paymentInfo_OK(@PathVariable("id") Integer id){String result = paymentHystrixService.paymentInfo_OK(id);return result;}@GetMapping("/consumer/payment/hystrix/timeout/{id}")@HystrixCommand(fallbackMethod = "paymentTimeOutFallbackMethod",commandProperties = {@HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value="1500")})
// @HystrixCommandpublic String paymentInfo_TimeOut(@PathVariable("id") Integer id){int age = 10/0;String result = paymentHystrixService.paymentInfo_TimeOut(id);return result;}public String paymentTimeOutFallbackMethod(@PathVariable("id") Integer id){return "我是消费者80,对方支付系统繁忙请10秒钟后再试或者自己运行出错请检查自己,o(╥﹏╥)o";}// 下面是全局fallback方法public String payment_Global_FallbackMethod(){return "Global异常处理信息,请稍后再试,/(ㄒoㄒ)/~~";}
}
定义了全局的降级方法payment_Global_FallbackMethod,避免为每一个业务方法都新增一个对应的降级方法。
测试案例:
正常调用
模拟超时
服务端down掉,客户端进行访问
hystrix案例-服务熔断
修改cloud-provider-hystrix-payment8001
业务类
package com.atguigu.springcloud.service;import cn.hutool.core.util.IdUtil;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.PathVariable;import java.util.concurrent.TimeUnit;/****/
@Service
public class PaymentService {/*** 正常访问,肯定OK* @param id* @return*/public String paymentInfo_OK(Integer id){return "线程池: "+Thread.currentThread().getName()+" paymentInfo_OK,id: "+id+"\t"+"O(∩_∩)O哈哈~";}@HystrixCommand(fallbackMethod = "paymentInfo_TimeOutHandler",commandProperties = {@HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value="5000")})public String paymentInfo_TimeOut(Integer id){//int age = 10/0;try { TimeUnit.MILLISECONDS.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); }return "线程池: "+Thread.currentThread().getName()+" id: "+id+"\t"+"O(∩_∩)O哈哈~"+" 耗时(秒): ";}public String paymentInfo_TimeOutHandler(Integer id){return "线程池: "+Thread.currentThread().getName()+" 8001系统繁忙或者运行报错,请稍后再试,id: "+id+"\t"+"o(╥﹏╥)o";}//=====服务熔断@HystrixCommand(fallbackMethod = "paymentCircuitBreaker_fallback",commandProperties = {@HystrixProperty(name = "circuitBreaker.enabled",value = "true"),// 是否开启断路器@HystrixProperty(name = "circuitBreaker.requestVolumeThreshold",value = "10"),// 请求次数@HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds",value = "10000"), // 时间窗口期@HystrixProperty(name = "circuitBreaker.errorThresholdPercentage",value = "60"),// 失败率达到多少后跳闸})public String paymentCircuitBreaker(@PathVariable("id") Integer id){if(id < 0){throw new RuntimeException("******id 不能负数");}String serialNumber = IdUtil.simpleUUID();return Thread.currentThread().getName()+"\t"+"调用成功,流水号: " + serialNumber;}public String paymentCircuitBreaker_fallback(@PathVariable("id") Integer id){return "id 不能负数,请稍后再试,/(ㄒoㄒ)/~~ id: " +id;}
}
参数配置的含义为,时间窗口期内,达到请求次数后的失败率则进行熔断,会返回paymentCircuitBreaker_fallback方法的返回值。
涉及到断路器的三个重要参数:快照时间窗、请求总数阀值、错误百分比阀值。
1:快照时间窗:断路器确定是否打开需要统计一些请求和错误数据,而统计的时间范围就是快照时间窗,默认为最近的10秒。2:请求总数阀值:在快照时间窗内,必须满足请求总数阀值才有资格熔断。默认为20,意味着在10秒内,如果该hystrix命令的调用次数不足20次,即使所有的请求都超时或其他原因失败,断路器都不会打开。
3:错误百分比阀值:当请求总数在快照时间窗内超过了阀值,比如发生了30次调用,如果在这30次调用中,有15次发生了超时异常,也就是超过50%的错误百分比,在默认设定50%阀值情况下,这时候就会将断路器打开。
package com.atguigu.springcloud.controller;import com.atguigu.springcloud.service.PaymentService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;@RestController
@Slf4j
public class PaymentController {@Resourceprivate PaymentService paymentService;@Value("${server.port}")private String serverPort;@GetMapping("/payment/hystrix/ok/{id}")public String paymentInfo_OK(@PathVariable("id") Integer id){String result = paymentService.paymentInfo_OK(id);log.info("*****result: "+result);return result;}@GetMapping("/payment/hystrix/timeout/{id}")public String paymentInfo_TimeOut(@PathVariable("id") Integer id){String result = paymentService.paymentInfo_TimeOut(id);log.info("*****result: "+result);return result;}//====服务熔断@GetMapping("/payment/circuit/{id}")public String paymentCircuitBreaker(@PathVariable("id") Integer id){String result = paymentService.paymentCircuitBreaker(id);log.info("****result: "+result);return result;}
}
断路器开启或者关闭的条件
- 当满足一定的阀值的时候(默认10秒内超过20个请求次数)
- 当失败率达到一定的时候(默认10秒内超过50%的请求失败)
- 到达以上阀值,断路器将会开启
- 当开启的时候,所有请求都不会进行转发
- 一段时间之后(默认是5秒),这个时候断路器是半开状态,会让其中一个请求进行转发。
如果成功,断路器会关闭,若失败,继续开启。重复4和5
断路器打开之后:
1:再有请求调用的时候,将不会调用主逻辑,而是直接调用降级fallback。通过断路器,实现了自动地发现错误并将降级逻辑切换为主逻辑,减少响应延迟的效果。
2:原来的主逻辑要如何恢复呢?
对于这一问题,hystrix也为我们实现了自动恢复功能。
当断路器打开,对主逻辑进行熔断之后,hystrix会启动一个休眠时间窗,在这个时间窗内,降级逻辑是临时的成为主逻辑,
当休眠时间窗到期,断路器将进入半开状态,释放一次请求到原来的主逻辑上,如果此次请求正常返回,那么断路器将继续闭合,
主逻辑恢复,如果这次请求依然有问题,断路器继续进入打开状态,休眠时间窗重新计时。
/*
断路器的所有配置项
*/
@HystrixCommand(fallbackMethod = "str_fallbackMethod",groupKey = "strGroupCommand",commandKey = "strCommand",threadPoolKey = "strThreadPool",commandProperties = {// 设置隔离策略,THREAD 表示线程池 SEMAPHORE:信号池隔离@HystrixProperty(name = "execution.isolation.strategy", value = "THREAD"),// 当隔离策略选择信号池隔离的时候,用来设置信号池的大小(最大并发数)@HystrixProperty(name = "execution.isolation.semaphore.maxConcurrentRequests", value = "10"),// 配置命令执行的超时时间@HystrixProperty(name = "execution.isolation.thread.timeoutinMilliseconds", value = "10"),// 是否启用超时时间@HystrixProperty(name = "execution.timeout.enabled", value = "true"),// 执行超时的时候是否中断@HystrixProperty(name = "execution.isolation.thread.interruptOnTimeout", value = "true"),// 执行被取消的时候是否中断@HystrixProperty(name = "execution.isolation.thread.interruptOnCancel", value = "true"),// 允许回调方法执行的最大并发数@HystrixProperty(name = "fallback.isolation.semaphore.maxConcurrentRequests", value = "10"),// 服务降级是否启用,是否执行回调函数@HystrixProperty(name = "fallback.enabled", value = "true"),// 是否启用断路器@HystrixProperty(name = "circuitBreaker.enabled", value = "true"),// 该属性用来设置在滚动时间窗中,断路器熔断的最小请求数。例如,默认该值为 20 的时候,// 如果滚动时间窗(默认10秒)内仅收到了19个请求, 即使这19个请求都失败了,断路器也不会打开。@HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "20"),// 该属性用来设置在滚动时间窗中,表示在滚动时间窗中,在请求数量超过// circuitBreaker.requestVolumeThreshold 的情况下,如果错误请求数的百分比超过50,// 就把断路器设置为 "打开" 状态,否则就设置为 "关闭" 状态。@HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "50"),// 该属性用来设置当断路器打开之后的休眠时间窗。 休眠时间窗结束之后,// 会将断路器置为 "半开" 状态,尝试熔断的请求命令,如果依然失败就将断路器继续设置为 "打开" 状态,// 如果成功就设置为 "关闭" 状态。@HystrixProperty(name = "circuitBreaker.sleepWindowinMilliseconds", value = "5000"),// 断路器强制打开@HystrixProperty(name = "circuitBreaker.forceOpen", value = "false"),// 断路器强制关闭@HystrixProperty(name = "circuitBreaker.forceClosed", value = "false"),// 滚动时间窗设置,该时间用于断路器判断健康度时需要收集信息的持续时间@HystrixProperty(name = "metrics.rollingStats.timeinMilliseconds", value = "10000"),// 该属性用来设置滚动时间窗统计指标信息时划分"桶"的数量,断路器在收集指标信息的时候会根据// 设置的时间窗长度拆分成多个 "桶" 来累计各度量值,每个"桶"记录了一段时间内的采集指标。// 比如 10 秒内拆分成 10 个"桶"收集这样,所以 timeinMilliseconds 必须能被 numBuckets 整除。否则会抛异常@HystrixProperty(name = "metrics.rollingStats.numBuckets", value = "10"),// 该属性用来设置对命令执行的延迟是否使用百分位数来跟踪和计算。如果设置为 false, 那么所有的概要统计都将返回 -1。@HystrixProperty(name = "metrics.rollingPercentile.enabled", value = "false"),// 该属性用来设置百分位统计的滚动窗口的持续时间,单位为毫秒。@HystrixProperty(name = "metrics.rollingPercentile.timeInMilliseconds", value = "60000"),// 该属性用来设置百分位统计滚动窗口中使用 “ 桶 ”的数量。@HystrixProperty(name = "metrics.rollingPercentile.numBuckets", value = "60000"),// 该属性用来设置在执行过程中每个 “桶” 中保留的最大执行次数。如果在滚动时间窗内发生超过该设定值的执行次数,// 就从最初的位置开始重写。例如,将该值设置为100, 滚动窗口为10秒,若在10秒内一个 “桶 ”中发生了500次执行,// 那么该 “桶” 中只保留 最后的100次执行的统计。另外,增加该值的大小将会增加内存量的消耗,并增加排序百分位数所需的计算时间。@HystrixProperty(name = "metrics.rollingPercentile.bucketSize", value = "100"),// 该属性用来设置采集影响断路器状态的健康快照(请求的成功、 错误百分比)的间隔等待时间。@HystrixProperty(name = "metrics.healthSnapshot.intervalinMilliseconds", value = "500"),// 是否开启请求缓存@HystrixProperty(name = "requestCache.enabled", value = "true"),// HystrixCommand的执行和事件是否打印日志到 HystrixRequestLog 中@HystrixProperty(name = "requestLog.enabled", value = "true"),},threadPoolProperties = {// 该参数用来设置执行命令线程池的核心线程数,该值也就是命令执行的最大并发量@HystrixProperty(name = "coreSize", value = "10"),// 该参数用来设置线程池的最大队列大小。当设置为 -1 时,线程池将使用 SynchronousQueue 实现的队列,// 否则将使用 LinkedBlockingQueue 实现的队列。@HystrixProperty(name = "maxQueueSize", value = "-1"),// 该参数用来为队列设置拒绝阈值。 通过该参数, 即使队列没有达到最大值也能拒绝请求。// 该参数主要是对 LinkedBlockingQueue 队列的补充,因为 LinkedBlockingQueue// 队列不能动态修改它的对象大小,而通过该属性就可以调整拒绝请求的队列大小了。@HystrixProperty(name = "queueSizeRejectionThreshold", value = "5"),}
)
hystrix案例-服务限流
请查看后面高级篇讲解alibaba的Sentinel说明
hystrix工作流程
官网图例:
步骤说明:
- 1 创建 HystrixCommand(用在依赖的服务返回单个操作结果的时候) 或 HystrixObserableCommand(用在依赖的服务返回多个操作结果的时候) 对象。
- 2 命令执行。其中 HystrixComand 实现了下面前两种执行方式;而 HystrixObservableCommand 实现了后两种执行方式:execute():同步执行,从依赖的服务返回一个单一的结果对象, 或是在发生错误的时候抛出异常。queue():异步执行, 直接返回 一个Future对象, 其中包含了服务执行结束时要返回的单一结果对象。observe():返回 Observable 对象,它代表了操作的多个结果,它是一个 Hot Obserable(不论 “事件源” 是否有 “订阅者”,都会在创建后对事件进行发布,所以对于 Hot Observable 的每一个 “订阅者” 都有可能是从 “事件源” 的中途开始的,并可能只是看到了整个操作的局部过程)。toObservable(): 同样会返回 Observable 对象,也代表了操作的多个结果,但它返回的是一个Cold Observable(没有 “订阅者” 的时候并不会发布事件,而是进行等待,直到有 “订阅者” 之后才发布事件,所以对于 Cold Observable 的订阅者,它可以保证从一开始看到整个操作的全部过程)。
- 3 若当前命令的请求缓存功能是被启用的, 并且该命令缓存命中, 那么缓存的结果会立即以 Observable 对象的形式 返回。
- 4 检查断路器是否为打开状态。如果断路器是打开的,那么Hystrix不会执行命令,而是转接到 fallback 处理逻辑(第 8 步);如果断路器是关闭的,检查是否有可用资源来执行命令(第 5 步)。
- 5 线程池/请求队列/信号量是否占满。如果命令依赖服务的专有线程池和请求队列,或者信号量(不使用线程池的时候)已经被占满, 那么 Hystrix 也不会执行命令, 而是转接到 fallback 处理逻辑(第8步)。
- 6 Hystrix 会根据我们编写的方法来决定采取什么样的方式去请求依赖服务。HystrixCommand.run() :返回一个单一的结果,或者抛出异常。HystrixObservableCommand.construct(): 返回一个Observable 对象来发射多个结果,或通过 onError 发送错误通知。
- 7 Hystrix会将 “成功”、“失败”、“拒绝”、“超时” 等信息报告给断路器, 而断路器会维护一组计数器来统计这些数据。断路器会使用这些统计数据来决定是否要将断路器打开,来对某个依赖服务的请求进行 “熔断/短路”。
- 8 当命令执行失败的时候, Hystrix 会进入 fallback 尝试回退处理, 我们通常也称该操作为 “服务降级”。而能够引起服务降级处理的情况有下面几种:第4步: 当前命令处于"熔断/短路"状态,断路器是打开的时候。第5步: 当前命令的线程池、 请求队列或 者信号量被占满的时候。第6步:HystrixObservableCommand.construct() 或 HystrixCommand.run() 抛出异常的时候。
- 9 当Hystrix命令执行成功之后, 它会将处理结果直接返回或是以Observable 的形式返回。
tips:如果我们没有为命令实现降级逻辑或者在降级处理逻辑中抛出了异常, Hystrix 依然会返回一个 Observable 对象, 但是它不会发射任何结果数据, 而是通过 onError 方法通知命令立即中断请求,并通过onError()方法将引起命令失败的异常发送给调用者。
服务监控hystrixDashboard
除了隔离依赖服务的调用以外,Hystrix还提供了准实时的调用监控(Hystrix Dashboard),Hystrix会持续地记录所有通过Hystrix发起的请求的执行信息,并以统计报表和图形的形式展示给用户,包括每秒执行多少请求多少成功,多少失败等。Netflix通过hystrix-metrics-event-stream项目实现了对以上指标的监控。Spring Cloud也提供了Hystrix Dashboard的整合,对监控内容转化成可视化界面。
新建服务监控hystrixDashboard实例
-
新建cloud-consumer-hystrix-dashboard9001
-
POM
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>com.atguigu.springcloud</groupId><artifactId>cloud2020</artifactId><version>1.0-SNAPSHOT</version></parent><artifactId>cloud-consumer-hystrix-dashboard9001</artifactId><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><scope>runtime</scope><optional>true</optional></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies> </project>
-
YML
server:port: 9001
-
主启动
package com.atguigu.springcloud;import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;@SpringBootApplication @EnableHystrixDashboard public class HystrixDashboardMain9001 {public static void main(String[] args){SpringApplication.run(HystrixDashboardMain9001.class,args);} }
-
服务端进行引用
被监控的项目需要进行监控的依赖配置<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId> </dependency>
-
启动9001
-
修改8001的主启动,由于Springcloud升级后的bug,需要添加如下代码,否则会报错:“Unable to connect to Command Metric Stream.”
package com.atguigu.springcloud;import com.netflix.hystrix.contrib.metrics.eventstream.HystrixMetricsStreamServlet; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.web.servlet.ServletRegistrationBean; import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; import org.springframework.context.annotation.Bean;/*** @auther untifa* @create 2024-12-20 10:01:27*/ @SpringBootApplication @EnableEurekaClient //本服务启动后会自动注册进eureka服务中 @EnableCircuitBreaker public class PaymentHystrixMain8001 {public static void main(String[] args){SpringApplication.run(PaymentHystrixMain8001.class,args);}/***此配置是为了服务监控而配置,与服务容错本身无关,springcloud升级后的坑*ServletRegistrationBean因为springboot的默认路径不是"/hystrix.stream",*只要在自己的项目里配置上下面的servlet就可以了*/@Beanpublic ServletRegistrationBean getServlet() {HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet);registrationBean.setLoadOnStartup(1);registrationBean.addUrlMappings("/hystrix.stream");registrationBean.setName("HystrixMetricsStreamServlet");return registrationBean;}}
-
监控地址:http://localhost:8001/hystrix.stream
-
监控信息介绍
7色、1圈、1线
实心圆:共有两种含义。它通过颜色的变化代表了实例的健康程度,它的健康度从绿色<黄色<橙色<红色递减。
该实心圆除了颜色的变化之外,它的大小也会根据实例的请求流量发生变化,流量越大该实心圆就越大。所以通过该实心圆的展示,就可以在大量的实例中快速的发现故障实例和高压力实例。
曲线:用来记录2分钟内流量的相对变化,可以通过它来观察到流量的上升和下降趋势。
相关文章:
Spring Cloud (四、服务熔断降级-HyStrix)
spring cloud 概述 分布式系统面临的问题 复杂分布式体系结构中的应用程序有数十个依赖关系,每个依赖关系在某些时候将不可避免地失败。 服务雪崩 多个微服务之间调用的时候,假设微服务A调用微服务B和微服务C,微服务B和微服务C又调用其它的…...
【C语言】如何插入并播放音频文件
在 C 语言中处理音频文件可以是一个有趣且挑战性的任务,尤其是在嵌入式开发或多媒体程序开发中。尽管 C 语言本身并不直接支持音频处理,但可以通过集成第三方库来处理音频文件的解码和播放。本篇博客将介绍如何在 C 语言中插入并播放音频文件,…...
图书项目:整合SSM
步骤: pom文件:导包,写入静态资源导出配置,连接数据库 建包:controller dao/mapper pojo service 配置文件:mybatis-config.xml applicationContext.xml(Spring的配置文件) datab…...
C#OPC(下)
安装 OPC UA SDK 通过 NuGet 包管理器,在 Visual Studio 中右键单击项目名称,选择 “管理 NuGet 程序包”,在搜索框中输入 “OPCFoundation.NetStandard.Opc.Ua”,找到对应的 OPC UA SDK 包后点击 “安装”,将其集成到…...
STLG_01_05_程序设计C语言 - 数据类型概念解析
一、典型例题 下面这些示例,将能够更熟练地运用C语言中的数据类型,加深对数据存储和处理的理解: 示例:确定变量a、b、c和d的数据类型,并说明它们的存储大小和取值范围 short int a -1000; unsigned int b 50000; f…...
使用工厂+策略模式实现去除繁琐的if else
使用工厂策略模式实现去除繁琐的if else 在中间有一个mapstruct的bug,即在修改实体类中的类型时,或者修改属性名字,mapstruct都无法进行转换,会报错,此时需要maven cleanmaven compile即可 前言 在这次的开发中&#…...
Apache MINA 反序列化漏洞CVE-2024-52046
漏洞描述: Apache MINA 是一个功能强大、灵活且高性能的网络应用框架。它通过抽象网络层的复杂性,提供了事件驱动架构和灵活的 Filter 链机制,使得开发者可以更容易地开发各种类型的网络应用。 Apache MINA 框架的 ObjectSerializationDeco…...
SpringSpringBoot常用注解总结
Spring&SpringBoot常用注解总结 1.SpringBootApplication 这个注解是 Spring Boot 项目的基石,创建 SpringBoot 项目之后会默认在主类加上。 SpringBootApplication public class SpringSecurityJwtGuideApplication {public static void main(java.lang.Str…...
设计模式 创建型 原型模式(Prototype Pattern)与 常见技术框架应用 解析
原型模式(Prototype Pattern)是一种创建型设计模式,其核心思想在于通过复制现有的对象(原型)来创建新的对象,而非通过传统的构造函数或类实例化方式。这种方式在需要快速创建大量相似对象时尤为高效&#x…...
cnPuTTY 0.82.0.1—PuTTY Release 0.82中文版本简单说明~~
2024-11-27 官方发布PuTTY 0.82主要包含如下变化: 1.Unicode处理进行了重大重构,以允许使用系统默认配置的字符集/代码页之外的Unicode字符。仅部分实现,其他尚未完成。 2.Unicode版本进行更新:所有字符分析均已更…...
TypeScript 常用类型
文章目录 1. 类型注解2. 原始类型3. 数组类型4. 联合类型5. 类型别名6. 函数类型7. 对象类型8. 接口类型8.1 接口声明8.2 接口继承 9. 元组类型10. 类型断言11. 字面量类型12. 枚举类型12.1 数字枚举12.2 字符串枚举 13. any 类型14. typeof 运算符 1. 类型注解 前言࿱…...
综合能源建模:理论、方法与实践
一、引言 随着全球能源需求的持续增长以及对能源安全、环境保护和可持续性发展的日益关注,综合能源系统(Integrated Energy System,IES)作为一种能够整合多种能源资源、实现能源高效利用和协同优化的解决方案,正逐渐成…...
《摄影艺术创作》慕课期末答案
《摄影艺术创作》慕课期末考试答案 题数 100 人们常说,“百闻不如一见”、“一图胜千言”,这强调的是 的表现力。 A视觉形象 B文字语言 C音响元素 D有声语言 “绘画是加法,摄影是减法”,主要是指无论摄影和绘画,都要…...
MySQL实用SQL示例
创建数据库 CREATE DATABASE zq-cloud CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;创建表 CREATE TABLE regulatory_firm_category (category_id int NOT NULL AUTO_INCREMENT COMMENT 分类id,自增主键,parent_id int NOT NULL COMMENT 父级id,category_…...
MySQL日志
MySQL日志 文章目录 MySQL日志binlogredoundoredo vs undo binlog binlog日志也就是二进制日志,把对于数据库的写入操作以二进制的形式保存到磁盘中。binlog日志是mysql的逻辑日志,可以理解为记录的是sql日志,由mysql的服务层进行记录&#…...
双目的一些文章学习
文章1 PSMNet https://arxiv.org/pdf/1803.08669PSMNet文章博客PSMNet文章中牵涉到的一些知识,空洞卷积,SPPNet网络,计算视差时用soft argmin代替argmin文章中引入了空洞卷积和SPPNet网络来融合多尺度的信息,又引入3D卷积来增加模…...
国产文本编辑器EverEdit - 批量转码转换行符
1 批量转码&转换行符 1.1 应用场景 如果用户批量在Windows编辑文件,要上传到异构系统,如:Linux,则需要批量转换编码和换行符,此时可以使用EverEdit的批量转码功能。 1.2 使用方法 选择主菜单文档 -> 批量转码…...
NextCloud服务安装与配置教程
NextCloud服务安装与配置教程 什么是 NextCloud: Nextcloud 是一款开源的私有云存储和协作平台,允许用户在自己的服务器上托管数据并管理团队协作。它可以作为一个功能丰富、安全可靠的替代方案,与商业云服务(如 Google Drive、Dropbox)相比提供更多控制和隐私保护。简单来…...
查看 SSD能承载的每秒随机IO次数
查看 SSD能承载的每秒随机IO次数 通常给大家的一个建议就是对于数据库部署的机器,一定要采用SSD固态硬盘,而不要使用机械 硬盘,因为SSD固态硬盘最强大的地方,就是他的随机IO性能非常高。 其次,光是用SSD还不够&#x…...
C# 设计模式(结构型模式):享元模式
C# 设计模式(结构型模式):享元模式 (Flyweight Pattern) 在软件开发中,尤其是在处理大量对象时,我们常常会面临内存和性能上的挑战。当多个对象具有相似的状态时,通常会占用大量的内存资源,从而…...
使用Python,networkx构造有向图及无向图以及图合并等api
使用Python,networkx构造有向图及无向图以及图合并等api 源码图的构造、节点及边的添加等有向图及无向图及多重图 参考 方法名方法作用subgraph(G, nbunch)返回包含nbunch节点的子图union(G, H[, rename])合并G和H图disjoint_union(G, H)合并G和H图cartesian_produc…...
【SOC 芯片设计 DFT 学习专栏 -- 测试向量生成 ATPG (Automatic Test Pattern Generation) 】
文章目录 OverviewATPG 的基本功能ATPG 的工作流程ATPG 应用场景示例示例 1:检测单个信号的 Stuck-at Fault示例 2:针对 Transition Fault 的 ATPG ATPG 工具与常用工具链ATPG 优化与挑战 Overview 本文主要介绍 DFT scan 中的 ATPG 功能。在 DFT (Desi…...
uniapp本地加载腾讯X5浏览器内核插件
概述 TbsX5webviewUTS插件封装腾讯x5webview离线内核加载模块,可以把uniapp的浏览器内核直接替换成Android X5 Webview(腾讯TBS)最新内核,提高交互体验和流畅度。 功能说明 下载SDK插件 1.集成x5内核后哪些页面会由x5内核渲染? 所有plus…...
树莓派之旅-在wsl-x86-64 上进行树莓派的交叉编译
前情提要: 想把自己花里胡哨的终端丢到树莓派上去,可是树莓派算力不够,编译时间过于漫长 交叉编译 定义网上有,懒得复制了,大概就是在本机电脑上编译目标平台的可执行文件 这里的目标平台是树莓派 使用 uname -m …...
JavaScript中Map与Object的区别
在JavaScript中,Map和Object是用于存储键值对数据的两种不同的数据结构(Map是ES6新增的数据结构),它们在构造方式、键的类型以及原型继承等方面存在区别。 一、主要区别 1.构造方式 Map:Map只能通过构造函数new Map…...
基于嵌入式无人机UAV通信系统的实时最优资源分配算法matlab仿真
目录 1.课题概述 2.系统仿真结果 3.核心程序与模型 4.系统原理简介 5.完整工程文件 1.课题概述 基于嵌入式无人机UAV通信系统的实时最优资源分配算法matlab仿真。具体参考文献: 考虑使用UAV作为中继辅助节点的设备到设备(D2D)无线信息和…...
计算机网络 (20)高速以太网
一、发展背景 随着计算机技术和网络应用的不断发展,传统的以太网速率已逐渐无法满足日益增长的带宽需求。因此,高速以太网应运而生,它以提高数据传输速率为主要目标,不断推动着以太网技术的发展。 二、技术特点 高速传输ÿ…...
element ui 组件 时间选择器出现转换问题的解决办法
在使用时间选择器添加数据是会出现转换失败问题 vue中代码为: 解决办法: 在el-date-picker中添加 format 和 value-format...
当知识图谱遇上文本智能处理,会擦出怎样的火花?
目前以理解人类语言为入口的认知智能成为了人工智能发展的突破点,而知识图谱则是迈向认知智能的关键要素。达观数据在2018AIIA人工智能开发者大会承办的语言认知智能与知识图谱公开课上,三位来自企业和学术领域的专家分别从不同角度讲述的知识图谱的应用…...
SpringBootWeb案例-1
文章目录 SpringBootWeb案例1. 准备工作1.1 需求&环境搭建1.1.1 需求说明1.1.2 环境搭建 1.2 开发规范 2. 部门管理2.1 查询部门2.1.1 原型和需求2.1.2 接口文档2.1.3 思路分析2.1.4 功能开发2.1.5 功能测试 2.2 前后端联调2.3 删除部门2.3.1 需求2.3.2 接口文档2.3.3 思路…...
在正则表达式中,\1 是用来引用第一个捕获组的内容的。捕获组是用括号 () 包裹的部分
在正则表达式中,\1 是用来引用第一个捕获组的内容的。捕获组是用括号 () 包裹的部分,它们会保存正则表达式匹配到的内容。在替换操作中,\1 就是对第一个捕获组内容的引用,表示你希望将捕获组中的内容放到替换文本中的某个位置。 …...
免费下载 | 2024年具身大模型关键技术与应用报告
这份报告的核心内容涉及具身智能的关键技术与应用,主要包括以下几个方面: 具身智能的定义与重要性: 具身智能是基于物理身体进行感知和行动的智能系统,通过与环境的交互获取信息、理解问题、做出决策并实现行动,产生智…...
[API测试] Karate 之独立运行方式
在 Karate 介绍与快速示例(API测试自动化、模拟、性能测试与UI自动化工具) 这一篇中介绍了如何在Maven项目中,如何结合JUnit 运行 Karate的API测试, 如果是专职的QA人员来测试, 对Java语言或者Maven完全不熟悉的话要怎么来运行 Karate的测试呢? 答案就是使用Karate的独立运…...
WeNet:面向生产的流式和非流式端到端语音识别工具包
这篇文章介绍了WeNet,一个面向生产的开源端到端(E2E)语音识别工具包。WeNet的主要特点和贡献如下: 统一流式和非流式识别:提出了一种名为U2的两阶段框架,能够在单一模型中同时支持流式和非流式语音识别&…...
《我在技术交流群算命》(二):QGraphicsItem怎么写自定义信号啊(QObject多继承顺序问题)
某位群友突然无征兆的抛出以下问题: QGraphicsItem怎么写自定义信号啊 看到这个问题的时候我是比较疑惑的,按鄙人对 Qt 的了解,自定义信号只需: 继承QObject类中加入Q_OBJECT宏声明一个信号并使用 但该群友毕竟也不是一个Qt新手࿰…...
实践深度学习:构建一个简单的图像分类器
引言 深度学习在图像识别领域取得了巨大的成功。本文将指导你如何使用深度学习框架来构建一个简单的图像分类器,我们将以Python和TensorFlow为例,展示从数据准备到模型训练的完整流程。 环境准备 在开始之前,请确保你的环境中安装了以下工…...
实践:事件循环
实践:事件循环 代码示例 console.log(1); setTimeout(() > console.log(2), 0); Promise.resolve(3).then(res > console.log(res)); console.log(4);上述的代码的输出结果是什么 1和4肯定优先输出,因为他们会立即方式堆栈的执行上下文中执行&am…...
基于Python的医院预约挂号与诊断系统
作者:计算机学姐 开发技术:SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等,“文末源码”。 专栏推荐:前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏:…...
计算机网络基础
文章目录 名词含义1.应用层1.1网络应用原理1.1.1网络应用体系1.1.2进程通信1.1.3可供程序使用的运输服务1.1.4因特网的运输服务1.1.5应用层协议 1.2WEB和HTTP1.2.1HTTP概述1.2.2持续与非持续连接1.2.3报文格式 名词含义 ISP(Internet Service Provider,因特网服务提…...
Rabbitmq追问1
如果消费端代码异常,未手动确认,那么这个消息去哪里 2024-12-31 21:19:12 如果消费端代码发生异常,未手动确认(ACK)的情况下,消息的处理行为取决于消息队列的实现和配置,以下是基于 RabbitMQ …...
基于SpringBoot和OAuth2,实现通过Github授权登录应用
基于SpringBoot和OAuth2,实现通过Github授权登录应用 文章目录 基于SpringBoot和OAuth2,实现通过Github授权登录应用0. 引言1. 创建Github应用2. 创建SpringBoot测试项目2.1 初始化项目2.2 设置配置文件信息2.3 创建Controller层2.4 创建Html页面 3. 启动…...
python数据分析:使用pandas库读取和编辑Excel表
使用 Pandas,我们可以轻松地读取和写入Excel 文件,之前文章我们介绍了其他多种方法。 使用前确保已经安装pandas和 openpyxl库(默认使用该库处理Excel文件)。没有安装的可以使用pip命令安装: pip install pandas ope…...
SpringCloud源码分析-Lettue Redis
redis connection异步发送 底层是nio channel...
Linux(13)——网络概述
目录 一、TCP/IP 网络模型: 1、应用层(Application): 2、传输层(Transport): 3、互联网层(Internet or network): 4、链路层(Link࿰…...
PHP框架+gatewayworker实现在线1对1聊天--聊天界面布局+创建websocket连接(5)
文章目录 聊天界面布局html代码 创建websocket连接为什么要绑定? 聊天界面布局 在View/Index目录下创建index.html html代码 <div id"chat"><div id"nbar"><div class"pull-left">与牛德胜正在聊天...</div…...
Qos的详细解释
QoS(Quality of Service),即服务质量,是一种用于网络管理的技术,旨在确保不同类型的数据流(如语音、视频、文件传输等)在网络中按优先级和要求得到适当的带宽、延迟、抖动和丢包率等服务&#x…...
未来20年在大语言模型相关研究方向--大语言模型的优化与改进
未来20年在大语言模型相关研究方向 模型性能优化 模型架构创新:研究新型的模型架构,如探索更高效的Transformer变体、融合递归神经网络(RNN)和卷积神经网络(CNN)的优点,以提高模型的性能、可扩展性和适应性,满足不同应用场景对模型效率和效果的要求。高效训练算法:开…...
【Vue】vue-router使用addRoute动态加载路由后刷新页面404
场景:动态加载路由,点击菜单路由跳转正常,但刷新页面报404 原因:使用404做异常路由捕获 刷新页面会导致路由丢失,重建路由时先加载了静态路由(包含异常路由捕获404),此时动态路由还未…...
《计算机组成及汇编语言原理》阅读笔记:p177-p177
《计算机组成及汇编语言原理》学习第 13 天,p177-p177 总结,总计 1 页。 一、技术总结 1.real mode A programming model where the program has access to the entire capability of the machine, bypassing security and memory management. Useful…...
《从入门到精通:蓝桥杯编程大赛知识点全攻略》(一)-递归实现指数型枚举、递归实现排列型枚举
本篇博客将聚焦于通过递归来实现两种经典的枚举方法:指数型枚举和排列型枚举。这两种枚举方式在计算机科学和算法竞赛中都有广泛应用,无论是在解题中,还是在实际工作中都极具价值。 目录 前言 斐波那契数列递归 递归实现指数型枚举 算法思…...