Spring Cloud Hystrix 豪猪哥 服务容错与保护组件

news2024/11/21 22:02:21

Spring Cloud Hystrix 豪猪哥 服务容错与保护组件

  • 一、Spring Cloud Hystrix概述
    • 1.简介
    • 2.核心功能
    • 3.雪崩效应
  • 二、Hystrix服务降级
    • 1.服务降级简介
    • 2.样例准备
    • 3.服务提供者降级
    • 4.服务消费者降级
    • 5.全局降级方法
    • 6.对API接口降级方法
  • 三、Hystrix服务熔断
    • 1.服务熔断机制简介
    • 2.熔断工作流程
  • 四、服务监控 hystrix Dashboard


一、Spring Cloud Hystrix概述

在这里插入图片描述

1.简介

Spring Cloud Hystrix是一个用于处理分布式系统延迟和容错的库,它提供了熔断机制、服务降级、服务隔离等关键特性,以提高分布式系统的弹性和可用性

在微服务系统中,Hystrix 能够帮助我们实现以下目标:

  • 保护线程资源:防止单个服务的故障耗尽系统中的所有线程资源。
  • 快速失败机制:当某个服务发生了故障,不让服务调用方一直等待,而是直接返回请求失败。
  • 提供降级(FallBack)方案:在请求失败后,提供一个设计好的降级方案,通常是一个兜底方法,当请求失
  • 败后即调用该方法。
  • 防止故障扩散:使用熔断机制,防止故障扩散到其他服务。
  • 监控功能:提供熔断器故障监控组件 Hystrix Dashboard,随时监控熔断器的状态。

2.核心功能

  • 服务降级: 在请求失败后,提供一个设计好的降级方案,通常是一个兜底方法,当请求失败后即调用该方法。
  • 服务熔断: 当服务调用失败率达到一定阈值时,Hystrix会自动熔断该服务的调用,阻止进一步的请求,从而避免雪崩效应
  • 请求合并: 在一个时间节点,访问同一个节点,等几秒,将相同节点的请求合并去请求同一个节点
  • 请求缓存: 可以缓存相同请求的响应结果,从而避免重复调用远程服务
  • 隔离: 隔离分为线程池隔离和信号量隔离。通过判断线程池或信号量是否已满,超出容量的请求直接降级,从而
    达到限流的作用。

3.雪崩效应

在这里插入图片描述

在所有服务都处于可用状态时,请求 1 需要调用服务1,2,3完成,请求 2 需要调用服务4,5,2,6完成,请求 3 需要调用服务 2,3完成。

当服务2发生故障或网络延迟:

  • 即使其他所有服务都可用,由于服务2的不可用,那么用户请求 1、2、3 都会处于阻塞状态,等待服务2的响应。在高并发的场景下,会导致整个服务器的线程资源在短时间内迅速消耗殆尽。
  • 所有依赖于服务2的其他服务,服务1,5也都会处于线程阻塞状态,等待服务2的响应,导致这些服务的不可用。
  • 所有依赖服务5的服务,服务5处于线程阻塞状态,导致服务4不可用。
  • 最终导致雪崩效应,然后微服务架构引入了熔断器系列服务容错和保护机制。

在这里插入图片描述

雪崩原因

  • 服务提供者不可用: 硬件故障,程序BUG,并发请求过大,缓存击穿等。
  • 不断的请求重试,代码重试等。
  • 无服务调用者不可用:同步请求造成了资源耗尽。

雪崩效应最终的结果就是:服务链条中的某一个服务不可用,导致一系列的服务不可用,最终造成服务逻辑
崩溃。这种问题造成的后果,往往是无法预料的。

二、Hystrix服务降级

1.服务降级简介

服务降级是指,当请求超时、资源不足等情况发生时进行服务降级处理,不调用真实服务逻辑,而是使用
快速失败(fallback)方式直接返回一个托底数据,保证服务链条的完整,避免服务雪崩。

