【Java学习日志】2.Spring框架

Spring管理项目中的类,方法等

Spring 的核心技术 ioc ,aop。能实现模块之间,类之间的解耦合。 举例来说,classA依赖classB,spring被用来解决A类和B类之间的关系
Spring boot,2017年出现的框架
Spring的jar包通常比较小,占用资源少,运行效率高,不依赖其他jar,可以继承其他优秀框架
spring容器可以管理java对象

spring的核心功能IoC控制反转

控制反转,inversion of control

​ 是一个理论:把对象的创建,赋值,管理工作都交给代码之外的容器实现,也就是对象的创建是由其他外部资源完成的
​ 控制:创建对象,对象的属性赋值,对象之间的关系管理 //容器的作用
​ 反转:(正转是指开发人员自己new出对象)把new这个权限转移给容器来做
​ 为什么使用ioc:目的是减少对代码的改动,也能实现不同的功能,实现解耦合
java中创建对象有哪些方式:构造方法(new);反射;序列化(磁盘文件中);克隆;ioc(容器创建文件);动态代理
​ ioc的体现:servlet:servlet是由Tomcat服务器作为容器存放的,然后再实现继承。
​ ioc的技术实现:di依赖注入dependency injection,只需要在程序中提供要使用的对象名称就可以,至于对象如何在容器中创建,赋值,查找都由容器内部来实现
​ spring使用了di实现了ioc的功能,spring底层创建对象,使用的是反射机制。

在resources下建立beans.xml

在其中:
告诉spring创建对象,声明beans,就是告诉spring要创建某个类的对象
id:对象的自定义名称,唯一值。 spring通过这个名称找到对象
class:类的全限定名称(不能是接口,因为spring通过反射来创建对象,必须使用类)
spring就完成了 SomeService someService = new SomeServiceImpl();
spring就是把创建好的对象放入map中,spring框架中会有一个map存放对象 //springMap.put(id的值,对象)
一个bean标签声明一个java对象

如何使用spring容器创建的对象?

在测试class中编写Test文件,其中:

​ 1.指定spring配置文件的名称 //String config = “beans.xml"
​ 2.创建表示spring容器的对象,ApplicationContext
​ //ApplicationContext(是一个接口)就是表示spring的容器,通过容器这个对象获取对象了
​ 使用:ApplicationContext ac = new ClassPathXmlApplicationContext(config);//config表示文件路径
​ // ClassPathXmlApplicationContext(config)表示从类路径中加载spring的配置文件
​ SomeService service = (SomeService) ac.getBean();
​ //从容器中获取某个对象,你要调用对象的方法
​ service.dosome();
​ //使用spring创建好的方法

junit:单元测试,一个工具类库,做测试方法使用的。

​ 单元:指定的是方法,一个类中有很多方法,一个方法称作一个单元。
​ 使用单元测试: 1.需要添加junit依赖
​ 2.创建测试作用的类:叫做测试类 src/test/java目录中创建类
​ 3.创建测试方法(public方法,没有返回值,方法名称写成test+目标测试方法,方法没有参数,方法上面加上@Test,这样的方法是可以单独执行的,不用使用main方法)

di依赖注入

​ 有类就可以使用spring创建对象:在beans中设置id和class,然后从spring中拿去beans中的类做对象
​ spring创建对象:默认调用的是无参数构造方法
​ 赋值:di依赖注入,两种方式,一种是:在spring的配置文件中,使用标签和属性完成,叫做基于XML的di实现 另一种是:使用Spring中的注解,完成属性赋值,叫做基于注解di实现
di语法的分类
​ set注入(设值注入):spring调用类的set方法,在set方法可以实现属性的赋值,用得很多,在主类中需要存在set方法,用来使后续的set注入可以实现
​ 构造注入,spring调用类的有参构造方法,创建对象。在构造方法中完成赋值
简单类型(java基本类型和字符串)的set注入(设值注入):在applicationContext中的beans标签下输入:

<bean id = "xx" class = "yyy">
			<property name = "属性名字" value = "此属性的值"/>		
    		//一个property只能给给一个属性赋值
			<property ....>
</bean>

​ 在执行文件中,spring会先调用类的无参数构造方法创建对象,然后再用对象的set或者get方法来实现
​ 而且在set方法中只会考虑对应属性的set方法是否存在,一旦set方法存在,哪怕属性本身没有生命,也会执行set设值注入

	引用类型的set注入:
	<bean id = "xx" class = "yyy">
		<property name = "属性名字" ref = "bean的id(对象的名称)"/>		
        //一个property只能给给一个属性赋值
		<property ....>
	</bean>
	//相当于引用   已经用set设值注入的对象  到另外一个新对象的属性赋值中

spring boot的简易方法

@configuration 加上@beans可以替代原本需要在xml文件中声明的bean容器和spring容器
@configuration 加上@ImportResouce可以引入resource文件夹中原本写好的xml文件和 bean文件来引入到当前文件中
@PropertyResource 读取Properties属性配置文件,可以实现外部化配置,在程序代码 之外提供数据
步骤: 1.在resources目录下,创建properties文件,使用k=v的格式提供数据 //tiger.age = 3
2.在PropertyResource中指定properties文件夹位置 //在对象类中,@component(“tiger) @value(“ t i g e r . a g e " ∗ ∗ ∗ ∗ 3. 使用 @ v a l u e (“ {tiger.age}"** **3.使用@value(“ tiger.age"3.使用@value{ }”

Spring boot 中使用容器

通过代码从容器中获取对象

SpringApplication.run(Application.class.args); 返回值获取容器

就是在接口中使用注释@Service,然后在主程序中手工创建和接收容器对象

`//获取容器对象`
`ConfigurableApplicationContext ctx=SpringApplication.run(Application)`
`//从容器者获取对象`
`UserService userService =(UserService)ctx.getBean(s:"userService");`
`userService.sayHello(name:"李四");`
两个接口:CommandLineRunner 和 ApplicationRunner

