Alibaba SpringCloud集成Nacos、Sentinel实现服务治理-17

news2024/11/17 23:29:59

关于服务治理

总体而言,限流和降级作为微服务架构中的重要机制,尽管在实现上可能有多种方式,但它们都着眼于保护服务提供者和消费者,在面对异常情况时确保系统稳定运行。限流关注于保护服务提供者,控制请求流量;而降级则关注于服务消费者,确保在服务不可用或异常情况下提供基本的功能。

  • 限流是一种针对服务提供者的策略,用于控制对特定服务接口或服务实例的访问量。其目的在于保护服务提供者免受过大请求流量的影响,确保服务稳定性。限流措施可以在服务提供者或服务消费者两端实现,通过设定流量阈值并采取排队、拒绝请求或返回错误信息等方式来控制流量,从而保护服务
  • 降级是针对服务消费者的应对策略,在服务出现异常或限流时,通过对服务调用进行降级处理,确保消费者端能够在异常情况下正常工作。降级的目的在于转变为弱依赖状态,使系统能够在服务不可用时提供基本的功能或数据。这种策略可以在服务消费者端实施,通过返回默认值、提供备用数据或简化功能等方式来保证系统的可用性。
  • 断路器:一个自动中断,恢复的功能,实际场景中用的不多。

在这里插入图片描述

1、Sentinel.dashbod 图形化界面安装

  1. 下载地址:https://github.com/alibaba/Sentinel/releases

  2. 启动:下面命令中的端口号可以根据需要修改

java -Dserver.port=9999 -Dcsp.sentinel.dashboard.server=localhost:9999 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.8.7.jar

在这里插入图片描述

  1. 通过 http://localhost:9999 访问图形化界面,密码默认为sentinel。
    在这里插入图片描述

2、alibaba-sentinel-server

服务端主要是限流配置

在这里插入图片描述

pom.xml

在本示例中,主要用到了三个主要组件,nacos服务发现,sentinel,以及nacos配置中心(做为sentinel规则的存储,否则当服务重启后规则就会丢失)

        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>

        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>

        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-sentinel-datasource</artifactId>
        </dependency>

        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-datasource-nacos</artifactId>
        </dependency>

application.properties配置

这里配置比较多,可参考上面jar包引用说明查看,主要是配置了Nacos和Sentinel控制台的地址。

spring.profiles.active = dev
spring.application.name=AlibabaSpringbootSentinelServer
server.port=19504

management.endpoints.web.exposure.include=*
management.endpoint.health.show-details=always

spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
spring.cloud.nacos.discovery.fail-fast=true
spring.cloud.nacos.username=nacos
spring.cloud.nacos.password=nacos

spring.cloud.sentinel.transport.dashboard=localhost:9999
spring.cloud.sentinel.transport.port=8719 #与sentinel通信的转用端口
spring.cloud.sentinel.eager=true
spring.cloud.sentinel.web-context-unify=true

spring.cloud.sentinel.datasource.ds2.nacos.server-addr=127.0.0.1:8848
spring.cloud.sentinel.datasource.ds2.nacos.username=nacos
spring.cloud.sentinel.datasource.ds2.nacos.password=nacos
#需要nocas中配合一个名为 AlibabaSpringbootSentinelServer-sentinel 的文件,这里不需要加-dev啥的,因为这处指定死了名称
spring.cloud.sentinel.datasource.ds2.nacos.dataId=${spring.application.name}-sentinel
spring.cloud.sentinel.datasource.ds2.nacos.groupId=DEFAULT_GROUP
spring.cloud.sentinel.datasource.ds2.nacos.data-type=json
#type=flow 以 JSON 格式返回现有的限流规则,degrade 返回现有生效的降级规则列表,system 则返回系统保护规则。
spring.cloud.sentinel.datasource.ds2.nacos.rule-type=flow

SpringbootApplication启动类

主要是添加了@EnableDiscoveryClient注解,如果不需要服务发现可以去掉。

@Slf4j
@SpringBootApplication(scanBasePackages = {"com.korgs",  "cn.hutool.extra.spring"})
@Configuration
@EnableConfigurationProperties
@ServletComponentScan
@RestController
@EnableDiscoveryClient
public class AlibabaSpringbootSentinelServerApplication {

	@Value("${server.port}")
	private String serverPort;

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

	@GetMapping("/helloworld/{uuid}")
	public BaseResponse<String> helloWorld(@PathVariable String uuid){
		String str = LogGenerator.trackLog()
				+ " uuid=" + uuid + " I am busy to handle this request."
				+ " serverPort=" + serverPort;
		log.info( str );
		return BaseResponse.success(str);
	}
}