服务降级常用两种情况:

  • 服务器压力剧增:
    根据实际业务情况及流量,对一些不重要、不紧急的服务进行有策略地不处理或简单处
    理,从而释放服务器资源以保证核心服务正常运作。
  • 某些服务不可用:
    当某些服务不可用时,为了避免长时间等待造成服务卡顿或雪崩效应,而主动执行备用的降级逻辑立刻返回一
    个友好的提示,以保障主体业务不受影响。

2.样例准备

使用 我的另一篇文章 Spring Cloud OpenFeign 声明式服务调用与负载均衡组件 文章中 OpenFeign实现服务远程调用 的样例 实现负载均衡

3.服务提供者降级

对于stock模块
1.更改启动类 添加注解 @EnableCircuitBreaker

@EnableEurekaClient
@EnableCircuitBreaker //激活服务降级 服务提供者使用
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class, DruidDataSourceAutoConfigure.class})
public class OpenFeignStockApplication {
    public static void main(String[] args) {
        SpringApplication.run(OpenFeignStockApplication.class,args);
    }
}

2.填写兜底方法 及使用兜底方法 对与StockController进行更改

@RestController
@RequestMapping("/stock")
public class StockController {

    private Integer count = 0 ;

    @Value("${server.port}")
    public Integer port;

    @GetMapping("/subStock/{seconds}")
    //该注解走该节点方法 发生异常 走降级方法
    @HystrixCommand(fallbackMethod = "subStockFallBack",
            commandProperties = {
                //在6秒钟还没有返回 就执行兜底方法
                //execution.isolation.thread.timeoutInMilliseconds这个为官方文档的默认值 
                //value默认为1000 即是超时1秒走兜底方法 subStockFallBack
                @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "6000")
    })
    public R subStock(@PathVariable("seconds") Integer seconds){
        try{
            System.out.println("睡眠"+seconds+"秒");
            TimeUnit.SECONDS.sleep(seconds);
        }catch (Exception e){
            e.printStackTrace();
        }
        HashMap<String, Object> map = new HashMap<>();
        map.put("port",port);
        map.put("count",++count);
        return R.ok(map);
    }

    //降级方法 参数用不用都要写
    public R subStockFallBack(Integer seconds){
        return R.failed("subStock 的兜底方法");
    }
}

3.测试

Tip: 如果我们order 设置的openfegin的超时时间小于6秒那么我们适当调大一些 避免直接走openfegin的超时异常而非我们的降级方法 更改order模块的yml文件

CLOUD-OPENFEGIN-STOCK-SERVICE:
  ribbon:
  	#将ReadTimeout和ConnectTimeout调大一些方便测试
    #指的是建立连接后从服务器读取到可用资源所用的时间
    ReadTimeout: 20000
    #指的是建立连接所用时间,适用于网络状态正常的情况下,两端连接所用的时间
    ConnectTimeout: 20000
    ServerListRefreshInterval: 5000  #每五秒拉取一下服务列表
    NFLoadBalancerRuleClassName: com.chq.csdn.rule.FiveTimesRule

访问localhost:7001/order/addOrder/6
在这里插入图片描述
我们可以发现 超时不在报异常了 而是直接走了我们的降级方法

4.服务消费者降级

1.更改启动类

@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class, DruidDataSourceAutoConfigure.class})
@EnableEurekaClient
@EnableFeignClients
@EnableHystrix //服务消费方 使用这个注解
public class OpenFeignOrderApplication {
    public static void main(String[] args) {
        SpringApplication.run(OpenFeignOrderApplication.class,args);
    }
}

2.更改OrderController

@RestController
@RequestMapping("/order")
@DefaultProperties(defaultFallback = "globalFallBack")
public class OrderController{

    @Autowired
    private StockApi stockApi;

    @GetMapping("/addOrder/{seconds}")
    @HystrixCommand(fallbackMethod = "addOrderFallBack",
            commandProperties = {
                    //在6秒钟还没有返回 就执行兜底方法
                    @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "6000")
            })
    public R addOrder(@PathVariable("seconds") Integer seconds){
        return stockApi.subStock(seconds);
    }

    public R addOrderFallBack(Integer seconds){
        return R.failed("订单系统繁忙,请稍后再试");
    }
}