在容器创建好对象后,自动执行run方法

整个过程中相当于Springboot自动帮你调用了原本卸载xml文件中的和spring容器,也就是在主程序中,在SpringApplication.run(Application.class,args);之前自动创建了Spring容器,然后在SpringApplication.run(Application.class,args);这个语句中就可以执行容器对象提取

tips:使用@Resource可以直接标注已在类中声明的对象,就会被直接引入到容器中去

spring boot 和 web组件

拦截器,servlet,filter

拦截器

拦截器是SpringMVC中的一种对象,能拦截对Controller的请求

拦截器实现对请求的预先处理,可以是系统的,也可以是自定义的

自定义拦截器:创建类实现SpringMVCk框架的HandlerInterceptor接口,HandlerInterceptor接口三种方法

public interface HandlerInterceptor {
    default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        return true;
    }

    default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
    }

    default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
    }
}

crtl+i 快速实现重写

public class controller implements WebMvcConfigurer

**WebMvcConfigurer **继承了SpringMVC,他的方法就是原来的.xml文件

注:原本SpringMVC的流程

image-20211226000022362

重写servlet方法

ctrl+O 重写继承的父类方法

过滤器的使用

Filter是servlet中的过滤器,可以处理请求,对请求的参数,属性进行调整,常常在过滤器中处理字符编码。在框架中使用过滤器:

1.创建过滤器类

2.注册Filter过滤器对象

@Mapper注解

放在dao接口上方,每个接口都需要注释,其目的是告诉MyBatis这是dao接口,需要为他创建此接口的代理对象,位置就放在类的上方

如果不想每个接口都标明@Mapper,就使用@MapperScan在主启动类中表明对应接口所在包的位置@MapperScan(basePackages = "com.yoann.dao")

如果要把mapper和接口的两个文件.java和.xml分开,需要在properties文件下编辑指出mapper的位置 mybatis.mapper-locations = classpath:mapper/*.xml //任意xml文件//拓展即是把原来写在MyBatis文件中的相关配置,现在放在了properties文件中进行配置

事务控制:
Spring框架中的事务:

1.管理事务的对象:事务管理器(接口,接口有很多实现类) //例如使用JDBC或者mybatis访问数据库,使用的事务管理器:DataSourceTransactionManager

2.声明式事务:在xml配置文件或者使用注解说明事务控制的内容 //控制事务的隔离级别,传播行为,超时时间

3.事务的处理方式:Spring中的@Transactional 或者 aspectj框架可以在xml配置文件中,声明事务控制的内容

SpringBoot原理分析:

在做SprinBoot和mybatis-plus组合项目时,对于Mapper接口文件(EmployeeMapper),只需要让其继承BaseMapper<目标实体>,而使用Service接口文件(EmployeeService),需要继承mybatis-plus中的IService<目标实体,比如employee>,而对应的**ServiceImpl类(比如employeeServiceImpl)**需要继承ServiceImpl<对应Mapper,目标实体>并实现Service接口,目标实体(比如employee)需要实现Serializable(IO类中方法)

使用Category封装实体,大致格式是 public R<List<Category>> list (Category category){}

java微服务(Spring Cloud)

img

img

为了实现服务之间的异步通讯,需要学些MQ-RabbitMQ(RabbitMQ:消息队列)。

由于服务越来越多,每个服务的访问地址多是一样的。
协议://地址:端口号。由于模块繁多,并且模块搭建的集群数量增加,会导致其他模块需要维护各种ip地址等信息,导致项目的维护性急需要使用一个技术来解决当前问题:
Eureka:注册中心帮助我们管理服务信息。Erueka实现通讯地址维护。
Robbin:可以帮我们实现服务之间的负载均衡
在上述的架构中,如果说订单模块出现了问题。只要是涉及到订单模块的功能,全部都无法使用。可能会导致服务器提供的线程池耗尽。为了解决上述的问题,使用Hystrix处理。
Hystrix:提供了线程池隔离的方式,避免服务器线程池耗尽在一个服务无法使用时,可以提供断路器的方式来解决。使用Hystrix帮我们实现断路器和隔壁,并最终服务降级
Eureka,Robbin,Hystrix都是SpringCloud中的组件

虽然已经将每个模块独立的做开发,比如商品模块,压力最大的时商品的查询。
在单独模块中再次拆分项目的方式就可以称之为微服务架构

微服务技术栈有那些?

微服务技术条目 落地技术
服务开发 SpringBoot、Spring、SpringMVC等
服务配置与管理 Netfix公司的Archaius、阿里的Diamond等
服务注册与发现 Eureka、Consul、Zookeeper等
服务调用 Rest、PRC、gRPC
服务熔断器 Hystrix、Envoy等
负载均衡 Ribbon、Nginx等
服务接口调用(客户端调用服务的简化工具) Fegin等
消息队列 Kafka、RabbitMQ、ActiveMQ等
服务配置中心管理 SpringCloudConfig、Chef等
服务路由(API网关) Zuul等
服务监控 Zabbix、Nagios、Metrics、Specatator等
全链路追踪 Zipkin、Brave、Dapper等
数据流操作开发包 SpringCloud Stream(封装与Redis,Rabbit,Kafka等发送接收消息)
时间消息总栈 SpringCloud Bus
服务部署 Docker、OpenStack、Kubernetes等

核心观念是解耦,让每一个服务提供单个业务功能的服务,独立处理问题,并且能够自行启动或销毁,并尽量让每个服务有独立的数据库。

SpringCloud能干嘛?

Distributed/versioned configuration 分布式/版本控制配置
Service registration and discovery 服务注册与发现
Routing 路由
Service-to-service calls 服务到服务的调用
Load balancing 负载均衡配置
Circuit Breakers 断路器
Distributed messaging 分布式消息管理
相对于Dubbo(分布式+服务治理)来说,社区活跃度更高,rest风格使用起来更加灵活,适合快速演化的微服务环境。

Eureka基本的架构

Springcloud 封装了Netflix公司开发的Eureka模块来实现服务注册与发现 (对比Zookeeper).

Eureka采用了C-S的架构设计,EurekaServer作为服务注册功能的服务器,他是服务注册中心.

而系统中的其他微服务,使用Eureka的客户端连接到EurekaServer并维持心跳连接。这样系统的维护人员就可以通过EurekaServer来监控系统中各个微服务是否正常运行,Springcloud 的一些其他模块 (比如Zuul) 就可以通过EurekaServer来发现系统中的其他微服务,并执行相关的逻辑.

img

两个组件

Eureka 包含两个组件:Eureka Server 和 Eureka Client.

Eureka Server 提供服务注册,各个节点启动后,回在EurekaServer中进行注册,这样Eureka Server中的服务注册表中将会储存所有课用服务节点的信息,服务节点的信息可以在界面中直观的看到.

Eureka Client 是一个Java客户端,用于简化EurekaServer的交互,客户端同时也具备一个内置的,使用轮询负载算法的负载均衡器。在应用启动后,将会向EurekaServer发送心跳 (默认周期为30秒) 。如果Eureka Server在多个心跳周期内没有接收到某个节点的心跳,EurekaServer将会从服务注册表中把这个服务节点移除掉 (默认周期为90s).

三大角色

Eureka Server:提供服务的注册与发现

Service Provider:服务生产方,将自身服务注册到Eureka中,从而使服务消费方能狗找到

Service Consumer:服务消费方,从Eureka中获取注册服务列表,从而找到消费服务

设计模式+微服务拆分思想

tips:使用IDEA连接oracle或者mysql时,oracle系统用户名为sys as SYSDBA,密码oracle,mysql直接连接root,密码zhaoyan就可以了

TipS:在使用SpringCloud时,因为已经集成了SpringBoot的一些功能,所以在使用时我们按照以下的步骤就可以完成相关微服务的部署了。

1.导入依赖
2。编写配置文件
3.开启这个功能,比如@EnableEurekaSerber   
4.然后配置主启动类就可以了。
Eureka部署
  1. springcloud-eureka-7001 模块建立
  2. pom.xml 配置
<!--导包~-->
<dependencies>
    <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-eureka-server -->
    <!--导入Eureka Server依赖-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-eureka-server</artifactId>
        <version>1.4.6.RELEASE</version>
    </dependency>
    <!--热部署工具-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
    </dependency>
</dependencies>

application.yml

server:
  port: 7001

# Eureka配置
eureka:
  instance:
    # Eureka服务端的实例名字
    hostname: 127.0.0.1
  client:
    # 表示是否向 Eureka 注册中心注册自己(这个模块本身是服务器,所以不需要)
    register-with-eureka: false
    # fetch-registry如果为false,则表示自己为注册中心,客户端的化为 ture
    fetch-registry: false
    # Eureka监控页面~
    service-url:
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/

源码中Eureka的默认端口以及访问路径:

img

主启动类:

/**yoann
 * @Auther: yoann
 * @Date: 2020/05/17
 * @Description: 启动之后,访问 http://127.0.0.1:7001/
 */
