SpringCloud 微服务系列——【服务间的通信方式、OpenFeign、Hystrix组件使用】

news2024/11/23 21:46:18

在这里插入图片描述

✅作者简介:2022年博客新星 第八。热爱国学的Java后端开发者,修心和技术同步精进。
🍎个人主页:Java Fans的博客
🍊个人信条:不迁怒,不贰过。小知识,大智慧。
💞当前专栏:SpringCloud 微服务学习专栏
✨特色专栏:国学周更-心性养成之路
🥭本文内容:SpringCloud 微服务系列——【服务间的通信方式、OpenFeign、Hystrix组件使用】

文章目录

    • 1、服务间通信方式
      • 1.1、基于RestTemplate的服务调用
      • 2.2、基于Ribbon的服务调用
    • 2、OpenFeign组件的使用
    • 3、Hystrix组件使用

在这里插入图片描述

1、服务间通信方式

在整个微服务架构中,服务间的服务改如何调用,有哪些调用方式?

在这里插入图片描述

在springcloud中服务间调用方式主要是使用 http restful方式进行服务间调用。

1.1、基于RestTemplate的服务调用

spring框架提供的RestTemplate类可用于在应用中调用rest服务,它简化了与http服务的通信方式,统一了RESTful的标准,封装了http链接, 我们只需要传入url及返回值类型即可。相较于之前常用的HttpClient,RestTemplate是一种更优雅的调用RESTful服务的方式。

创建用户服务的springboot工程

引入依赖

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--        引入consul客户端依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-consul-discovery</artifactId>
        </dependency>
        <!--        引入健康检查依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
    </dependencies>

编写application.yml文件

server:
  port: 8888  #配置服务端口
spring:
  application:
    name: USERS  #配置服务名
  cloud:
    consul:
      port: 8500  #注册中心端口
      host: localhost #注册中心地址

编写启动类,添加注解

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

创建订单服务的springboot工程

引入依赖(参照用户服务)

编写application.yml文件

server:
  port: 8889  #配置服务端口
spring:
  application:
    name: ORDERS  #配置服务名
  cloud:
    consul:
      port: 8500  #注册中心端口
      host: localhost #注册中心地址

编写启动类,添加注解

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

编写用户服务和订单服务的控制层,并实现调用

@Controller
public class UserController {
    private Logger logger = LoggerFactory.getLogger(getClass());
    @GetMapping("/user")
    @ResponseBody
    public String invokeOrder(){
        logger.info("用户服务被调用!");
        // 创建发送http请求的 RestTemplate 对象
        RestTemplate restTemplate = new RestTemplate();
        String rest = restTemplate.getForObject("http://localhost:8889/order", String.class);
        logger.info("订单服务调用成功,返回结果"+rest);
        return " Invoke UsersService ok "+rest;
    }

}

@Controller
public class OrderController {
    private  Logger logger = LoggerFactory.getLogger(getClass());
    @GetMapping("/order")
    @ResponseBody
    public String OrderTest(){
        logger.info("订单服务被调用!");
        return " invoke  OrderService ok";
    }
}

问题:

1.以上的通信方式已经将访问的地址写成固定的值,无法实现负载的均衡

2.提供接口的服务发生改变,不利于服务的维护

解决问题:负载均衡

1.自定义负载均衡

//实现调用订单接口的随机策略 实现负载均衡
public String getHost(){
    ArrayList<String> hosts = new ArrayList<>();
    hosts.add("localhost:8889");
    hosts.add("localhost:9090");
    return hosts.get(new Random().nextInt(hosts.size()));
}

问题:

  • 1.无法实现服务的健康检查
  • 2.均衡的策略比较单一 (随机策略)

2.2、基于Ribbon的服务调用

  • 官方网址: https://github.com/Netflix/ribbon
  • Spring Cloud Ribbon是一个基于HTTP和TCP的客户端负载均衡工具,它基于Netflix Ribbon实现。通过Spring Cloud的封装,可以让我们轻松地将面向服务的REST模版请求自动转换成客户端负载均衡的服务调用。

引入Ribbon的依赖

<!--引入ribbon依赖-->
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>

编写application.yml

server:
  port: 8082
spring:
  application:
    name: USERSCLIENT  #服务名称
  cloud:
    consul:
      host: localhost  # 服务注册的地址
      discovery:
        service-name: USERSCLIENT  # 服务注册的名字
      port: 8500

改写用户服务和订单服务的控制层,并实现调用