Controller测试类实现

给普通的uri上添加@SentinelResource(value = "userInfo", blockHandler = "exceptionHandler"),这个注解在文章最后会详细解释。

@Slf4j
@RestController
@RequestMapping("/api/user")
public class UserController {

    @Value("${server.port}")
    private String serverPort;

    @SentinelResource(value = "userInfo", blockHandler = "exceptionHandler")
    @GetMapping("/userinfo/{uuid}")
    public BaseResponse<String> userInfo(@PathVariable String uuid){
        String str = LogGenerator.trackLog()
                + " uuid=" + uuid + " I am busy to handle userInfo."
                + " serverPort=" + serverPort;
        log.info( str );
        return BaseResponse.success(str);
    }

    @SentinelResource(value = "userOrder")
    @GetMapping("/userorderlist/{uuid}")
    public ListResponse<List<String>> userOrder(@PathVariable String uuid){
        String str = LogGenerator.trackLog()
                + " uuid=" + uuid + " I am busy to handle userInfo."
                + " serverPort=" + serverPort;
        log.info( str );
        List<String> userOrders = new ArrayList<>();
        userOrders.add("order1");
        userOrders.add("order2");
        userOrders.add("order3");
        userOrders.add("order4");
        return ListResponse.success(userOrders);
    }

    @SentinelResource(value = "userStatus")
    @GetMapping("/userstatus/{uuid}")
    public BaseResponse<String> userStatus(@PathVariable String uuid){
        String str = LogGenerator.trackLog()
                + " uuid=" + uuid + " I am busy to handle userStatus."
                + " serverPort=" + serverPort;
        return BaseResponse.success(str);
    }

    public BaseResponse<String> exceptionHandler(long s, BlockException ex) {
        ex.printStackTrace();
        return BaseResponse.error(s+"");
    }
}

3、Sentinel配置限流规则

限流规则配置

  • 配置之前要先启动 alibaba-sentinel-server 服务,然后登陆sentinel客户端,就可以发现此服务,然后在流控规则中新增规则即可。
    在这里插入图片描述
  • 配置规则,规则可以注解的value或uri来配置。
    比如下面这个配置
    @SentinelResource(value = "userInfo", blockHandler = "exceptionHandler")
    @GetMapping("/userinfo/{uuid}")
    public BaseResponse<String> userInfo(@PathVariable String uuid){
      
    }

资源名可以配置成userInfo,也可以配置成/userinfo/{uuid},一般建议配置成@SentinelResource注解的值,这样也起到了一个解耦的作用。
在这里插入图片描述

Controller限流功能测试

因为上面规则的阈值配置成了1,所以我们快速访问上述的userinfo地址。会发现uri返回时好时坏。在浏览器中打开http://localhost:19504/swagger-ui/index.html,如下:
在这里插入图片描述
上述红框就是限流后的返回结果。


4、alibaba-sentinel-client

客户端主要是降级配置,这个示例中添加了ribbon和RestTemplate支持,前者用于负载,后者用于远程访问。
在这里插入图片描述

pom.xml

    <dependencies>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-loadbalancer</artifactId>
        </dependency>

        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>
    </dependencies>

application.properties配置

spring.profiles.active = dev
spring.application.name=AlibabaSpringbootSentinelClient
server.port=19505

management.endpoints.web.exposure.include=*

spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
spring.cloud.nacos.discovery.fail-fast=true
spring.cloud.nacos.username=nacos
spring.cloud.nacos.password=nacos

#自定义配置服务端
service-url.nacos-service = http://AlibabaSpringbootSentinelServer

SpringbootApplication启动类

主要是添加了@EnableDiscoveryClient注解,如果不需要服务发现可以去掉。

@Slf4j
@SpringBootApplication(scanBasePackages = {"com.korgs",  "cn.hutool.extra.spring"})
@Configuration
@EnableConfigurationProperties
@ServletComponentScan
@RestController
@EnableDiscoveryClient
public class AlibabaSpringbootSentinelClientApplication {

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

	@GetMapping("/helloworld")
	public String helloWorld(){
		log.info( LogGenerator.trackLog()
				+ "msg=" + "I am busy to handle this request.");
		return "hello world";
	}
}

配置RestTemplate

添加@SentinelRestTemplate,配置全局降级响应