@SpringBootApplication
// @EnableEurekaServer 服务端的启动类,可以接受别人注册进来~
@EnableEurekaServer
public class EurekaServer_7001 {
    public static void main(String[] args) {
        SpringApplication.run(EurekaServer_7001.class,args);
    }
}

启动成功后访问 http://localhost:7001/得到以下页面:

img

Eureka客户端部署:

1.导入Eureca依赖:

<!--Eureka依赖-->
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-eureka -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-eureka</artifactId>
    <version>1.4.6.RELEASE</version>
</dependency>

2.application中新增Eureca配置:

# Eureka配置:配置服务注册中心地址
eureka:
  client:
    service-url:
      defaultZone: http://localhost:7001/eureka/

3.为主启动类添加@EnableEurekaClient注解:

/**
 * @Auther: yoann
 * @Date: 2020/05/17
 * @Description: 启动类
 */
@SpringBootApplication
// @EnableEurekaClient 开启Eureka客户端注解,在服务启动后自动向注册中心注册服务
@EnableEurekaClient
public class DeptProvider_8001 {
    public static void main(String[] args) {
        SpringApplication.run(DeptProvider_8001.class,args);
    }
}

4.先启动7001服务端后启动8001客户端进行测试,然后访问监控页http://localhost:7001/ 产看结果如图,成功:img

5.修改Eureka上的默认描述信息:

# Eureka配置:配置服务注册中心地址
eureka:
  client:
    service-url:
      defaultZone: http://localhost:7001/eureka/
  instance:
    instance-id: springcloud-provider-dept-8001 #修改Eureka上的默认描述信息

结果如图:

img

如果此时停掉springcloud-provider-dept-8001 等30s后 监控会开启保护机制:img

6.配置关于服务加载的监控信息:img

pom.xml中添加依赖

<!--actuator完善监控信息-->
<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

application.yml中添加配置

# info配置
info:
# 项目的名称
app.name: haust-springcloud
# 公司的名称
company.name: 北航 

此时刷新监控页,点击进入

img

跳转新页面显示如下内容:

img

EureKa自我保护机制:好死不如赖活着

一句话总结就是:某时刻某一个微服务不可用,eureka不会立即清理,依旧会对该微服务的信息进行保存

默认情况下,当eureka server在一定时间内没有收到实例的心跳,便会把该实例从注册表中删除(默认是90秒),但是,如果短时间内丢失大量的实例心跳,便会触发eureka server的自我保护机制,比如在开发测试时,需要频繁地重启微服务实例,但是我们很少会把eureka server一起重启(因为在开发过程中不会修改eureka注册中心),当一分钟内收到的心跳数大量减少时,会触发该保护机制。可以在eureka管理界面看到Renews threshold和Renews(last min),当后者(最后一分钟收到的心跳数)小于前者(心跳阈值)的时候,触发保护机制,会出现红色的警告:EMERGENCY!EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ARE UP WHEN THEY'RE NOT.RENEWALS ARE LESSER THAN THRESHOLD AND HENCE THE INSTANCES ARE NOT BEGING EXPIRED JUST TO BE SAFE.从警告中可以看到,eureka认为虽然收不到实例的心跳,但它认为实例还是健康的,eureka会保护这些实例,不会把它们从注册表中删掉。

