Spring Cloud学习笔记【容错降级-Hystrix】
创始人
2025-05-31 21:18:56

文章目录

  • Hystrix概述
    • Hystrix是什么
    • 什么是服务降级
    • 什么是服务熔断
    • 什么是服务限流
  • Hystrix使用
    • 服务降级演示
      • 服务端lf-hystrix-user搭建
      • 消费端lf-hystrix-auth搭建
      • 测试
      • jMeter配置
      • 服务端user测试
      • 消费端auth远程调用测试
      • 解决方案
    • 服务降级配置
      • 服务端user配置
      • 服务端user测试
      • 调用端auth配置
      • 调用端auth测试
      • 类统一配置
      • 全局统一配置
    • 服务熔断
      • Hystrix的熔断机制
      • 熔断配置代码
      • 测试
      • 熔断类型
      • 断路器在什么情况下开始起作用
      • hystrix工作流程
  • 服务监控hystrixDashboard
    • 搭建服务
    • 测试

Hystrix概述

Hystrix是什么

Hystrix是一个用于分布式系统的延迟和容错库,由Netflix开发并开源。它旨在提高应用程序的可靠性和弹性,并通过提供故障转移和回退机制来减少系统出现故障的影响。

Hystrix使用断路器模式来控制和停止远程服务的调用,以防止系统出现过度负载或其他错误。当远程服务的调用失败或超时时,Hystrix将采取适当的措施,例如使用回退方法返回预设值或提供备用服务。

Hystrix还提供了实时指标和监视功能,使开发人员能够监视应用程序的健康状况,并进行必要的调整和优化。

在微服务架构中,Hystrix可以在服务之间提供容错保护,以确保整个系统的可靠性和弹性。通过使用Hystrix,开发人员可以构建更具弹性和可靠性的分布式系统。

什么是服务降级

服务降级是一种应对系统高并发、故障等异常情况的策略。在系统资源紧张或者出现异常的情况下,为了保证核心功能的稳定性,可以暂时关闭一些非核心或者不重要的服务,降低服务质量,但保证核心服务的可用性。
比如,在大促销活动期间,电商平台的订单处理服务压力会比较大,为了保证订单核心服务的可用性,可以暂时关闭用户评价服务,避免评价服务带来的额外压力。

什么是服务熔断

服务熔断是一种应对服务故障的策略。当服务出现故障或异常时,及时停止请求该服务,避免故障扩散到整个系统中,进而保证系统的可用性。
比如,当某个服务不可用时,可以在服务调用之前设置一个超时时间,如果服务没有及时响应或者返回错误,就及时停止请求该服务,并进行相应的降级处理。

什么是服务限流

服务限流是一种控制系统请求量的策略。在系统高并发的情况下,可以通过限制并发请求数、请求速率等方式,控制系统的请求量,避免系统过载。
比如,可以设置每秒钟只允许处理一定数量的请求,超出限制的请求就会被拒绝,从而保证系统的稳定性。

Hystrix使用

服务降级演示

服务端lf-hystrix-user搭建

新建一个服务端user的module,参照user服务
新建lf-hystrix-user服务
在这里插入图片描述
pom.xml

	org.springframework.cloudspring-cloud-starter-netflix-hystrixorg.springframework.cloudspring-cloud-starter-netflix-eureka-clientorg.springframework.bootspring-boot-starter-weborg.springframework.bootspring-boot-starter-actuatororg.springframework.bootspring-boot-devtoolsruntimetrueorg.projectlomboklomboktrueorg.springframework.bootspring-boot-starter-testtest

application.yml

server:port: 9001spring:application:name: lf-hystrix-usermain:allow-bean-definition-overriding: true #当遇到同样名字的时候,是否允许覆盖注册eureka:instance:# 配置eureka的状态显示hostname: localhostinstance-id: ${eureka.instance.hostname}:${spring.application.name}:${server.port}client:#表示是否将自己注册进EurekaServer默认为true。register-with-eureka: true#是否从EurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡fetchRegistry: trueservice-url:#defaultZone: http://localhost:7001/eurekadefaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka  # 集群版

启动类UserApplication