3.测试 重启order 访问localhost:7001/order/addOrder/6
在这里插入图片描述
这里我们可以得出结论 当服务消费者和服务提供者同时返回降级方法时,会走服务消费者的降级方法

5.全局降级方法

1.对于服务消费者order我们更改OrderController

@RestController
@RequestMapping("/order")
@DefaultProperties(defaultFallback = "globalFallBack") //全局默认兜底方法 使用globalFallBack方法
public class OrderController{

    @Autowired
    private StockApi stockApi;

    @GetMapping("/addOrder/{seconds}")
    @HystrixCommand(fallbackMethod = "addOrderFallBack",
            commandProperties = {
                    //在6秒钟还没有返回 就执行兜底方法
                    @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "6000")
            })
    public R addOrder(@PathVariable("seconds") Integer seconds){
        return stockApi.subStock(seconds);
    }

	//这里我们再写一个 
    @GetMapping("/insertOrder/{seconds}")
    @HystrixCommand//如不配置超时时间 这里默认超时时间为一秒 超过一秒未响应则执行全局兜底方法
    public R insertOrder(@PathVariable("seconds") Integer seconds){
        return stockApi.subStock(seconds);
    }

    public R addOrderFallBack(Integer seconds){
        return R.failed("订单系统繁忙,请稍后再试");
    }

    public  R globalFallBack(){
        return R.failed("全局的兜底方法");
    }
}

2.测试
访问http://localhost:7001/order/addOrder/6

在这里插入图片描述

当全局降级方法 和 局部降级方法都存在时 会走局部降级方法


访问http://localhost:7001/order/insertOrder/1
在这里插入图片描述
默认超时时长为1 走全局降级方法

6.对API接口降级方法

1.开启feign 支持 hystrix 在order模块的yml文件中

feign:
  hystrix:
    #开启feign 支持 hystrix 一定要开启 默认为关闭状态
    enabled: true

2.更改OrderController 注意各个注解和findOrder方法

@RestController
@RequestMapping("/order")
//@DefaultProperties(defaultFallback = "globalFallBack")
public class OrderController{

    @Autowired
    private StockApi stockApi;

    @GetMapping("/addOrder/{seconds}")
    @HystrixCommand(fallbackMethod = "addOrderFallBack",
            commandProperties = {
                    //在6秒钟还没有返回 就执行兜底方法
                    @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "6000")
            })
    public R addOrder(@PathVariable("seconds") Integer seconds){
        return stockApi.subStock(seconds);
    }


    @GetMapping("/insertOrder/{seconds}")
    @HystrixCommand
    public R insertOrder(@PathVariable("seconds") Integer seconds){
        return stockApi.subStock(seconds);
    }

    @GetMapping("/findOrder/{id}")
    public R findOrder(@PathVariable("id") Integer id){
        return stockApi.findStock(id);
    }

    public R addOrderFallBack(Integer seconds){
        return R.failed("订单系统繁忙,请稍后再试");
    }

    public  R globalFallBack(){
        return R.failed("全局的兜底方法");
    }
}

3.对api接口包进行操作

@Component
@FeignClient(value = "CLOUD-OPENFEGIN-STOCK-SERVICE",fallback = StockApiFallBackService.class)
public interface StockApi {
    /*
     * ip + port  => ribbon => localhost:8091
     * localhost:8091/stock/subStock
     * 远程调用
     * */
    @GetMapping("/stock/subStock/{seconds}")
    R subStock(@PathVariable("seconds") Integer seconds);

    @GetMapping("/stock/findStock/{id}")
    R findStock(@PathVariable("id") Integer id);
}

4.StockApiFallBackService类实现接口StockApi 在此写我们的降级方法

@Component
public class StockApiFallBackService implements StockApi{
    @Override
    public R subStock(Integer seconds) {
        return R.failed("Api 下的subStock 兜底方法");
    }