该保护机制的目的是避免网络连接故障,在发生网络故障时,微服务和注册中心之间无法正常通信,但服务本身是健康的,不应该注销该服务,如果eureka因网络故障而把微服务误删了,那即使网络恢复了,该微服务也不会重新注册到eureka server了,因为只有在微服务启动的时候才会发起注册请求,后面只会发送心跳和服务列表请求,这样的话,该实例虽然是运行着,但永远不会被其它服务所感知。所以,eureka server在短时间内丢失过多的客户端心跳时,会进入自我保护模式,该模式下,eureka会保护注册表中的信息,不在注销任何微服务,当网络故障恢复后,eureka会自动退出保护模式。自我保护模式可以让集群更加健壮。

但是我们在开发测试阶段,需要频繁地重启发布,如果触发了保护机制,则旧的服务实例没有被删除,这时请求有可能跑到旧的实例中,而该实例已经关闭了,这就导致请求错误,影响开发测试。所以,在开发测试阶段,我们可以把自我保护模式关闭,只需在eureka server配置文件中加上如下配置即可:eureka.server.enable-self-preservation=false【不推荐关闭自我保护机制】

详细内容可以参考下这篇博客内容:https://blog.csdn.net/wudiyong22/article/details/80827594

Euraka和Zookeeper区别

RDBMS (MySQL\Oracle\sqlServer) ===> ACID

NoSQL (Redis\MongoDB) ===> CAP

  • C (Consistency) 强一致性
  • A (Availability) 可用性
  • P (Partition tolerance) 分区容错性
CAP理论的核心

一个分布式系统不可能同时很好的满足一致性,可用性和分区容错性这三个需求
根据CAP原理,将NoSQL数据库分成了满足CA原则,满足CP原则和满足AP原则三大类
CA:单点集群,满足一致性,可用性的系统,通常可扩展性较差
CP:满足一致性,分区容错的系统,通常性能不是特别高
AP:满足可用性,分区容错的系统,通常可能对一致性要求低一些

著名的CAP理论指出,一个分布式系统不可能同时满足C (一致性) 、A (可用性) 、P (容错性),由于分区容错性P再分布式系统中是必须要保证的,因此我们只能再A和C之间进行权衡。

Zookeeper 保证的是 CP —> 满足一致性,分区容错的系统,通常性能不是特别高
Eureka 保证的是 AP —> 满足可用性,分区容错的系统,通常可能对一致性要求低一些

Zookeeper保证的是CP

当向注册中心查询服务列表时,我们可以容忍注册中心返回的是几分钟以前的注册信息,但不能接收服务直接down掉不可用。也就是说,服务注册功能对可用性的要求要高于一致性。但zookeeper会出现这样一种情况,当master节点因为网络故障与其他节点失去联系时,剩余节点会重新进行leader选举。问题在于,选举leader的时间太长,30-120s,且选举期间整个zookeeper集群是不可用的,这就导致在选举期间注册服务瘫痪。在云部署的环境下,因为网络问题使得zookeeper集群失去master节点是较大概率发生的事件,虽然服务最终能够恢复,但是,漫长的选举时间导致注册长期不可用,是不可容忍的。

Eureka保证的是AP

Eureka看明白了这一点,因此在设计时就优先保证可用性。Eureka各个节点都是平等的,几个节点挂掉不会影响正常节点的工作,剩余的节点依然可以提供注册和查询服务。而Eureka的客户端在向某个Eureka注册时,如果发现连接失败,则会自动切换至其他节点,只要有一台Eureka还在,就能保住注册服务的可用性,只不过查到的信息可能不是最新的,除此之外,Eureka还有之中自我保护机制,如果在15分钟内超过85%的节点都没有正常的心跳,那么Eureka就认为客户端与注册中心出现了网络故障,此时会出现以下几种情况:

1.Eureka不在从注册列表中移除因为长时间没收到心跳而应该过期的服务
2.Eureka仍然能够接受新服务的注册和查询请求,但是不会被同步到其他节点上 (即保证当前节点依然可用)
3.当网络稳定时,当前实例新的注册信息会被同步到其他节点中
因此,Eureka可以很好的应对因网络故障导致部分节点失去联系的情况,而不会像zookeeper那样使整个注册服务瘫痪

Ribbon(负载均衡)

客户端负载均衡服务

部署ribbon

1.springcloud-consumer-dept-80向pom.xml中添加Ribbon和Eureka依赖

<!--Ribbon-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-ribbon</artifactId>
    <version>1.4.6.RELEASE</version>
</dependency>
<!--Eureka: Ribbon需要从Eureka服务中心获取要拿什么-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-eureka</artifactId>
    <version>1.4.6.RELEASE</version>
</dependency>

在application.yml文件中配置Eureka

# Eureka配置
eureka:
  client:
    register-with-eureka: false # 不向 Eureka注册自己
    service-url: # 从三个注册中心中随机取一个去访问
      defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/

主启动类加上@EnableEurekaClient注解,开启Eureka

//Ribbon 和 Eureka 整合以后,客户端可以直接调用,不用关心IP地址和端口号
@SpringBootApplication
@EnableEurekaClient //开启Eureka 客户端
public class DeptConsumer_80 {
    public static void main(String[] args) {
        SpringApplication.run(DeptConsumer_80.class, args);
    }
}

自定义Spring配置类:ConfigBean.java 配置负载均衡实现RestTemplate:

@Configuration
public class ConfigBean {//@Configuration -- spring  applicationContext.xml