@Controller
public class UsersController {
    @Autowired
    private DiscoveryClient discoveryClient; //直接注入
    @Autowired
    private LoadBalancerClient loadBalancerClient; //直接注入
    @Autowired
    private  RestTemplate restTemplate;  //配置后注入

    @GetMapping("/user")
    @ResponseBody
    public String invokeOrders(){
        RestTemplate restTemplate = new RestTemplate();
        String result = restTemplate.getForObject("http://localhost:8091/order", String.class);
        System.out.println(result);
        return "users service ok";
    }

    @GetMapping("/user2")
    @ResponseBody
    public String invokeOrders2(){

        List<ServiceInstance> ordersclient = discoveryClient.getInstances("ORDERSCLIENT");
        ServiceInstance serviceInstance = ordersclient.get(new Random().nextInt(ordersclient.size()));
        URI uri = serviceInstance.getUri();
        System.out.println("uri = " + uri);
        RestTemplate restTemplate = new RestTemplate();
        String result = restTemplate.getForObject(uri+"/order", String.class);
        System.out.println(result);
        return "users service ok";
    }

    @GetMapping("/user3")
    @ResponseBody
    public String invokeOrders3(){
        ServiceInstance ordersclient = loadBalancerClient.choose("ORDERSCLIENT");
        URI uri = ordersclient.getUri();
        System.out.println("uri = " + uri);
        return "users service ok";
    }

    @GetMapping("/user4")
    @ResponseBody
    public String invokeOrders4(){
        String result = restTemplate.getForObject("http://ORDERSCLIENT/order", String.class);
        return "users service ok";
    }
}

使用Ribbon注解实现负载均衡前需要使用配置类配置RestTemplate

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

Ribbon的负载均衡策略