    @Override
    public R findStock(Integer id) {
        return R.failed("Api 下的findStock 兜底方法");
    }
}

5.对StockController进行更改

@RestController
@RequestMapping("/stock")
public class StockController {

    private Integer count = 0 ;

    @Value("${server.port}")
    public Integer port;

    @GetMapping("/subStock/{seconds}")
    //掉用此请求 走降级方法
    @HystrixCommand(fallbackMethod = "subStockFallBack",
            commandProperties = {
                //在6秒钟还没有返回 就执行兜底方法
                @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "6000")
    })
    public R subStock(@PathVariable("seconds") Integer seconds){
        try{
            System.out.println("睡眠"+seconds+"秒");
            TimeUnit.SECONDS.sleep(seconds);
        }catch (Exception e){
            e.printStackTrace();
        }
        HashMap<String, Object> map = new HashMap<>();
        map.put("port",port);
        map.put("count",++count);
        return R.ok(map);
    }

    @GetMapping("/findStock/{id}")
    //掉用此请求 走降级方法
    @HystrixCommand(fallbackMethod = "findStockFallBack",
            commandProperties = {
                    //在6秒钟还没有返回 就执行兜底方法
                    @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "6000")
            })
    public R findStock(@PathVariable("id") Integer id){
        if (id < 0){
            //异常除法 findStockFallBack 兜底方法
            throw new RuntimeException("id 不能为负数");
        }
        try {
            System.out.println("睡眠"+id+"秒");
            TimeUnit.SECONDS.sleep(id);
        }catch (Exception e){
            e.printStackTrace();
        }
        String info = "当前id:" + id + "的库存有:" + new Random().nextInt(100);
        HashMap<String, Object> map = new HashMap<>();
        map.put("port",port);
        map.put("info",info);
        return R.ok(map);
    }
    //降级方法 参数用不用都要写
    public R subStockFallBack(Integer seconds){
        return R.failed("subStock 的兜底方法");
    }

    //降级方法 参数用不用都要写
    public R findStockFallBack(Integer seconds){
        return R.failed("findStock 的兜底方法");
    }
}

6.测试
访问http://localhost:7001/order/findOrder/-1
在这里插入图片描述
访问http://localhost:7001/order/findOrder/6
在这里插入图片描述


总结

  • 方法一: 直接在被兜底方法上添加@HystrixCommand注解,并且在括号内标明兜底方法的方法名以及
    commandProperties属性。
    注意: 该方法中兜底方法与被兜底方法必须在同一个类下。该方法可以通过修改
    value值等属性对兜底方法进行相应控制。

  • 方法二: 只用在被兜底方法上添加@HystrixCommand注解,不需要在@HystrixCommand注解中标明任何属
    性。并在所在类上添加: @DefaultProperties(defaultFallback = “globalOrderFallBack”)
    该方法大大避免了代码的冗余,同一个兜底方法可以被多次调用,只用在需要被兜底的方法上添加
    @HystrixCommand注解即可。
    注意: 全局兜底方法没有参数。

  • 方法三: 新创建一个类(api包下),该类实现客服端服务的接口。当然想要让被调用的服务知道该类中是与之
    对应的兜底方法,还需要在客服端服务接口上的@FeignClient注解中添加上fallback属性
    注意: 该方法(第三种方法)只有在运行超时(例如服务端出现高并发,宕机),兜底方法才会执行,出现运行时
    异常则不会执行兜底方法。如果需要兼顾到运行时异常需要采用第1,2种方法。


三、Hystrix服务熔断

1.服务熔断机制简介

熔断机制是为了应对雪崩效应而出现的一种微服务链路保护机制。

当微服务系统中的某个微服务不可用或响应时间太长时,为了保护系统的整体可用性,熔断器会暂时切断请求对该服务的调用,并快速返回一个友好的错误响应。这种熔断状态不是永久的,在经历了一定的时间后,熔断器会再次检测该微服务是否恢复正常,若服务恢复正常则恢复其调用链路。