    @LoadBalanced //配置负载均衡实现RestTemplate
    @Bean
    public RestTemplate getRestTemplate() {
        return new RestTemplate();
    }
}

修改conroller:DeptConsumerController.java

//Ribbon:我们这里的地址,应该是一个变量,通过服务名来访问
//private static final String REST_URL_PREFIX = "http://localhost:8001";
private static final String REST_URL_PREFIX = "http://SPRINGCLOUD-PROVIDER-DEPT";

Tips:这样部署完之后可以直接通过服务端的名字来直接执行对应的服务

流程图:

在这里插入图片描述

Feign 负载均衡

Feign是声明式Web Service客户端,它让微服务之间的调用变得更简单,类似controller调用service。SpringCloud集成了Ribbon和Eureka,可以使用Feigin提供负载均衡的http客户端。他主要是面向接口和注解的编程方式。

FeignFeign默认集成了Ribbon,他旨在使编写Java Http客户端变得更容易
前面在使用Ribbon + RestTemplate时,利用RestTemplate对Http请求的封装处理,形成了一套模板化的调用方法。但是在实际开发中,由于对服务依赖的调用可能不止一处,往往一个接口会被多处调用,所以通常都会针对每个微服务自行封装一个客户端类来包装这些依赖服务的调用。所以,Feign在此基础上做了进一步的封装,由他来帮助我们定义和实现依赖服务接口的定义,在Feign的实现下,我们只需要创建一个接口并使用注解的方式来配置它 (类似以前Dao接口上标注Mapper注解,现在是一个微服务接口上面标注一个Feign注解),即可完成对服务提供方的接口绑定,简化了使用Spring Cloud Ribbon 时,自动封装服务调用客户端的开发量。

在SpringCloud中的配置过程

拷贝原来的Ribbon负载均衡的拷贝springcloud-consumer-dept-80模块下的pom.xml,resource,以及java代码到springcloud-consumer-feign模块,并添加feign依赖。

<!--Feign的依赖-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-feign</artifactId>
    <version>1.4.6.RELEASE</version>
</dependency>

改造controller对应的DeptConsumerController.java文件

@RestController
public class DeptConsumerController {

    @Autowired
    private DeptClientService deptClientService;

    /**
     * 消费方添加部门信息
     * @param dept
     * @return
     */
    @RequestMapping("/consumer/dept/add")
    public boolean add(Dept dept) {
        return deptClientService.addDept(dept);
    }

    /**
     * 消费方根据id查询部门信息
     * @param id
     * @return
     */
    @RequestMapping("/consumer/dept/get/{id}")
    public Dept get(@PathVariable("id") Long id) {
       return deptClientService.queryById(id);
    }

    /**
     * 消费方查询部门信息列表
     * @return
     */
    @RequestMapping("/consumer/dept/list")
    public List<Dept> list() {
        return deptClientService.queryAll();
    }
}

之后改造feign(feign也是包含ribbon的)的主启动类

@SpringBootApplication
@EnableEurekaClient
// feign客户端注解,并指定要扫描的包以及配置接口DeptClientService
@EnableFeignClients(basePackages = {"com.haust.springcloud"})
// 切记不要加这个注解,不然会出现404访问不到,扫描包文件
//@ComponentScan("com.haust.springcloud")
public class FeignDeptConsumer_80 {
    public static void main(String[] args) {
        SpringApplication.run(FeignDeptConsumer_80.class, args);
    }
}

改造springcloud-api模块

pom.xml添加feign依赖

<!--Feign的依赖-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-feign</artifactId>
    <version>1.4.6.RELEASE</version>
</dependency>

新建service包,并新建DeptClientService的接口(就像原来service使用controller包中的方法一样)

// @FeignClient:微服务客户端注解,value:指定微服务的名字,这样就可以使Feign客户端直接找到对应的微服务
@FeignClient(value = "SPRINGCLOUD-PROVIDER-DEPT")
public interface DeptClientService {

    @GetMapping("/dept/get/{id}")
    public Dept queryById(@PathVariable("id") Long id);

    @GetMapping("/dept/list")
    public Dept queryAll();

    @GetMapping("/dept/add")
    public Dept addDept(Dept dept);
}

Hystrix:服务熔断

Tips:分布式系统面临的问题:复杂分布式体系结构中的应用程序有数十个依赖关系,每个依赖关系在某些时候将不可避免失败!

服务雪崩

多个微服务之间调用的时候,假设微服务A调用微服务B和微服务C,微服务B和微服务C又调用其他的微服务,这就是所谓的“扇出”,如果扇出的链路上某个微服务的调用响应时间过长,或者不可用,对微服务A的调用就会占用越来越多的系统资源,进而引起系统崩溃,所谓的“雪崩效应”。

img

对于高流量的应用来说,单一的后端依赖可能会导致所有服务器上的所有资源都在几十秒内饱和。比失败更糟糕的是,这些应用程序还可能导致服务之间的延迟增加,备份队列,线程和其他系统资源紧张,导致整个系统发生更多的级联故障,这些都表示需要对故障和延迟进行隔离和管理,以达到单个依赖关系的失败而不影响整个应用程序或系统运行。我们需要,弃车保帅

Hystrix

Hystrix是一个应用于处理分布式系统的延迟和容错的开源库,在分布式系统里,许多依赖不可避免的会调用失败,比如超时,异常等,Hystrix 能够保证在一个依赖出问题的情况下,不会导致整个体系服务失败,避免级联故障,以提高分布式系统的弹性。

相当于断路器,“断路器”本身是一种开关装置,当某个服务单元发生故障之后,通过断路器的故障监控 (类似熔断保险丝) ,向调用方返回一个服务预期的,可处理的备选响应 (FallBack) ,而不是长时间的等待或者抛出调用方法无法处理的异常,这样就可以保证了服务调用方的线程不会被长时间,不必要的占用,从而避免了故障在分布式系统中的蔓延,乃至雪崩。