@Configuration
public class RibbonConfig {
    @Bean
    @LoadBalanced
    @SentinelRestTemplate
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

Controller测试类实现

配置自定义降级响应,即被服务端限流后的响应

@Slf4j
@RestController
@RequestMapping("/api/load")
public class LoadUserController {

    @Autowired
    private RestTemplate restTemplate;

    @Value("${service-url.nacos-service}")
    private String ribbonServiceUrl;

    /*熔断,降级,这里主要用到的是fallback标签*/
    @GetMapping("/fusing")
    @SentinelResource(value = "fusing", fallback = "handleFallback")
    public BaseResponse<String> fusing(String uuid){
        String result =  restTemplate.getForObject(ribbonServiceUrl + "/api/user/userinfo/{1}", String.class, uuid);

        return BaseResponse.success(result);
    }

    public BaseResponse<String> handleFallback(String uuid, Throwable e) {
        log.error("handleFallback2 id:{},throwable class:{}", uuid, e.getClass());
        return BaseResponse.error("服务降级返回");
    }
}

Controller被限流后的降级测试

  • 先启动 alibaba-sentinel-server
  • 再启动 alibaba-sentinel-client
  • 打开 http://localhost:19505/swagger-ui
    在这里插入图片描述
    当快速访问时就会发现,返回结果变成了自定义的描述了。

5、Sentinel详细使用说明

Sentinel注解

@SentinelRestTemplate注解

此注解的属性支持限流(blockHandler, blockHandlerClass)和降级(fallback, fallbackClass)的处理。下面的示例是演示调用服务时时支持的限流。

即在消费者一端实现的限流配置,但目的也是为了保护服务提供者,一般不太常用,还是在提供者端配置为好。在消费端限流(也称降级)是指在服务提供者发生异常后,客户端的的处理逻辑

//配置全局限流异常
@Bean
@SentinelRestTemplate(blockHandler = "handleException", blockHandlerClass = ExceptionUtil.class)
public RestTemplate restTemplate() {
  return new RestTemplate();
}

@SentinelRestTemplate注解 中 blockHandler 或 fallback 属性对应的方法必须是对应 blockHandlerClass 或 fallbackClass 属性中的静态方法。
该方法的参数跟返回值跟 org.springframework.http.client.ClientHttpRequestInterceptor#interceptor 方法一致,其中参数多出了一个 BlockException 参数用于获取 Sentinel 捕获的异常。

比如上述 @SentinelRestTemplate 注解中 ExceptionUtil 的 handleException 属性对应的方法声明如下:

public class ExceptionUtil {
    public static ClientHttpResponse handleException(HttpRequest request, byte[] body, ClientHttpRequestExecution execution, BlockException exception) {
    }
  public static SentinelClientHttpResponse handleException(HttpRequest request,
                                                           byte[] body, ClientHttpRequestExecution execution, BlockException ex) {
    System.out.println("Oops: " + ex.getClass().getCanonicalName());
    return new SentinelClientHttpResponse("custom block info");
  }
}

当使用 RestTemplate 调用被 Sentinel 熔断后,会返回 RestTemplate request block by sentinel 信息,或者也可以编写对应的方法自行处理返回信息。这里提供了 SentinelClientHttpResponse 用于构造返回信息。

@SentinelResource 注解

public class TestService {

    // 原函数
    @SentinelResource(value = "hello", blockHandler = "exceptionHandler", fallback = "helloFallback")
    public String hello(long s) {
        return String.format("Hello at %d", s);
    }
    
    // Fallback 函数,函数签名与原函数一致或加一个 Throwable 类型的参数.
    public String helloFallback(long s) {
        return String.format("Halooooo %d", s);
    }

    // Block 异常处理函数,参数最后多一个 BlockException,其余与原函数一致.
    public String exceptionHandler(long s, BlockException ex) {
        ex.printStackTrace();
        return "Oops, error occurred at " + s;
    }