@SpringBootApplication
@EnableEurekaClient
public class UserApplication {public static void main(String[] args) {SpringApplication.run(UserApplication.class,args);}
}

业务类UserController
一个正常返回的接口
一个延时返回的接口

@RestController
@RequestMapping("/user")
public class UserController {/*** 获取当前用户信息*/@GetMapping("/info/{username}")public String info(@PathVariable("username") String username){return username + " login success 端口:9001";}/*** 获取当前用户信息timeout*/@GetMapping("/info/timeout/{username}")public String infoTimeOut(@PathVariable("username") String username){try {Thread.sleep(5*1000);} catch (InterruptedException e) {e.printStackTrace();}return username + " login success 超时端口:9001";}}

消费端lf-hystrix-auth搭建

新建module lf-hystrix-auth
在这里插入图片描述
pom.xml

org.springframework.cloudspring-cloud-starter-openfeignorg.springframework.cloudspring-cloud-starter-netflix-hystrixorg.springframework.cloudspring-cloud-starter-netflix-eureka-clientorg.springframework.bootspring-boot-starter-weborg.springframework.bootspring-boot-starter-actuatororg.springframework.bootspring-boot-devtoolsruntimetrueorg.projectlomboklomboktrueorg.springframework.bootspring-boot-starter-testtest

application.yml

server:port: 9002spring:application:name: lf-hystrix-autheureka:instance:# 配置eureka的状态显示hostname: localhostinstance-id: ${eureka.instance.hostname}:${spring.application.name}:${server.port}client:#表示是否将自己注册进EurekaServer默认为true。register-with-eureka: true#是否从EurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡fetchRegistry: trueservice-url:defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka  # 集群版

启动类HystrixAuthApplication

@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
public class HystrixAuthApplication {public static void main(String[] args) {SpringApplication.run(HystrixAuthApplication.class,args);}
}

业务类service

@FeignClient(value = "LF-HYSTRIX-USER")
public interface AuthService {@GetMapping("/user/info/{username}")String getUserInfo(@PathVariable("username") String username);@GetMapping("/user/info/timeout/{username}")String getUserInfoTimeOut(@PathVariable("username") String username);}

业务类controller

@RestController
@RequestMapping("/auth")
public class AuthController {@AutowiredAuthService authService;@PostMapping("login")public String login(@RequestBody String name){return authService.getUserInfo(name);}@PostMapping("/login/timeout")public String loginTimeout(@RequestBody String name){return authService.getUserInfoTimeOut(name);}}

测试

使用jMeter多线程高并发来直接请求服务端user的超时接口。

jMeter配置

在这里插入图片描述
200个线程数,循环100次,1秒钟启动完毕
在这里插入图片描述
http请求配置
在这里插入图片描述

服务端user测试

启动各个服务。
jMeter启动高并发的请求user服务的timeout接口。
同时,我们请求直接请求user服务的正常接口观察。
在这里插入图片描述
发现正常接口的调用也明显变慢。
这是由于tomcat的默认的工作线程数被打满了,没有多余的线程来分解压力和处理。

消费端auth远程调用测试

启动lf-hystrix-auth服务。
同样高并发的请求user服务的timeout接口。
这次观察使用auth服务调用普通接口的情况。
在这里插入图片描述
在这里插入图片描述
如图要么会等待很久,要么会超时报错

解决方案

  • 对于服务方来说:自身服务如果响应时间超时,宕机,或者报错,需要有服务降级。
  • 对于调用方来说:调用服务超过时间限制,需要自己处理降级

服务降级配置

服务端user配置

业务类UserController

@RestController
@RequestMapping("/user")
public class UserController {/*** 获取当前用户信息*/@GetMapping("/info/{username}")public String info(@PathVariable("username") String username){return username + " login success 端口:9001";}/*** 获取当前用户信息timeout*/@GetMapping("/info/timeout/{username}")@HystrixCommand(fallbackMethod = "userInfoTimeOutHandler", commandProperties = {@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "3000")})public String infoTimeOut(@PathVariable("username") String username){try {Thread.sleep(5*1000);} catch (InterruptedException e) {e.printStackTrace();}return username + " login success 超时端口:9001";}/*** 超时访问的降级方法** @param username* @return*/public String userInfoTimeOutHandler(String username) {return "/(ㄒoㄒ)/调用用户信息接口超时或异常:\t" + "\t当前线程池名字" + Thread.currentThread().getName();}}