Hystrix的作用

当一切正常时,请求流可以如下所示:img

当许多后端系统中有一个潜在阻塞服务时,它可以阻止整个用户请求:img

随着大容量通信量的增加,单个后端依赖项的潜在性会导致所有服务器上的所有资源在几秒钟内饱和。

应用程序中通过网络或客户端库可能导致网络请求的每个点都是潜在故障的来源。比失败更糟糕的是,这些应用程序还可能导致服务之间的延迟增加,从而备份队列、线程和其他系统资源,从而导致更多跨系统的级联故障。img

当使用Hystrix包装每个基础依赖项时,上面的图表中所示的体系结构会发生类似于以下关系图的变化。每个依赖项是相互隔离的,限制在延迟发生时它可以填充的资源中,并包含在回退逻辑中,该逻辑决定在依赖项中发生任何类型的故障时要做出什么样的响应:img

官网资料:https://github.com/Netflix/Hystrix/wiki

为了避免因某个微服务后台出现异常或错误而导致整个应用或网页报错,使用熔断是必要的

服务熔断
通过@HystrixCommand注解实现熔断机制

当失败的调用到一定阀值缺省是5秒内20次调用失败,进行服务的降级进而熔断该节点微服务的调用,快速返回错误的响应信息。

部署步骤:

1.导入hystrix依赖

<!--导入Hystrix依赖-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-hystrix</artifactId>
    <version>1.4.6.RELEASE</version>
</dependency

2.调整yml配置文件

3.修改controller

在controller方法上添加**@HystrixCommand**注解。例如:

@HystrixCommand(fallbackMethod = "hystrixGet")
    @RequestMapping("/dept/get/{id}")//根据id查询
    public Dept get(@PathVariable("id") Long id){
        Dept dept = deptService.queryById(id);
        if (dept==null){
            throw new RuntimeException("这个id=>"+id+",不存在该用户,或信息无法找到~");
        }
        return dept;
    }

4.为主启动类添加对熔断的支持注解@EnableCircuitBreaker

@SpringBootApplication
@EnableEurekaClient // EnableEurekaClient 客户端的启动类,在服务启动后自动向注册中心注册服务
@EnableDiscoveryClient // 服务发现~
@EnableCircuitBreaker // 添加对熔断的支持注解
public class HystrixDeptProvider_8001 {
    public static void main(String[] args) {
        SpringApplication.run(HystrixDeptProvider_8001.class,args);
    }
}

5.测试:

使用熔断后,当访问一个不存在的id时,前台页展示数据如下:

img

而不适用熔断的springcloud-provider-dept–8001模块访问相同地址会出现下面状况:img

服务降级

服务降级是指 当服务器压力剧增的情况下,根据实际业务情况及流量,对一些服务和页面有策略的不处理,或换种简单的方式处理,从而释放服务器资源以保证核心业务正常运作或高效运作。说白了,就是尽可能的把系统资源让给优先级高的服务

Tips:降级的方式可以根据业务来,可以延迟服务,比如延迟给用户增加积分,只是放到一个缓存中,等服务平稳之后再执行 ;或者在粒度范围内关闭服务,比如关闭相关文章的推荐。

服务降级需要考虑的问题

1)那些服务是核心服务,哪些服务是非核心服务
2)那些服务可以支持降级,那些服务不能支持降级,降级策略是什么
3)除服务降级之外是否存在更复杂的业务放通场景,策略是什么?

自动降级分类

1)超时降级:主要配置好超时时间和超时重试次数和机制,并使用异步机制探测回复情况

2)失败次数降级:主要是一些不稳定的api,当失败调用次数达到一定阀值自动降级,同样要使用异步机制探测回复情况

3)故障降级:比如要调用的远程服务挂掉了(网络故障、DNS故障、http服务返回错误的状态码、rpc服务抛出异常),则可以直接降级。降级后的处理方案有:默认值(比如库存服务挂了,返回默认现货)、兜底数据(比如广告挂了,返回提前准备好的一些静态页面)、缓存(之前暂存的一些缓存数据)

4)限流降级:秒杀或者抢购一些限购商品时,此时可能会因为访问量太大而导致系统崩溃,此时会使用限流来进行限制访问量,当达到限流阀值,后续请求会被降级;降级后的处理方案可以是:排队页面(将用户导流到排队页面等一会重试)、无货(直接告知用户没货了)、错误页(如活动太火爆了,稍后重试)。

服务降级部署案例:

1.在springcloud-api模块下的service包中新建降级配置类DeptClientServiceFallBackFactory.java

/**
 * @Auther: yoann
 * @Date: 2020/05/20
 * @Description: Hystrix服务降级 ~
 */
@Component
public class DeptClientServiceFallBackFactory implements FallbackFactory {

    @Override
    public DeptClientService create(Throwable cause) {
        return new DeptClientService() {
            @Override
            public Dept queryById(Long id) {
                return new Dept()
                        .setDeptno(id)
                        .setDname("id=>" + id + "没有对应的信息,客户端提供了降级的信息,这个服务现在已经被关闭")
                        .setDb_source("没有数据~");
            }
            @Override
            public List<Dept> queryAll() {
                return null;
            }

            @Override
            public Boolean addDept(Dept dept) {
                return false;
            }
        };
    }
}

2.在DeptClientService中指定降级配置类DeptClientServiceFallBackFactory

@Component //注册到spring容器中
//@FeignClient:微服务客户端注解,value:指定微服务的名字,这样就可以使Feign客户端直接找到对应的微服务
@FeignClient(value = "SPRINGCLOUD-PROVIDER-DEPT",fallbackFactory = DeptClientServiceFallBackFactory.class)//fallbackFactory指定降级配置类
public interface DeptClientService {

    @GetMapping("/dept/get/{id}")
    public Dept queryById(@PathVariable("id") Long id);

    @GetMapping("/dept/list")
    public List<Dept> queryAll();