2.熔断工作流程

三种熔断状态:

  • 熔断关闭状态: 当服务访问正常时,熔断器处于关闭状态,服务调用方可以正常地对服务进行调用。

  • 熔断开启状态: 默认情况下,在固定时间内接口调用出错比率达到一个阈值(例如100条数据10条出错),熔断器会进入熔断开启状态。进入熔断状态后,后续对该服务的调用都会被切断,熔断器会执行本地的降级方法。

  • 半熔断状态 在半熔断状态下,熔断器会尝试恢复服务调用方对服务的调用,允许部分请求调用该服务,并监控其调用成功率。如果成功率达到预期,则说明服务已恢复正常,熔断器进入关闭状态;如果成功率仍旧很低,则重新进入熔断开启状态。

在这里插入图片描述
Hystrix 实现熔断机制:

  1. 当服务的调用出错率达到或超过 Hystix 规定的峰值后,熔断器进入熔断开启状态。
  2. 熔断器进入熔断开启状态后,Hystrix 会启动一个休眠时间窗,在这个时间窗内,调用服务会优先走降级方法
  3. 当有请求再次调用该服务时,会直接调用降级方法快速地返回失败响应,以避免系统雪崩。
  4. 当休眠时间窗到期后,Hystrix 会进入半熔断转态,允许部分请求对服务原来的主业务逻辑进行调用,并监控其调用成功率。
  5. 如果调用成功率达到预期,则说明服务已恢复正常,Hystrix 进入熔断关闭状态,服务原来的主业务逻辑恢复;否则 Hystrix 重新进入熔断开启状态,休眠时间窗口重新计时,继续重复第 2 到第 5 步。

四、服务监控 hystrix Dashboard

Hystrix 提供了调用监控功能,Hystrix 会持续地记录所有通过 Hystrix 发起的请求的执行信息,并以统计报表的形式展示给用户,包括每秒执行请求的数量、成功请求的数量和失败请求的数量等。

实现服务监控 hystrix Dashboard

1.在原有的代码基础上新建一个模块 cloud-hystrix-dashboard-service
在这里插入图片描述
2.创建主启动类

@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class, DruidDataSourceAutoConfigure.class})
@EnableHystrixDashboard
public class DashBoardApplication {
    public static void main(String[] args) {
        SpringApplication.run(DashBoardApplication.class,args);
    }
}

3.yml文件

server:
  port: 9999

4.对order模块的启动类下

@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class, DruidDataSourceAutoConfigure.class})
@EnableEurekaClient
@EnableFeignClients
@EnableHystrix //服务消费方 使用这个注解
public class OpenFeignOrderApplication {

    public static void main(String[] args) {
        SpringApplication.run(OpenFeignOrderApplication.class,args);
    }

    /*
     * 此配置是为了服务监控而已,与服务认错本身无关,springcloud升级后发现的坑
     * ServletRegistrationBean因为springboot的默认路劲不是 /hystrix.stream
     * 只要在自己的项目李配置上下面deServlet就可以了
     * */
    @Bean
    public ServletRegistrationBean getServlet(){
        HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();
        ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet);
        registrationBean.setLoadOnStartup(1);
        registrationBean.addUrlMappings("/hystrix.stream");
        registrationBean.setName("HystrixMetricsStreamServlet");
        return registrationBean;
    }
}

5.启动项目 访问 localhost:9999/hystrix
在这里插入图片描述

6.进入Hystrix监控页面
在这里插入图片描述

7.访问 http://localhost:7001/order/findOrder/0 观察监控页面变化
在这里插入图片描述
通过Hystrix可以观察到我们服务的变化,不过Spring Cloud Alibaba出版的Sentinel会更加整洁,更加好用,但是他们的原理差不多,理解Hystrix可以学习Sentinel会事半功倍

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2244907.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Facebook商城号封号的原因是什么?