主要修改是,添加@HystrixCommand注解,定义降级的具体处理方法
在这里插入图片描述
启动类添加注解
@EnableCircuitBreaker
在这里插入图片描述

服务端user测试

我们定义的是3s超时,而方法中延迟5秒,看结果
在这里插入图片描述可以看到异常情况会被捕获到,走fallbackMethod的方法来处理。

调用端auth配置

启动类修改
添加注解@EnableHystrix
在这里插入图片描述
application.yml修改
主要是设计超时时间改为5s

server:port: 9002spring:application:name: lf-hystrix-autheureka:instance:# 配置eureka的状态显示hostname: localhostinstance-id: ${eureka.instance.hostname}:${spring.application.name}:${server.port}client:#表示是否将自己注册进EurekaServer默认为true。register-with-eureka: true#是否从EurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡fetchRegistry: trueservice-url:defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka  # 集群版hystrix:command:default:execution:isolation:thread:timeoutInMilliseconds: 5000feign:client:config:## default 设置的全局超时时间,指定服务名称可以设置单个服务的超时时间default:connectTimeout: 5000readTimeout: 5000

修改业务类AuthController
和服务端一样,设置一个fallbackMethod
在这里插入图片描述

@RestController
@RequestMapping("/auth")
public class AuthController {@AutowiredAuthService authService;@PostMapping("login")public String login(@RequestBody String name){return authService.getUserInfo(name);}@PostMapping("/login/timeout")@HystrixCommand(fallbackMethod = "loginTimeOutHandler", commandProperties = {@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1500")})public String loginTimeout(@RequestBody String name){return authService.getUserInfoTimeOut(name);}/*** 超时访问的降级方法** @param username* @return*/public String loginTimeOutHandler(String username) {return "/(ㄒoㄒ)/调用登录接口超时或异常:\t" + "\t当前线程池名字" + Thread.currentThread().getName();}}

调用端auth测试

在这里插入图片描述
如图,走到了loginTimeOutHandler的方法,这是因为auth服务的超时时间是1.5s,而user服务端的接口有5s钟延迟。且服务端的超时时间是3s才触发,所以此处是auth的降级方法生效了。
我们把auth端的超时时间设为4s,再看看效果,就是服务端降级方法先生效了。
在这里插入图片描述
服务端user降级方法生效在这里插入图片描述

类统一配置

通过上面的例子我们也可以发现,每个方法都加一个配置降级方法,代码膨胀。
我们可以用@DefaultProperties(defaultFallback = “”)对类中的方法统一配置全局异常处理,需要单独配置的才用上面的方法。
修改AuthController

@RestController
@RequestMapping("/auth")
@DefaultProperties(defaultFallback = "globalFallbackHandler")
public class AuthController {@AutowiredAuthService authService;@PostMapping("login")public String login(@RequestBody String name){return authService.getUserInfo(name);}@PostMapping("/login/timeout")@HystrixCommandpublic String loginTimeout(@RequestBody String name){int a =1/0;return authService.getUserInfoTimeOut(name);}/*** 全局的降级方法*/public String globalFallbackHandler() {return "/(ㄒoㄒ)/调用登录接口超时或异常:\t" + "\t当前线程池名字" + Thread.currentThread().getName();}/*** 超时访问的降级方法** @param username* @return*/public String loginTimeOutHandler(String username) {return "/(ㄒoㄒ)/全局异常降级处理:\t" + "\t当前线程池名字" + Thread.currentThread().getName();}}

在这里插入图片描述
如图,我们设置一个全局降级方法,然后写一个异常int a= 1/0测试效果。
在这里插入图片描述

全局统一配置

Hystrix也可以对feign接口统一配置。例如服务端宕机了,可以统一处理进行服务降级。只需要为Feign客户端定义的接口添加一个服务降级处理的实现类即可实现解耦。
新增一个异常处理类AuthFallbakServiceImpl,实现feign注解的接口
在这里插入图片描述
AuthFallbakServiceImpl类

@Component
public class AuthFallbakServiceImpl implements AuthService {@Overridepublic String getUserInfo(String username) {return "====AuthService fall back getUserInfo,o(╥﹏╥)o====";}@Overridepublic String getUserInfoTimeOut(String username) {return "====AuthService fall back getUserInfoTimeOut,o(╥﹏╥)o====";}
}

同时修改AuthService @FeignClient注解的信息

@Component
@FeignClient(value = "LF-HYSTRIX-USER",fallback = AuthFallbakServiceImpl.class)
public interface AuthService {@GetMapping("/user/info/{username}")String getUserInfo(@PathVariable("username") String username);@GetMapping("/user/info/timeout/{username}")String getUserInfoTimeOut(@PathVariable("username") String username);}

测试
启动项目
故意将服务端user关掉,模拟服务端user宕机,然后请求接口在这里插入图片描述

服务熔断

Hystrix的熔断机制

  1. 断路器
    Hystrix的断路器会在服务调用失败或超时时打开,当断路器打开时,Hystrix将会执行回退逻辑,并将请求转发到备用服务上。断路器打开的条件通常是在一定时间内请求失败率达到了一定的阈值。当断路器打开后,Hystrix会通过定时任务来检查是否应该重新尝试请求原始服务,如果重新尝试请求后服务正常,断路器就会关闭。
  2. 超时控制
    超时控制是通过设置服务响应时间的最大值来实现的。当服务响应时间超过预定的最大值时,Hystrix会将服务请求转发到备用服务上。
  3. 熔断控制
    熔断控制通过设置阈值来实现。当服务请求失败率达到一定阈值时,Hystrix会自动开启断路器,将请求转发到备用服务上。当一段时间内服务请求成功率达到一定的阈值时,Hystrix会自动关闭断路器,重新调用原始服务。
  4. 资源隔离
    资源隔离是通过线程池隔离和信号量隔离来实现的。线程池隔离是通过将服务请求放到独立的线程池中来实现,从而避免服务请求之间的相互干扰。信号量隔离是通过限制并发请求数来实现的,从而避免服务过载。

熔断配置代码

我们在服务端user上测试
在controller中加入以下代码

// =====服务熔断=====@HystrixCommand(fallbackMethod = "userCircuitBreaker_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"),// 失败率达到多少后跳闸})@GetMapping("/circuit/{id}")public String paymentCircuitBreaker(@PathVariable("id") Integer id) {if (id < 0) {int a =1/0;}String serialNumber = UUID.randomUUID().toString();return Thread.currentThread().getName() + "\t" + "调用成功,流水号: " + serialNumber;}public String userCircuitBreaker_fallback(@PathVariable("id") Integer id) {return "id 不能负数,请稍后再试,/(ㄒoㄒ)/~~   id: " + id;}

测试

单独测试一次,两种情况整数和负数,没有问题
在这里插入图片描述

在这里插入图片描述
接下来,连续多次测试负数,使其走到降级方法中。然后测试正数,发现正数也开始报错了,等一段时间,正数才会恢复正常,这个等待时间就是时间窗口期
时间窗口期参数代表的是断路器开启后,在休眠窗口期间的时间,即在此期间,HystrixCommand将拒绝尝试执行该命令,而是直接返回一个fallback响应(如果定义了fallback逻辑)。

具体来说,当HystrixCommand执行请求时,如果超时、失败、线程池被占满等情况达到一定阈值时,HystrixCommand会切换至开启状态,此时断路器会拦截请求并返回fallback响应。同时,sleepWindowInMilliseconds参数将启动一个休眠窗口,以限制后续请求的执行,并且只有在休眠窗口期间结束后,才会尝试再次执行HystrixCommand。
在这里插入图片描述

熔断类型

  • 熔断打开状态:当系统出现异常或负载过高等问题时,熔断器会进入熔断打开状态,停止向系统发送请求,而是直接返回一个预定义的错误响应(比如fallback)。在此期间,系统将不会接收到任何新的请求,直至达到熔断器的等待时间(也称休眠时间)或请求重试次数后,进入熔断半开状态。
  • 熔断关闭状态:在正常情况下,熔断器处于熔断关闭状态,允许系统正常处理请求,并记录请求的成功率和响应时间等指标,以便进行熔断器的自适应调整。
  • 熔断半开状态:在熔断器的等待时间或请求重试次数达到阈值后,熔断器进入熔断半开状态。在此状态下,熔断器会允许一个或多个请求通过到达系统,以检测系统的可用性和稳定性。如果这些请求成功,则熔断器将进入熔断关闭状态,并重新计算熔断器的参数和指标。如果这些请求失败,则熔断器将重新进入熔断打开状态,并阻止进一步的请求到达系统,直到下一个熔断器等待时间。

断路器在什么情况下开始起作用

在这里插入图片描述

  • 请求总数阈值:指定在一段时间内,断路器需要接收的请求总数的最小值。如果请求总数低于此阈值,则断路器不会打开,即使在此期间出现了一些失败的请求。如果请求总数高于此阈值,则断路器可能会打开,阻止进一步的请求到达服务,以保护系统免受额外的负载和损害。

  • 快照时间窗:指定断路器收集统计信息的时间段。在此时间段内,断路器会记录服务的响应时间、成功率和失败率等指标,并根据这些指标进行自适应调节。如果快照时间窗过短,则断路器可能无法准确反映系统的负载和异常情况;如果快照时间窗过长,则断路器可能会对系统的响应时间和失败率产生不必要的延迟和影响。

  • 错误百分比阈值:指定断路器在快照时间窗内记录的失败请求占总请求数的百分比阈值。如果错误百分比超过此阈值,则断路器可能会打开,阻止进一步的请求到达服务,并返回预定义的错误响应(比如fallback),以保护系统免受额外的负载和损害。如果错误百分比低于此阈值,则断路器将保持关闭状态,允许请求正常到达服务。

hystrix工作流程

在这里插入图片描述
Hystrix的工作流程如下:

  1. 应用程序通过HystrixCommand执行远程调用或本地调用。
  2. HystrixCommand包含一个或多个HystrixObservableCommand实例,每个HystrixObservableCommand实例负责一个服务调用。
  3. HystrixCommand通过执行run()方法执行实际的服务调用。
  4. HystrixCommand使用HystrixThreadPool来管理线程池,并使用HystrixCommandKey和HystrixThreadPoolKey来对线程池进行标识和分类。
  5. HystrixCommand在服务调用中使用HystrixCommandProperties来配置断路器的行为,包括断路器的时间窗口、错误比例、超时时间等。
  6. 如果服务调用出现问题,HystrixCommand将执行fallback()方法,返回一个备用结果。
  7. 如果服务调用的错误比例超过一定阈值,HystrixCommand将打开断路器,并触发断路器打开事件。
  8. 断路器打开后,HystrixCommand将执行circuitBreaker()方法,并在一定时间窗口内拒绝所有的服务调用。
  9. 如果断路器在一定时间窗口内没有收到新的服务调用,则进入半开状态,HystrixCommand将尝试执行一次服务调用。
  10. 如果服务调用成功,则断路器将关闭,否则将继续保持打开状态。

服务监控hystrixDashboard

搭建服务

新建module
cloud-consumer-hystrix-dashboard9999
在这里插入图片描述
pom.xml

org.springframework.cloudspring-cloud-starter-netflix-hystrix-dashboardorg.springframework.bootspring-boot-starter-actuatororg.springframework.bootspring-boot-devtoolsruntimetrueorg.projectlomboklomboktrueorg.springframework.bootspring-boot-starter-testtest

application.yml

server:port: 9999

启动类
HystrixDashboardMain9999

@SpringBootApplication
@EnableHystrixDashboard
public class HystrixDashboardMain9999 {public static void main(String[] args) {SpringApplication.run(HystrixDashboardMain9999.class, args);}}

服务端启动类
添加如下代码
在这里插入图片描述

    @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:9999/hystrix,并填写服务端地址http://localhost:9001/hystrix.stream
在这里插入图片描述
即可进入监控页面
在这里插入图片描述
请求服务端接口,就可以看到监控数据了。
监控图界面说明
在这里插入图片描述

相关内容

热门资讯

【实验报告】实验一 图像的... 实验目的熟悉Matlab图像运算的基础——矩阵运算;熟悉图像矩阵的显示方法࿰...
MATLAB | 全网最详细网... 一篇超超超长,超超超全面网络图绘制教程,本篇基本能讲清楚所有绘制要点&#...
大模型落地比趋势更重要,NLP... 全球很多人都开始相信,以ChatGPT为代表的大模型,将带来一场NLP领...
Linux学习之端口、网络协议... 端口:设备与外界通讯交流的出口 网络协议:   网络协议是指计算机通信网...
kuernetes 资源对象分... 文章目录1. pod 状态1.1 容器启动错误类型1.2 ImagePullBackOff 错误1....
STM32实战项目-数码管 程序实现功能: 1、上电后,数码管间隔50ms计数; 2、...
TM1638和TM1639差异... TM1638和TM1639差异说明 ✨本文不涉及具体的单片机代码驱动内容,值针对芯...
Qt+MySql开发笔记:Qt... 若该文为原创文章,转载请注明原文出处 本文章博客地址:https://h...
Java内存模型中的happe... 第29讲 | Java内存模型中的happen-before是什么? Java 语言...
《扬帆优配》算力概念股大爆发,... 3月22日,9股封单金额超亿元,工业富联、鸿博股份、鹏鼎控股分别为3.0...
CF1763D Valid B... CF1763D Valid Bitonic Permutations 题目大意 拱形排列࿰...
SQL语法 DDL、DML、D... 文章目录1 SQL通用语法2 SQL分类3 DDL 数据定义语言3.1 数据库操作3.2 表操作3....
文心一言 VS ChatGPT... 3月16号,百度正式发布了『文心一言』,这是国内公司第一次发布类Chat...
CentOS8提高篇5:磁盘分...        首先需要在虚拟机中模拟添加一块新的硬盘设备,然后进行分区、格式化、挂载等...
Linux防火墙——SNAT、... 目录 NAT 一、SNAT策略及作用 1、概述 SNAT应用环境 SNAT原理 SNAT转换前提条...
部署+使用集群的算力跑CPU密... 我先在开头做一个总结,表达我最终要做的事情和最终环境是如何的,然后我会一...
Uploadifive 批量文... Uploadifive 批量文件上传_uploadifive 多个上传按钮_asing1elife的...
C++入门语法基础 文章目录:1. 什么是C++2. 命名空间2.1 域的概念2.2 命名...
2023年全国DAMA-CDG... DAMA认证为数据管理专业人士提供职业目标晋升规划,彰显了职业发展里程碑及发展阶梯定义...
php实现助记词转TRX,ET... TRX助记词转地址网上都是Java,js或其他语言开发的示例,一个简单的...
【分割数据集操作集锦】毕设记录 1. 按要求将CSV文件转成json文件 有时候一些网络模型的源码会有data.json这样的文件里...
Postman接口测试之断言 如果你看文字部分还是不太理解的话,可以看看这个视频,详细介绍postma...
前端学习第三阶段-第4章 jQ... 4-1 jQuery介绍及常用API导读 01-jQuery入门导读 02-JavaScri...
4、linux初级——Linu... 目录 一、用CRT连接开发板 1、安装CRT调试工具 2、连接开发板 3、开机后ctrl+c...
Urban Radiance ... Urban Radiance Fields:城市辐射场 摘要:这项工作的目标是根据扫描...
天干地支(Java) 题目描述 古代中国使用天干地支来记录当前的年份。 天干一共有十个,分别为:...
SpringBoot雪花ID长... Long类型精度丢失 最近项目中使用雪花ID作为主键,雪花ID是19位Long类型数...
对JSP文件的理解 JSP是java程序。(JSP本质还是一个Servlet) JSP是&#...
【03173】2021年4月高... 一、单向填空题1、大量应用软件开发工具,开始于A、20世纪70年代B、20世纪 80年...
LeetCode5.最长回文子... 目录题目链接题目分析解题思路暴力中心向两边拓展搜索 题目链接 链接 题目分析 简单来说࿰...