    @GetMapping("/dept/add")
    public Boolean addDept(Dept dept);

3.在springcloud-consumer-dept-feign模块中开启降级:

server:
  port: 80

# Eureka配置
eureka:
  client:
    register-with-eureka: false # 不向 Eureka注册自己
    service-url: # 从三个注册中心中随机取一个去访问
      defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/

# 开启降级feign.hystrix
feign:
  hystrix:
    enabled: true
Dashboard 流监控

1.新建springcloud-consumer-hystrix-dashboard模块

<!--Hystrix依赖-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-hystrix</artifactId>
    <version>1.4.6.RELEASE</version>
</dependency>
<!--dashboard依赖-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
    <version>1.4.6.RELEASE</version>
</dependency>
<!--Ribbon-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-ribbon</artifactId>
    <version>1.4.6.RELEASE</version>
</dependency>
<!--Eureka-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-eureka</artifactId>
    <version>1.4.6.RELEASE</version>
</dependency>
<!--实体类+web-->
<dependency>
    <groupId>com.haust</groupId>
    <artifactId>springcloud-api</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--热部署-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-devtools</artifactId>
</dependency>

2.主启动类

@SpringBootApplication
// 开启Dashboard
@EnableHystrixDashboard
public class DeptConsumerDashboard_9001 {
    public static void main(String[] args) {
        SpringApplication.run(DeptConsumerDashboard_9001.class,args);
    }
}

3.给springcloud-provider-dept-hystrix-8001模块下的主启动类添加如下代码,添加监控

@SpringBootApplication
@EnableEurekaClient //EnableEurekaClient 客户端的启动类,在服务启动后自动向注册中心注册服务
public class DeptProvider_8001 {
    public static void main(String[] args) {
        SpringApplication.run(DeptProvider_8001.class,args);
    }

    //增加一个 Servlet
    @Bean
    public ServletRegistrationBean hystrixMetricsStreamServlet(){
        ServletRegistrationBean registrationBean = new ServletRegistrationBean(new HystrixMetricsStreamServlet());
        //访问该页面就是监控页面
        registrationBean.addUrlMappings("/actuator/hystrix.stream");
       
        return registrationBean;
    }
}

访问:http://localhost:9001/hystrix,进入监控界面:

img

img

Zuul路由网关

Zuul包含了对请求的路由(用来跳转的)和过滤两个最主要功能:

其中路由功能负责将外部请求转发到具体的微服务实例上,是实现外部访问统一入口的基础,而过滤器功能则负责对请求的处理过程进行干预,是实现请求校验,服务聚合等功能的基础。Zuul和Eureka进行整合,将Zuul自身注册为Eureka服务治理下的应用,同时从Eureka中获得其他服务的消息,也即以后的访问微服务都是通过Zuul跳转后获得。Zuul 服务最终还是会注册进 Eureka,他主要提供:代理 + 路由 + 过滤 三大功能!

官方文档:https://github.com/Netflix/zuul/

入门配置案例

1.新建springcloud-zuul模块,并导入依赖

<dependencies>
    <!--导入zuul依赖-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-zuul</artifactId>
        <version>1.4.6.RELEASE</version>
    </dependency>
    <!--Hystrix依赖-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-hystrix</artifactId>
        <version>1.4.6.RELEASE</version>
    </dependency>
    <!--dashboard依赖-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-hystrix-dashboar</artifactId>
        <version>1.4.6.RELEASE</version>
    </dependency>
    <!--Ribbon-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-ribbon</artifactId>
        <version>1.4.6.RELEASE</version>
    </dependency>
    <!--Eureka-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-eureka</artifactId>
        <version>1.4.6.RELEASE</version>
    </dependency>
    <!--实体类+web-->
    <dependency>
        <groupId>com.haust</groupId>
        <artifactId>springcloud-api</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!--热部署-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
    </dependency>
</dependencies>

2.application.yml

server:
  port: 9527

spring:
  application:
    name: springcloud-zuul #微服务名称

# eureka 注册中心配置
eureka:
  client:
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
  instance: #实例的id
    instance-id: zuul9527.com
    prefer-ip-address: true # 显示ip

info:
  app.name: haust.springcloud # 项目名称
  company.name: 河南科技大学西苑校区 # 公司名称

# zull 路由网关配置
zuul:
  # 路由相关配置
  # 原来访问路由 eg:http://www.cspStudy.com:9527/springcloud-provider-dept/dept/get/1
  # zull路由配置后访问路由 eg:http://www.cspstudy.com:9527/haust/mydept/dept/get/1
  routes:
    mydept.serviceId: springcloud-provider-dept # eureka注册中心的服务提供方路由名称
    mydept.path: /mydept/** # 将eureka注册中心的服务提供方路由名称 改为自定义路由名称
  # 不能再使用这个路径访问了,*: 忽略,隐藏全部的服务名称~
  ignored-services: "*"
  # 设置公共的前缀
  prefix: /haust

3.主启动类

/**
 * @Auther: yoann
 * @Date: 2020/05/20
 * @Description: Zuul路由网关主启动类
 */
@SpringBootApplication
@EnableZuulProxy // 开启Zuul
public class ZuulApplication_9527 {

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

4.测试:img

可以看出Zull路由网关被注册到Eureka注册中心中了img

上图是没有经过Zull路由网关配置时,服务接口访问的路由,可以看出直接用微服务(服务提供方)名称去访问,这样不安全,不能将微服务名称暴露!

所以经过Zull路由网关配置后,访问的路由为:img

我们看到,微服务名称被替换并隐藏,换成了我们自定义的微服务名称mydept,同时加上了前缀haust,这样就做到了对路由fan访问的加密处理!

详情参考springcloud中文社区zuul组件 :https://www.springcloud.cc/spring-cloud-greenwich.html#_router_and_filter_zuul

Spring Cloud Config 分布式配置

Spring Cloud Config为分布式系统中的外部配置提供服务器和客户端支持。使用Config Server,您可以在所有环境中管理应用程序的外部属性。客户端和服务器上的概念映射与Spring Environment和PropertySource抽象相同,因此它们与Spring应用程序非常契合,但可以与任何以任何语言运行的应用程序一起使用。随着应用程序通过从开发人员到测试和生产的部署流程,您可以管理这些环境之间的配置,并确定应用程序具有迁移时需要运行的一切。服务器存储后端的默认实现使用git,因此它轻松支持标签版本的配置环境,以及可以访问用于管理内容的各种工具。很容易添加替代实现,并使用Spring配置将其插入。

配置文件管理

img

spring cloud config 为微服务架构中的微服务提供集中化的外部支持,配置服务器为各个不同微服务应用的所有环节提供了一个中心化的外部配置。

spring cloud config 分为服务端和客户端两部分。

服务端也称为 分布式配置中心,它是一个独立的微服务应用,用来连接配置服务器并为客户端提供获取配置信息,加密,解密信息等访问接口。

客户端则是通过指定的配置中心来管理应用资源,以及与业务相关的配置内容,并在启动的时候从配置中心获取和加载配置信息。配置服务器默认采用git来存储配置信息,这样就有助于对环境配置进行版本管理。并且可用通过git客户端工具来方便的管理和访问配置内容。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-irTcLF6A-1661324094938)(C:\Users\MI\AppData\Roaming\Typora\typora-user-images\image-20220822141211464.png)]