Facebook商城作为一个重要的销售平台&#xff0c;不仅为商家提供了巨大的市场机会&#xff0c;也带来了一系列需要警惕的风险&#xff0c;其中包括账号被封的风险。本文将从环境异常、频繁操作和违规行为三个主要方面深入探讨&#xff0c;解析导致Facebook商城账号被封禁的具体…

Android okhttp 网络链接各阶段监控

步骤 1: 添加依赖 在项目的 build.gradle 文件中&#xff0c;添加 OkHttp 依赖&#xff1a; implementation com.squareup.okhttp3:okhttp:4.11.0 步骤 2: 创建自定义的 EventListener 创建一个自定义的 EventListener 类&#xff1a; import android.util.Log import okht…

MyBatis——#{} 和 ${} 的区别和动态 SQL

1. #{} 和 ${} 的区别 为了方便&#xff0c;接下来使用注解方式来演示&#xff1a; #{} 的 SQL 语句中的参数是用过 ? 来起到类似于占位符的作用&#xff0c;而 ${} 是直接进行参数替换&#xff0c;这种直接替换的即时 SQL 就可能会出现一个问题 当传入一个字符串时&#xff…

【Python】30个Python爬虫的实战项目!!!(附源码)

Python爬虫是数据采集自动化的利器。本文精选了30个实用的Python爬虫项目&#xff0c;从基础到进阶&#xff0c;每个项目都配有完整源码和详细讲解。通过这些项目的实战&#xff0c;可以全面掌握网页数据抓取、反爬处理、并发下载等核心技能。 一、环境准备 在开始爬虫项目前…

深述C++模板类

1、前言 函数模板是通用函数的描述&#xff0c;类模板是通用类的描述&#xff0c;使用任意类型来描述类的定义。和函数模板有很多相似的地方&#xff0c;关于函数模板可以看我之前写过的一篇文章&#xff1a;简述C函数模板。这里就不过多赘述。 2、模板类的基本概念 模板类的…

C语言教程指针笔记整理

https://www.bilibili.com/video/BV1cx4y1d7Ut?spm_id_from333.788.videopod.episodes&vd_sourcee8984989cddeb3ef7b7e9fd89098dbe8&p107 本篇为贺宏宏老师C语言教程指针部分笔记整理 //.c文件 #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include …

从二维到一维:动态规划矩阵问题的优化之道

动态规划中的矩阵问题是非常经典的应用场景&#xff0c;比如最小路径和问题。这类问题很自然地可以想到使用二维 dp 数组来求解。 我们定义&#xff1a; dp[i][j] 表示从矩阵的第 i行第 j列到右下角的最小路径和。 基本解法 求解过程从右下角开始&#xff0c;向左上角遍历&am…

git,ssh免密公钥配置,gitee为例,GitHub,gitlab同理

git&#xff0c;ssh免密公钥配置&#xff0c;gitee为例&#xff0c;视频教程在这 git&#xff0c;ssh免密公钥配置&#xff0c;gitee为例&#xff0c;GitHub&#xff0c;gitlab同理_哔哩哔哩_bilibili 一、进入.ssh目录 cd ~/.ssh 二、查看是否有id_rsa.pub这个文件 分为…

Spring Boot整合Kafka,实现单条消费和批量消费,示例教程

如何安装Kafka&#xff0c;可以参考docker搭载Kafka集群&#xff0c;一个文件搞定&#xff0c;超简单&#xff0c;亲试可行-CSDN博客 1、在pom.xml中加入依赖 <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-sta…

基于Vue+SpringBoot的求职招聘平台

平台概述 本平台是一个高效、便捷的人才与职位匹配系统&#xff0c;旨在为求职者与招聘者提供一站式服务。平台内设三大核心角色&#xff1a;求职者、招聘者以及超级管理员&#xff0c;每个角色拥有独特的功能模块&#xff0c;确保用户能够轻松完成从信息获取到最终录用的整个…

FPGA FIFO系列 - FIFO使用中需要注意的若干问题