    // 这里单独演示 blockHandlerClass 的配置.
    // 对应的 `handleException` 函数需要位于 `ExceptionUtil` 类中,并且必须为 public static 函数.
    @SentinelResource(value = "test", blockHandler = "handleException", blockHandlerClass = {ExceptionUtil.class})
    public void test() {
        System.out.println("Test");
    }
}
  • value:资源名称,必需项(不能为空)
  • entryType:entry 类型,可选项(默认为 EntryType.OUT)
  • blockHandler / blockHandlerClass(限流处理): blockHandler 对应处理 BlockException 的函数名称,可选项。blockHandler 函数访问范围需要是 public,返回类型需要与原方法相匹配,参数类型需要和原方法相匹配并且最后加一个额外的参数,类型为 BlockException。blockHandler 函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定 blockHandlerClass 为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析。
  • fallback / fallbackClass(异常处理):fallback 函数名称,可选项,用于在抛出异常的时候提供 fallback 处理逻辑。fallback 函数可以针对所有类型的异常(除了 exceptionsToIgnore 里面排除掉的异常类型)进行处理。fallback 函数签名和位置要求:
    • 返回值类型必须与原函数返回值类型一致;
    • 方法参数列表需要和原函数一致,或者可以额外多一个 Throwable 类型的参数用于接收对应的异常。
    • fallback 函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定 fallbackClass 为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析。
  • defaultFallback(since 1.6.0):默认的 fallback 函数名称,可选项,通常用于通用的 fallback 逻辑(即可以用于很多服务或方法)。默认 fallback 函数可以针对所有类型的异常(除了 exceptionsToIgnore 里面排除掉的异常类型)进行处理。若同时配置了 fallback 和 defaultFallback,则只有 fallback 会生效。defaultFallback 函数签名要求:
    • 返回值类型必须与原函数返回值类型一致;
    • 方法参数列表需要为空,或者可以额外多一个 Throwable 类型的参数用于接收对应的异常。
    • defaultFallback 函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定 fallbackClass 为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析。
  • exceptionsToIgnore(since 1.6.0):用于指定哪些异常被排除掉,不会计入异常统计中,也不会进入 fallback 逻辑中,而是会原样抛出。

配置全局异常处理

Sentinel内置的 URL 限流触发后默认处理逻辑是,直接返回 “Blocked by Sentinel (flow limiting)”。 如果需要自定义处理逻辑,实现的方式如下:

public class CustomUrlBlockHandler implements UrlBlockHandler {
    @Override
    public void blocked(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws IOException {
        // todo add your logic
    }
}

WebCallbackManager.setUrlBlockHandler(new CustomUrlBlockHandler());

Sentinel中配置限流规则

可以sentinel图形化界面中配置限流规则,可以用资源名,也可以添加相对的url路径,比如下面例子,在资源名对话框中可以配置userInfo 或 /api/user/userinfo

@RestController("/api/user")
public class UserController{
  @SentinelResource(value = "userInfo", blockHandler = "exceptionHandler")
  @GetMapping("/userinfo")
  public BaseResponse<String> userInfo(String uuid){
    String str = LogGenerator.trackLog()
            + " uuid=" + uuid + " I am busy to handle userInfo."
            + " serverPort=" + serverPort;
    log.info( str );
    return BaseResponse.success(str);
  }
}

给sentinel提供 ReadableDataSource 存储支持

默认情况下,当我们在Sentinel控制台中配置规则时,控制台推送规则方式是通过API将规则推送至客户端并直接更新到内存中。一旦我们重启应用,规则将消失。

Sentinel starter 整合了目前存在的几类 ReadableDataSource。只需要在配置文件中进行相关配置,即可在 Spring 容器中自动注册 DataSource。 下面我们介绍下如何将配置规则进行持久化,以存储到Nacos为例。

spring.cloud.sentinel.datasource.ds2.nacos.server-addr=127.0.0.1:8848
spring.cloud.sentinel.datasource.ds2.nacos.username=nacos
spring.cloud.sentinel.datasource.ds2.nacos.password=nacos

#需要nocas中配合一个名为 AlibabaSpringbootSentinelServer-sentinel 的文件,这里不需要加-dev啥的,因为这处指定死了名称
spring.cloud.sentinel.datasource.ds2.nacos.dataId=${spring.application.name}-sentinel
spring.cloud.sentinel.datasource.ds2.nacos.groupId=DEFAULT_GROUP
spring.cloud.sentinel.datasource.ds2.nacos.data-type=json

#type=flow 以 JSON 格式返回现有的限流规则,degrade 返回现有生效的降级规则列表,system 则返回系统保护规则。
spring.cloud.sentinel.datasource.ds2.nacos.rule-type=flow

然后在nacos中配置一外名为AlibabaSpringbootSentinelServer-sentinel的文件,这样就会在sentinel中存储了。文件内容如下:

[
  {
    "resource": "userInfo", //资源名称
    "limitApp": "default", //来源应用
    "grade": 1,   //阈值类型,0表示线程数,1表示QPS
    "count": 1,    //单机阈值
    "strategy": 0,  //流控模式,0表示直接,1表示关联,2表示链路
    "controlBehavior": 0,  //流控效果,0表示快速失败,1表示Warm Up,2表示排队等待
    "clusterMode": false  //是否集群
  }
]

6、与openFeign配合实现降级