参考文件:

https://blog.csdn.net/weixin_43591980/article/details/106255122?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522166070469716782184687815%2522%252C%2522scm%2522%253A%252220140713.130102334…%2522%257D&request_id=166070469716782184687815&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2alltop_positive~default-2-106255122-null-null.142v41pc_rank_34,1852^control&utm_term=springcloud&spm=1018.2226.3001.4187

kafka

定义

kafka就是消息队列,用来弥补hadoop和日志服务器处理数据速度的不同的,通过kafka集群可以将其存储为消息,等待使用的时候再用

传统定义:kafka是一个分布式的基于发布/订阅模式的消息队列,主要应用于大数据实时处理领域。

消息的发布与订阅:消息的发布者不会将消息直接发给特定的订阅者,而是将发布的消息分为不同的类别,订阅者只接收感兴趣的消息。

最新定义:kafka是一个开源的分布式事件流平台,被数千家公司用于高性能数据管道、流分析、数据集成和关键任务应用。

传统消息队列的应用场景

缓存/消峰,解耦异步通信

缓存/消峰:存在消息队列中慢慢处理 解耦:数据的消息存在消息队列中,而SpringBoot等需要数据的应用再随用随取就可以 异步通信:允许用户把一个消息放入队列,但并不立即处理它,而是再需要的时候再去处理它们。

消息队列的两种模式

点对点模式

消费者主动拉取数据,消息收到后清除消息。

发布/订阅模式

可以有多个topic主题(浏览,点赞,收藏等多个主题)

消费者消费数据后,不删除数据,且每个消费者相互独立,都可以消费到数据。

1.为了方便扩展,提高吞吐量,一个topic可以分为多个partition。

2.根据这个思想,我们可以配合分区的设计,提出了消费者组的概念,组内每个消费者并行消费。

3.为提高可用性,为每个partition增加若干副本,类似NameNode HA (副本也分为leader个那个和其他的follower,处理数据只根据leader数据进行处理,而只有leader的那个副本挂掉之后才会将一个follower转变成leader取做数据处理。

会使用zookeeper帮助记录服务器的编号信息以及leader,follower信息(所以导致kafka使用必须要用zookeeper,但是在2.8版本之后,kafka也可以不用zookeeper了,这种模式称为fraft模式)

kafka-topics.sh ,在Linux上安装和使用kafka,通过命令行使用kafka。

0&utm_medium=distribute.pc_search_result.none-task-blog-2alltop_positive~default-2-106255122-null-null.142v41pc_rank_34,1852^control&utm_term=springcloud&spm=1018.2226.3001.4187

kafka

定义

kafka就是消息队列,用来弥补hadoop和日志服务器处理数据速度的不同的,通过kafka集群可以将其存储为消息,等待使用的时候再用

传统定义:kafka是一个分布式的基于发布/订阅模式的消息队列,主要应用于大数据实时处理领域。

消息的发布与订阅:消息的发布者不会将消息直接发给特定的订阅者,而是将发布的消息分为不同的类别,订阅者只接收感兴趣的消息。

最新定义:kafka是一个开源的分布式事件流平台,被数千家公司用于高性能数据管道、流分析、数据集成和关键任务应用。

传统消息队列的应用场景

缓存/消峰,解耦异步通信

缓存/消峰:存在消息队列中慢慢处理 解耦:数据的消息存在消息队列中,而SpringBoot等需要数据的应用再随用随取就可以 异步通信:允许用户把一个消息放入队列,但并不立即处理它,而是再需要的时候再去处理它们。

消息队列的两种模式

点对点模式

消费者主动拉取数据,消息收到后清除消息。

发布/订阅模式

可以有多个topic主题(浏览,点赞,收藏等多个主题)

消费者消费数据后,不删除数据,且每个消费者相互独立,都可以消费到数据。

1.为了方便扩展,提高吞吐量,一个topic可以分为多个partition。

2.根据这个思想,我们可以配合分区的设计,提出了消费者组的概念,组内每个消费者并行消费。

3.为提高可用性,为每个partition增加若干副本,类似NameNode HA (副本也分为leader个那个和其他的follower,处理数据只根据leader数据进行处理,而只有leader的那个副本挂掉之后才会将一个follower转变成leader取做数据处理。

会使用zookeeper帮助记录服务器的编号信息以及leader,follower信息(所以导致kafka使用必须要用zookeeper,但是在2.8版本之后,kafka也可以不用zookeeper了,这种模式称为fraft模式)

kafka-topics.sh ,在Linux上安装和使用kafka,通过命令行使用kafka。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值