FIFO使用中需要注意的若干问题 文章目录 FIFO使用中需要注意的若干问题前言场景1&#xff1a;包数据FIFO设计之冗余法场景2、FIFO数据传输之流控总结 前言 场景1&#xff1a;包数据FIFO设计之冗余法 场景&#xff1a;类似图像、文字等码流数据是不需要重复被访问的&#xff0c…

.NET 9 - BinaryFormatter移除

1.简单介绍 .NET 9 SDK正式版已经发布, 下载地址是.NET9 同时.NET Conf 2024 大会已经从2024-11-13开始了&#xff0c;感觉Aspire和AI的内容相对挺多的&#xff0c;主题分享演示时候打开的网站大部分都是Blazor制作的。 这次.NET Conf 2024老师也再次说明了一下&#xff0c;…

[免费]SpringBoot+Vue毕业设计论文管理系统【论文+源码+SQL脚本】

大家好&#xff0c;我是java1234_小锋老师&#xff0c;看到一个不错的SpringBootVue毕业设计论文管理系统&#xff0c;分享下哈。 项目视频演示 【免费】SpringBootVue毕业设计论文管理系统 Java毕业设计_哔哩哔哩_bilibili 项目介绍 现代经济快节奏发展以及不断完善升级的信…

C# 高级--反射 详解

一、反射是什么 1、C#编译运行过程 高级语言->编译->dll/exe文件->CLR/JIT->机器码 2、原理解析metadata&#xff1a;元数据数据清单&#xff0c;记录了dll中包含了哪些东西,是一个描述。IL&#xff1a;中间语言&#xff0c;编译把高级语言编译后得到的C#中最真…

OpenCV与AI深度学习|16个含源码和数据集的计算机视觉实战项目(建议收藏!)

本文来源公众号“OpenCV与AI深度学习”&#xff0c;仅用于学术分享&#xff0c;侵权删&#xff0c;干货满满。 原文链接&#xff1a;分享&#xff5c;16个含源码和数据集的计算机视觉实战项目 本文将分享16个含源码和数据集的计算机视觉实战项目。具体包括&#xff1a; 1. 人…

【软考网工笔记】网络基础理论——应用层

TLv 基本编码规则&#xff08;BER&#xff09;将ASN.1表示的抽象类型值编码为字节串&#xff0c;这种字节串的结构为&#xff1a;类型——长度——值&#xff0c;简称TLv。 其中&#xff0c;值部分还可以递归的在编码为TLv结构&#xff0c;一具有表达复杂结构的能力。 IP地址…

用Python爬虫“偷窥”1688商品详情:一场数据的奇妙冒险

引言&#xff1a;数据的宝藏 在这个信息爆炸的时代&#xff0c;数据就像是一座座等待挖掘的宝藏。而对于我们这些电商界的探险家来说&#xff0c;1688上的商品详情就是那些闪闪发光的金子。今天&#xff0c;我们将化身为数据的海盗&#xff0c;用Python这把锋利的剑&#xff0…

企业网络安全规划建设实践

规划是指较全面或长远的计划。凡事预则立&#xff0c;不预则废&#xff01; 在企业战略规划方面&#xff0c;随着市场环境变化速度的不断加快&#xff0c;人们越来越意识到企业战略规划对企业生存和发展的重要性&#xff0c;战略规划能帮助企业解决影响组织未来发展最重要、最…

QT基本绘图

QT绘图 1.概述 这篇文章介绍如何绘图 2.绘图基本操作 创建一个普通的widget类型的项目 在widget.h 文件中重写绘图事件 #ifndef WIDGET_H #define WIDGET_H#include <QWidget>QT_BEGIN_NAMESPACE namespace Ui { class Widget; } QT_END_NAMESPACEclass Widget : p…

Linux驱动开发(7):使用设备树实现RGB 灯驱动

通过上一小节的学习&#xff0c;我们已经能够编写简单的设备树节点&#xff0c;并且使用常用的of函数从设备树中获取我们想要的节点资源。 这一小节我们带领大家使用设备树编写一个简单的RGB灯驱动程序&#xff0c;加深对设备树的理解。 1. 实验说明 本节实验使用到 EBF6ULL-…