1.ribbon负载均衡算法

  • RoundRobinRule 轮循策略 按顺序循环选择 Server

  • RandomRule 随机策略 随机选择 Server

  • AvailabilityFilteringRule 可用过滤策略

    `会先过滤由于多次访问故障而处于断路器跳闸状态的服务,还有并发的连接数量超过阈值的服务,然后对剩余的服务列表按照轮询策略进行访问

  • WeightedResponseTimeRule 响应时间加权策略

    根据平均响应的时间计算所有服务的权重,响应时间越快服务权重越大被选中的概率越高,刚启动时如果统计信息不足,则使用RoundRobinRule策略,等统计信息足够会切换到

  • RetryRule 重试策略

    先按照RoundRobinRule的策略获取服务,如果获取失败则在制定时间内进行重试,获取可用的服务。

  • BestAviableRule 最低并发策略

    会先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,然后选择一个并发量最小的服务

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yfY52EEv-1682171435733)(springcloud.assets/image-20200713162940968.png)]

设置负载均衡策略(服务调用端)

#设置负载均衡策略
ORDERSCLIENT:  # 服务的名称
  ribbon:
   NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule

2、OpenFeign组件的使用

思考: 使用RestTemplate+ribbon已经可以完成对端的调用,为什么还要使用feign?

String restTemplateForObject = restTemplate.getForObject("http://服务名/url?参数" + name, String.class);

存在问题:

  • 1.每次调用服务都需要写这些代码,存在大量的代码冗余
  • 2.服务地址如果修改,维护成本增高
  • 3.使用时不够灵活

官网:https://cloud.spring.io/spring-cloud-openfeign/reference/html/

Feign是一个声明式的伪Http客户端,它使得服务间的通信变得更简单。使用Feign,只需要创建一个接口并添加注解。同时可以完成数据的自动转换,它具有可插拔的注解特性(可以使用springmvc的注解),可使用Feign 注解和JAX-RS注解。Feign支持可插拔的编码器和解码器。Feign默认集成了Ribbon,默认实现了负载均衡的效果并且springcloud为feign添加了springmvc注解的支持

1.创建商品服务和商品类目服务(注册Consul注册中心)

@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients //OpenFeign注解
public class ProductsApplication {

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

@SpringBootApplication
@EnableDiscoveryClient
public class CategoryApplication {

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

2.添加OpenFeign依赖(消费者端)

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

3.添加启动类注解

@EnableFeignClients

4.在消费端编写OpenFeign客户端接口

@FeignClient("CATEGORY")
public interface CategoryClient {
    @GetMapping("/category") //请求方式 和请求的路径和服务提供者保持一致
    String test01();
}

5.消费者调用

@Controller
public class ProductsController {
    @Autowired
    private CategoryClient categoryClient; //注入接口
    @RequestMapping("/product")
    @ResponseBody
    public String testProduct(){
        String s = categoryClient.test01();//调用接口中的方法
        return "Products Ok ::"+s;
    }
}

服务间参数传递和响应处理

  • 1.参数的传递(零散)

    1.普通传参

    //客户端接口方法
    @GetMapping("/cat2")
    String test02(@RequestParam("id") Integer id,@RequestParam("name")String name);
    

    2.Restful传参

    //客户端接口方法
    @GetMapping("/cat2/{id}/{name}")
    String test02(@PathVariable("id") Integer id, @PathVariab le("name") String name);
    
  • 2.参数的传递(对象)

    //客户端接口方法
    @PostMapping("/p4")
    String test04(@RequestBody User user);
    
    // 服务的提供方 controller
    @PostMapping("/p4")
    @ResponseBody
    public String test04(@RequestBody User user){
        logger.info(user.toString());
        return  "Products ok";
    }
    
  • 3.参数的传递(数组)

//数组
@GetMapping("/p5")
String test05(@RequestParam("ids")String[] ids);

//服务的提供方
@GetMapping("/p5")
@ResponseBody
public String test05(String[] ids){
    for (String id : ids) {
        System.out.println(id);
    }
    return  "test05 ok";
}

服务间响应处理

@GetMapping("/cat6")
@ResponseBody //响应单个数据
public Product test05(Integer id){
    Product product = productsClient.test06(id);
    return product;
}

@GetMapping("/cat7")
@ResponseBody  //响应集合
public List<Product> test06(Integer id){
    return productsClient.test07(id);
}

服务调用超时处理(超出1秒调用超时)

在这里插入图片描述

修改超时时间

feign:
  client:
    config:
      PRODUCTS:
         connectTimeout: 5000   #连接超时时间
        readTimeout: 5000   #读取超时时间
        
        
 #全局超时时间控制
 feign:
  client:
    config:
     default:
         connectTimeout:: 5000   #连接超时时间
         readTimeout: 5000   #读取超时时间
 

3、Hystrix组件使用

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0cWDswwR-1682171435735)(springcloud.assets/image-20200715123359665.png)]

In a distributed environment, inevitably some of the many service dependencies will fail. Hystrix is a library that helps you control the interactions between these distributed services by adding latency tolerance and fault tolerance logic. Hystrix does this by isolating points of access between the services, stopping cascading failures across them, and providing fallback options, all of which improve your system’s overall resiliency. --[摘自官方]

官网:https://github.com/Netflix/Hystrix

  • 译: 在分布式环境中,许多服务依赖项不可避免地会失败。Hystrix是一个库,它通过添加延迟容忍和容错逻辑来帮助您控制这些分布式服务之间的交互。Hystrix通过隔离服务之间的访问点、停止它们之间的级联故障以及提供后备选项来实现这一点,所有这些都可以提高系统的整体弹性。
  • 通俗定义: Hystrix是一个用于处理分布式系统的延迟和容错的开源库,在分布式系统中,许多依赖不可避免的会调用失败,超时、异常等,Hystrix能够保证在一个依赖出问题的情况下,不会导致整体服务失败,避免级联故障(服务雪崩现象),提高分布式系统的弹性。

作用

  • hystrix 用来保护微服务系统 实现 服务降级 服务熔断

名词解析:

1.服务雪崩

在微服务之间进行服务调用是由于某一个服务故障,导致级联服务故障的现象,称为雪崩效应。雪崩效应描述的是提供方不可用,导致消费方不可用并将不可用逐渐放大的过程

在这里插入图片描述

如果此时,Service A的流量波动很大,流量经常会突然性增加!那么在这种情况下,就算Service A能扛得住请求,Service B和Service C未必能扛得住这突发的请求。此时,如果Service C因为抗不住请求,变得不可用。那么Service B的请求也会阻塞,慢慢耗尽Service B的线程资源,Service B就会变得不可用。紧接着,Service A也会不可用,这一过程如下图所示

在这里插入图片描述

2.服务熔断

“熔断器”本身是一种开关装置,当某个服务单元发生故障之后,通过断路器(hystrix)的故障监控,某个异常条件被触发,直接熔断整个服务。向调用方法返回一个符合预期的、可处理的备选响应(FallBack),而不是长时间的等待或者抛出调用方法无法处理的异常,就保证了服务调用方的线程不会被长时间占用,避免故障在分布式系统中蔓延,乃至雪崩。如果目标服务情况好转则恢复调用。服务熔断是解决服务雪崩的重要手段

在这里插入图片描述

3.服务降级

服务压力剧增的时候根据当前的业务情况及流量对一些服务和页面有策略的降级,以此缓解服务器的压力,以保证核心任务的进行。同时保证部分甚至大部分任务客户能得到正确的响应。也就是当前的请求处理不了了或者出错了,给一个默认的返回。

  • 服务降级: 关闭微服务系统中某些边缘服务 保证系统核心服务正常运行
  • 12 淘宝 京东
  • 删除订单 — 关闭订单 确认收货 ----> 服务繁忙,!!!

在这里插入图片描述

降级和熔断总结

1.共同点

  • 目的很一致,都是从可用性可靠性着想,为防止系统的整体缓慢甚至崩溃,采用的技术手段;
  • 最终表现类似,对于两者来说,最终让用户体验到的是某些功能暂时不可达或不可用;
  • 粒度一般都是服务级别,当然,业界也有不少更细粒度的做法,比如做到数据持久层(允许查询,不允许增删改);
  • 自治性要求很高,熔断模式一般都是服务基于策略的自动触发,降级虽说可人工干预,但在微服务架构下,完全靠人显然不可能,开关预置、配置中心都是必要手段;sentinel

2.异同点

  • 触发原因不太一样,服务熔断一般是某个服务(下游服务)故障引起,而服务降级一般是从整体负荷考虑;
  • 管理目标的层次不太一样,熔断其实是一个框架级的处理,每个微服务都需要(无层级之分),而降级一般需要对业务有层级之分(比如降级一般是从最外围服务边缘服务开始)

3.总结

  • 熔断必会触发降级,所以熔断也是降级一种,区别在于熔断是对调用链路的保护,而降级是对系统过载的一种保护处理

服务熔断的实现

1.创建一个单独的springboot工程,演示Hystrix

2.引入consul注册中心的相关依赖

3.引入Hystrix依赖

<!--引入hystrix-->
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>

4.编写启动类 添加注解

@SpringBootApplication
@EnableDiscoveryClient
@EnableCircuitBreaker //开启hystrix熔断服务
public class HysTrixApplication {
    public static void main(String[] args) {
        SpringApplication.run(HysTrixApplication.class, args);
    }
}

5.编写控制器 添加注解

@Controller
public class HystrixController {

    @RequestMapping("/h1")
    @ResponseBody
    @HystrixCommand(fallbackMethod = "Test01fallbackMethod")
    public String test01(Integer id){
        if(id<0){
            throw  new  RuntimeException("无效id!");
        }
        return "hystrix ok";
    }

    @ResponseBody
    public String Test01fallbackMethod(Integer id){
       return "商品过于火爆,服务被熔断,请稍后再试!"+id;
    }
}

5.总结

  • 从上面演示过程中会发现如果触发一定条件断路器会自动打开,过了一点时间正常之后又会关闭。那么断路器打开条件是什么呢?

6.断路器打开条件

1、 当满足一定的阀值的时候(默认10秒内超过20个请求失败)

2、 当失败率达到一定的时候(默认10秒内超过50%的请求失败)

3、 到达以上阀值,断路器将会开启

4、 当开启的时候,所有请求都不会进行转发

5、 一段时间之后(默认是5秒),这个时候断路器是半开状态,会让其中一个请求进行转发。如果成功,断路器会关闭,若失败,继续开启。重复4和5。

在这里插入图片描述

默认的服务FallBack处理方法

  • 如果为每一个服务方法开发一个降级,对于我们来说,可能会出现大量的代码的冗余,不利于维护,这个时候就需要加入默认服务降级处理方法

服务降级的实现

服务降级: 站在系统整体负荷角度 实现: 关闭系统中某些边缘服务 保证系统核心服务运行
Emps 核心服务 Depts 边缘服务

1.客户端openfeign + hystrix实现服务降级实现

  • 引入hystrix依赖
  • 配置文件开启feign支持hystrix
  • 在feign客户端调用加入fallback指定降级处理
  • 开发降级处理方法

2.开启openfeign支持服务降级

feign.hystrix.enabled=true #开启openfeign支持降级

3.在openfeign客户端中加如Hystrix

@FeignClient(value = "HYSTRIXCLIENT",fallback = HysClientFallback.class)
public interface HysClient {
    @GetMapping("/h2")
    String test02(@RequestParam Integer id);
}

4.开发fallback处理类

@Component
public class HysClientFallback implements HysClient{
    @Override
    public String test02(Integer id) {
        return "服务器繁忙,请稍后再试!"+id;
    }
}

  码文不易,本篇文章就介绍到这里,如果想要学习更多Java系列知识点击关注博主,博主带你零基础学习Java知识。与此同时,对于日常生活有困扰的朋友,欢迎阅读我的第四栏目:《国学周更—心性养成之路》,学习技术的同时,我们也注重了心性的养成。

在这里插入图片描述

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

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

相关文章

【UE 粒子系统】电火花粒子效果

效果 步骤 1. 新建一个粒子系统&#xff0c;命名为“SparkParticles” 再新建一个材质&#xff0c;命名为“SparkParticleMaterial” 2. 打开“SparkParticleMaterial”&#xff0c;将混合模式改为半透明&#xff0c;着色模型为无光照 然后添加如下节点 3. 打开“SparkParticl…

输入输出练习

文章目录 1. AB(1)2. AB(2)3. AB(3)4. AB(4)计算一系列数的和5. AB(5) 计算一系列数的和6. AB(6)7. AB(7)8. 字符串排序(1)9. 字符串排序(2)10 字符串排序(2)11. 注意数据范围 1. AB(1) import java.util.Scanner;// 注意类名必须为 Main, 不要有任何 package xxx 信息 public …

差分运算放大电路原理解析

差分运算放大电路&#xff0c;对共模信号得到有效抑制&#xff0c;而只对差分信号进行放大&#xff0c;因而得到广泛的用。 注&#xff1a; &#xff08;1&#xff09;共模信号   共模信号&#xff08;common mode signal&#xff09;是指同时作用于多个电路或电子设备上的信…

1.10和1.11和1.12、Makefile

1.10和1.11和1.12、Makefile 1.10、Makefile(1)1.10.1、什么是Makefile1.10.2、Makefile的文件命名和规则实际操作 1.11、Makefile(2)1. 工作原理&#xff08;1.10.3&#xff09;实际操作 1.12、Makefile(3)1. 变量2. 模式匹配3. 函数实际操作①实现变量和模式匹配②实现函数操…

Vue(简介、前期配置、Vue展示、模板语法)

一、简介 1. 什么是Vue&#xff1f; 2. Vue特点 采用组件化模式&#xff0c;提高代码复用率、且让代码更好维护 组件化&#xff1a;每一部分直接就是大盒子组件&#xff08;创建一个单独的Vue文件&#xff09;&#xff0c;直接可以修改单独封装的组件部分代码 Vue使用声明式…

为什么需要内网穿透技术?

随着互联网技术的快速发展&#xff0c;企业和个人越来越依赖于网络资源&#xff0c;而内网穿透技术正是解决远程访问内网资源的关键。本文将详细介绍内网穿透的概念及其重要性&#xff0c;以帮助您了解为什么我们需要使用内网穿透技术。 目录 一、内网穿透技术简介 二、为什…

Java中List排序的3种方法

在某些特殊的场景下&#xff0c;我们需要在 Java 程序中对 List 集合进行排序操作。比如从第三方接口中获取所有用户的列表&#xff0c;但列表默认是以用户编号从小到大进行排序的&#xff0c;而我们的系统需要按照用户的年龄从大到小进行排序&#xff0c;这个时候&#xff0c;…

2 变量运算符-基本数据类型讲解【Go语言教程】

2 变量运算符-基本数据类型讲解【Go语言教程】 2.1 变量 2.1.1 声明变量方式 指定变量类型&#xff0c;声明后若不赋值&#xff0c;使用默认值 类型推导 通过: 多变量声明 全局变量定义 在函数外部定义的就是全局变量 变量变量名值数据类型 注意&#xff1a;如果go程序报错&…

UE4/5多人游戏详解(七、自定义委托,实现寻找会话和加入会话的函数,通过Steam进行两台电脑的联机)

目录 可能出现问题&#xff08;在六部分的测试可能无法连接的问题【在末尾加上了&#xff0c;怕有人没看见在这里写一下】&#xff09; 自定义委托 调整位置 创建更多的委托和回调函数给菜单&#xff1a; 多播和动态多播 代码&#xff1a; 委托变量 代码&#xff1a; 回…

( “树” 之 BST) 109. 有序链表转换二叉搜索树 ——【Leetcode每日一题】

二叉查找树&#xff08;BST&#xff09;&#xff1a;根节点大于等于左子树所有节点&#xff0c;小于等于右子树所有节点。 二叉查找树中序遍历有序。 109. 有序链表转换二叉搜索树 给定一个单链表的头节点 head &#xff0c;其中的元素 按升序排序 &#xff0c;将其转换为高度…

Linux: 进程间通信机制

文章目录 1. 前言2. 进程间通信机制2.1 管道2.1.1 匿名管道2.1.2 popen() 和 pclose()2.1.3 命名管道 FIFO 2.2 消息队列2.3 共享内存2.4 信号量2.5 网络套接字2.6 UNIX套接字2.7 信号 3. 参考资料 1. 前言 限于作者能力水平&#xff0c;本文可能存在谬误&#xff0c;因此而给…

基于格密码的LWE问题

LWE LWE问题&#xff0c; Learning With Errors&#xff0c;带有安全性证明的第一个版本是由Oded Regev 在2005年提出&#xff0c;Kawachi等给出了效率的改进&#xff0c;接着一些效率方面非常重要的改进由Peikert等提出。 格理论知识 格密码学&#xff08;Lattice-based Cr…

PTA L1-093 猜帽子游戏 (15 分)

宝宝们在一起玩一个猜帽子游戏。每人头上被扣了一顶帽子&#xff0c;有的是黑色的&#xff0c;有的是黄色的。每个人可以看到别人头上的帽子&#xff0c;但是看不到自己的。游戏开始后&#xff0c;每个人可以猜自己头上的帽子是什么颜色&#xff0c;或者可以弃权不猜。如果没有…

机器学习算法 决策树

文章目录 一、决策树的原理二、决策树的构建2.1 ID3算法构建决策树2.2 C4.5 算法树的构建2.3 CART 树的创建 三、决策树的优缺点 一、决策树的原理 决策树&#xff08;Decision Tree&#xff09;是一种非参数的有监督学习方法&#xff0c;它能够从一系列有特征和标签的数据中总…

NDK OpenCV人脸定位

NDK系列之OpenCV人脸定位技术实战&#xff0c;本节主要是通过OpenCV C库&#xff0c;实现识别人脸定位&#xff0c;并对识别到的人脸画面增加红框显示。 实现效果&#xff1a; 实现逻辑&#xff1a; 1.初始化CameraX&#xff0c;绑定图片分析器ImageAnalysis&#xff0c;监听…

7.队列算法

算法&#xff1a;队列算法 队列是一种抽象的数据结构&#xff0c;有点类似于Stacks。与堆栈不同&#xff0c;队列的两端都是开放的。一端始终用于插入数据(入队)&#xff0c;另一端用于删除数据(出队)。队列遵循先进先出方法&#xff0c;即首先访问先存储的数据项。 一个真实的…

【C++初阶】类与对象(上)

一.什么是类&#xff0c;什么是对象 我们可以形象的把类比作是一个房子的设计图纸&#xff0c;而对象就是根据设计图纸设计出来的房子。 由设计图纸到房子的过程&#xff0c;我们称之为类的实例化。 C兼容C的&#xff0c;所以C中的结构体在C中也能用&#xff0c;但是C把结构体升…

rust教程 第一章 —— 初识rust

文章目录 前言一、Rust简介二、安装Rust编译器三、第一个Rust程序四、 IDE环境五、初识包管理六、总结 前言 本系列教程目录可查看这里&#xff1a;Rust教程目录 近些年来不断有新的语言崛起&#xff0c;比如当下非常火的go语言&#xff0c;不过相比于C&#xff0c;go语言确实…

C++类和对象 (3)

类和对象 1. 类的6个默认成员函数2. 构造函数2.1. 概念&#xff08;问题提出&#xff09;2.2. 特性 3.析构函数3.1. 概念3.2.特性 1. 类的6个默认成员函数 如果一个类中什么成员都没有&#xff0c;简称为空类。 空类中真的什么都没有吗&#xff1f;并不是&#xff0c;任何类在…

使用OpenFeign实现接口访问

1. 引言 在微服务横行的年代&#xff0c;后端根据业务的不一样分成了很多单独运行的服务&#xff0c;比如在物联网中&#xff0c;根据业务拆分为定时服务、设备控制等服务。当前端想控制设备时&#xff0c;其请求首先到其对应的后端服务&#xff0c;后端服务再调用设备控制服务…