微服务-注册中心
1. 什么是微服务
微服务其实是一种架构的设计风格,并没有明确的技术绑定和架构概念,简单来说,微服务就是将原来单一架构开发为一组小型服务的方法,每个服务都运行在独立的进程中,(服务间的隔离,防止一个服务错误,影响其他错误),服务间采用轻量级的通讯机制,这些服务按照业务拆分,并且独立部署,服务会由一个统一的管理中心管理,服务可以采用 不同的语言开发,并且使用不同的存储技术
2. 服务的注册与发现Eureka
问题:为什么需要注册中心?
如果没有注册中心,服务和服务之间会形成硬耦合状态
如果说没有注册中心,服务的消费者调用服务的提供者,如果服务的提供者假如有很多个,那么需要在服务的消费者中注册很多的ip和端口来访问服务的提供者,假设此时有n个消费者,如果新增了一个提供者,那么需要在这n个消费者中都增加提供者的ip和端口,管理起来非常麻烦,耦合非常大
这个时候,注册中心Eureka就应运而生了
注册中心的作用就是为了减少服务间的耦合,
服务的提供者将服务注册在服务中心,服务中心就存在这些提供者的端口和ip,而消费者在注册中心发现服务,消费者通过调用地址来调用服务,如果新增了提供者,只需要注册进注册中心,消费者就会在注册中心发现服务,并调用
3. Eureka服务的搭建
1. 配置自定义的父工程
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.9.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.qf</groupId>
<artifactId>springcloud_demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<!-- <name>springcloud_demo</name>
<description>Demo project for Spring Boot</description>-->
<!--
SpringBoot 2.1.x <-> SpringCloud版本 G版
SpringBoot 2.2.x <-> SpringCloud版本 H版
-->
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Greenwich.SR5</spring-cloud.version>
</properties>
<!-- 删除
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>-->
<!-- 相当于让当前的工程继承了SpringCloud的父工程,用这种方式可以实现Maven的多继承 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<!-- 导入pom工程,相当于多继承 -->
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<!--插件删除 只有微服务才要依赖<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>-->
</project>
2. 创建一个maven工程,继承自定义的父工程,修改当前maven工程的pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>springcloud_demo</artifactId>
<groupId>com.qf</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>springcloud_eureka</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
3.编写启动类
@SpringBootApplication
@EnableEurekaServer
public class EurekaApplication {
public static void main ( String[] args ) {
SpringApplication.run(EurekaApplication.class,args);
}
}
4. 编写全局配置文件
# 修改端口号server:server:
server:
port: 20000
# 配置服务的名字
spring:
application:
name: eureka-server
# 配置eureka的相关属性
eureka:
client:
service-url:
#配置eureka的注册地址
defaultZone: http://localhost:20000/eureka
# 当前的微服务就是注册中心,注册中心不能从注册中心抓取服务,所以该配置需要配置成false
fetch-registry: false
5.启动springboot工程,启动Eureka服务
6.访问注册中心,http://localhost:20000
4.微服务客户端的搭建
1. 创建一个maven工程,继承自定义的父工程,修改pom文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>springcloudeureka001</artifactId>
<groupId>com.wcc</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>studentdemo</artifactId>
<dependencies>
<!--提供对外服务的依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
</dependencies>
</project>
2. 修改全局配置文件
# 端口号
server.port=8082
# 配置服务的名字 注意:微服务的名字尽量不要使用下划线
spring.application.name=student-demo
#配置微服务的地址
eureka.client.service-url.defaultZone: http://localhost:20000/eureka
3.编写启动类
@SpringBootApplication
@EnableEurekaClient
public class StudentClient {
public static void main ( String[] args ) {
SpringApplication.run(StudentClient.class,args);
}
}
4. 观察eureka服务中心
5. 使用eureka搭建集群
注意:因为在一台机器上模拟搭建,所以要修改端口号
1. 创建eureka的服务端三份,并修改其端口号
2. 修改本机的hosts文件
3. 修改三个eureka服务的service-url地址
# 配置eureka的相关地址
eureka.client.service-url.defaultZone: http://eureka1:20000/eureka,http://eureka2:20001/eureka,http://eureka3:20002/eureka
4. 启动三台eureka服务
5. 所有的微服务的注册地址必须改成eureka的集群地址
# 端口号
server.port=8082
# 配置服务的名字 注意:微服务的名字尽量不要使用下划线
spring.application.name=student-demo
#配置微服务的地址
eureka.client.service-url.defaultZone: http://eureka1:20000/eureka,http://eureka2:20001/eureka,http://eureka3:20002/eureka
6.eureka的自我保护机制
什么是eureka的自我保护机制?
eureka如果收到的微服务心跳相对于应该收到的微服务心跳来说,如果低于了85%,就会触发eureka的自我保护机制,一旦自我保护机制启动,eureka就会保护所有的微服务,不被移除,哪怕当前微服务已经下线,或者出现问题,都会保留在eureka的微服务的列表中
6.1 自我保护机制的作用
在介绍自我保护机制的作用之前,先说一下CAP
C:一致性(顺序一致性)
A:可用性
P:分区容错性(脑裂)
任何一个分布式系统,都只能满足CAP中的两个原则,因为分区问题不可避免,所以P是必选的,一般系统,都是从A和C中做选择,Zookeeper是CP设计,而eureka是AP设计
Zookeeper的过半数存活的设计
Zookeeper的过半数存活原则特别浪费资源,那么为什么还要设计过半数存活原则?
假设没有过半数存活原则,那么会发生什么问题呢?
客户端A向服务中心提交了数据a,各个服务中心就会同步这个数据a,客户端B就会在服务中心上读取到这个数据,这就是数据的一致性,这时,客户端A又向服务中心提交了数据b,但是如果刚好给客户端B提供服务的服务中心发生了脑裂,也就是分区容错,如果没有zookeeper的过半数存活原则,那么客户端B还是会继续向外提供服务,但是他提供给的服务的数据是数据a,那么整个集群的业务就会发生混乱
eureka的自我保护机制
思考:
Eureka的自我保护机制,虽然是为了保证服务间的高可用,但是如果服务器真的挂掉了,那么也被自我保护起来,是不是有问题呢?
自我保护机制一旦启动,确实会保护那些真的出问题的微服务,所以Eureka设置了一个阈值,当15%的心跳都丢失的时候,才会发生自我保护机制,因为这个时候,相对于15%的机器挂掉来说,发生脑裂的概率大一些,但是有没有可能真的是15%机器挂掉了,这个时候Eureka是不能帮我们判断的,需要客户端本身需要一定的容错机制,比如断路器
CP设计好还是AP设计好?
取决于业务,对于注册中心来说,偶尔拿到出问题的微服务,其实对于整个架构来讲没有太大的问题,微服务架构最害怕整个注册中心服务不可用,因此对于注册中心来说AP设计强于CP设计,并不是说一致性不好,对于分布式锁的业务来讲,一定要使用CP,不然整个集群的业务会混乱