  • alibaba-sentinel-openFeign-client:19508

此服务和上面的是alibaba-sentinel-client功能一样,只不过把ribbon换成了openFiegn实现,测试方法也完全一样,不详细说了。

但在业务实现中建议使用openFiegn。

在这里插入图片描述

源码下载

涉及模块:

  • alibaba-sentinel-server:19501,服务端
  • alibaba-sentinel-client : 19506, ribbon实现的客户端
  • alibaba-sentinel-openFeign-client: 19508,openFeign实现的客户端

源码下载:

  • 基础框架源码下载
  • Alibaba SpringCloud集成Nacos、Sentinel实现服务治理

源码运行方法:

  • 模块详细功能说明和运行测试方法

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

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

相关文章

20232810 2023-2024-2 《网络攻防实践》实验九

一、实践内容 1.1 反汇编 1.1.1 编程原理 编程的原理是一套指导软件开发和维护的概念、原则和实践&#xff0c;包括抽象以简化复杂系统、模块化以分解程序、封装以隐藏内部状态、继承以共享特性、多态以允许不同响应、算法和数据结构以组织计算和存储、控制结构以控制流程、…

UVa11419 SAM I AM

UVa11419 SAM I AM 题目链接题意分析AC 代码 题目链接 UVA - 11419 SAM I AM 题意 给出一个 RC 大小的网格&#xff0c;网格上面放了一些目标。可以在网格外发射子弹&#xff0c;子弹会沿着垂直或者水平方向飞行&#xff0c;并且打掉飞行路径上的所有目标&#xff0c;如下图所…

System V IPC(进程间通信)机制详解

文章目录 一、引言二、System V IPC的基本概念1、IPC结构的引入2、IPC标识符&#xff08;IPC ID&#xff09;3、S ystem V的优缺点 三、共享内存&#xff08;Shared Memory&#xff09;1、共享内存的基本概念2、共享内存的创建&#xff08;shmget&#xff09;3、共享内存的附加…

深入探索Android签名机制:从v1到v3的演进之旅

引言 在Android开发的世界中&#xff0c;APK的签名机制是确保应用安全性的关键环节。随着技术的不断进步&#xff0c;Android签名机制也经历了从v1到v3的演进。本文将带你深入了解Android签名机制的演变过程&#xff0c;揭示每个版本背后的技术细节&#xff0c;并探讨它们对开…

企业如何通过云服务器实现全球连通运营

如果说互联网是一座桥&#xff0c;连接起了全球各地的信息&#xff0c;那云服务器就如同一座高速公路&#xff0c;帮助企业轻松实现跨国家、跨时区的全球运营。 这个听起来像科幻电影的情节其实已经成为了我们现实生活的一部分。现在就来具体看一下如何做到这一点吧。 其一&…

Django开发实战之定制管理后台界面及知识梳理(中)

上一篇文章末尾讲到如何能够展示更多的字段在界面上&#xff0c;那么针对整个界面数据&#xff0c;如果我想按照某一个条件进行筛选&#xff0c;我该怎么做呢&#xff0c;只需要加上下面一行代码 注意&#xff1a;中途只有代码片段&#xff0c;文末有今天涉及的所有代码 1、增…

RuoYi-Vue-Plus (Logback 和 logback-plus.xml 、p6spy)

项目后本地日志 一、logback依赖 打开最外层的 pom.xml,查看 SpringBoot的依赖配置。 <dependencyManagement><dependencies><!-- SpringBoot的依赖配置--><dependency><groupId>org.springframework.boot</groupId><artifactId>s…

视频汇聚管理/安防监控系统EasyCVR如何开启和调用验证码登录接口?

安防视频监控/视频集中存储/云存储/磁盘阵列EasyCVR平台部署轻快&#xff0c;可支持的主流标准协议有国标GB28181、RTSP/Onvif、RTMP等&#xff0c;以及支持厂家私有协议与SDK接入&#xff0c;包括海康Ehome、海大宇等设备的SDK等。视频汇聚融合管理平台EasyCVR既具备传统安防视…

项目实施方案:多点异地机动车典型系统试验状态可视监控系统

目录 一、需求分析 1.1项目背景 1.2项目概述 二、系统优势 2.1兼容性能力强 2.2接入协议多样 2.3并发能力强 2.3.1 单平台参数 2.3.2 多平台性能参数 2.4 系统稳定性 三、建设目标 3.1安全性 3.2可扩展性 3.3易用性 3.4兼容性 3.5 响应能力 四、系统整体解决方…

C#窗体程序设计笔记:如何调出控件工具箱,并设置控件的属性

文章目录 调出控件工具箱设置控件属性 调出控件工具箱 使用Visual Studio打开C#解决方案后&#xff0c;初始界面如下图所示&#xff1a; 接着&#xff0c;在上方的菜单栏依次选择“视图”“工具箱”&#xff0c;即可打开工具箱&#xff0c;如下图所示&#xff1a; 设置控件属…

Service Worker的生命周期和全局对象和API

Service Worker的生命周期和全局对象和API 当我们注册了Service Worker后&#xff0c;它会经历生命周期的各个阶段&#xff0c;同时会触发相应的事件。整个生命周期包括了&#xff1a;installing --> installed --> activating --> activated --> redundant。当Se…

vue2人力资源项目6角色管理

elementUi编写表格样式及分页组件 <template><div class"container"><div class"app-container"><!--角色管理内容--><div class"role-operate"><el-button type"primary">添加角色</el-butt…

高级个人主页

高级个人主页 效果图部分代码领取源码下期更新预报 效果图 部分代码 <!DOCTYPE html> <html lang"en"><head><meta charset"utf-8" name"viewport" content"widthdevice-width, initial-scale1, maximum-scale1, use…

2024年3月 电子学会 青少年等级考试机器人理论真题五级

202403 青少年等级考试机器人理论真题五级 第 1 题 下图程序运行后&#xff0c;串口监视器显示的结果是&#xff1f;&#xff08; &#xff09; A&#xff1a;0 B&#xff1a;1 C&#xff1a;3 D&#xff1a;4 第 2 题 下列选项中&#xff0c;关于74HC595移位寄存器芯片的…

【ARM Cortex-M 系列 2.3 -- Cortex-M7 Debug event 详细介绍】

请阅读【嵌入式开发学习必备专栏】 文章目录 Cortex-M7 Debug eventDebug events Cortex-M7 Debug event 在ARM Cortex-M7架构中&#xff0c;调试事件&#xff08;Debug Event&#xff09;是由于调试原因而触发的事件。一个调试事件会导致以下几种情况之一发生&#xff1a; 进…

2024第16届四川教育后勤装备展6月1日举办 欢迎参观

2024第16届四川教育后勤装备展6月1日举办 欢迎参观 邀请函 主办单位&#xff1a; 中国西部教体融合博览会组委会 承办单位&#xff1a;重庆港华展览有限公司 博览会主题&#xff1a;责任教育 科教兴邦 组委会&#xff1a;交易会159交易会2351交易会9466 展会背景 成都…

matlab使用2-基础绘图

matlab使用2-基础绘图 文章目录 matlab使用2-基础绘图1. 二维平面绘图2. 三维立体绘图3. 图形窗口的分割 1. 二维平面绘图 % 创建一些二维数据 x 0:0.01:10; % x轴的数据点&#xff0c;从0到10&#xff0c;间隔为0.01 y sin(x); % y轴的数据点&#xff0c;是x的正弦…

实时“秒回”,像真人一样语音聊天,GPT-4o模型强到恐怖

今天凌晨OpenAl发布了 GPT-4o&#xff0c;这是一种新的人工智能模式&#xff0c;集合了文本、图片、视频、语音的全能模型。 能实时响应用户的需求&#xff0c;并通过语音来实时回答你&#xff0c;你可以随时打断它。还具有视觉能力&#xff0c;能识别物体并根据视觉做出快速的…

基准电流源电路仿真

1.补全电路 2.更改vpluse属性 3.添加tran仿真&#xff0c;因为加入启动电路主要看的就是tran仿真 4.启动仿真 5.看电路曲线 先点这个main form 不用选择ok&#xff0c;直接点中四条线&#xff0c;中间第2条曲线如果出现那样一个小波动后面没有起伏就说明成功了。

什么是Keycloak?怎么样使用Keycloak实现登录和权限验证?

什么是Keycloak&#xff1f;怎么样使用Keycloak实现登录和权限验证&#xff1f; 文章目录 什么是Keycloak&#xff1f;怎么样使用Keycloak实现登录和权限验证&#xff1f;Open Source Identity and Access Management(开源身份和访问管理)1、支持的协议&#xff1a;2、安装与部…