微服务-注册中心

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

微服务审批流 什么是微服务注册中心_spring

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服务中心

微服务审批流 什么是微服务注册中心_spring_02

5. 使用eureka搭建集群

注意:因为在一台机器上模拟搭建,所以要修改端口号

1. 创建eureka的服务端三份,并修改其端口号

2. 修改本机的hosts文件

微服务审批流 什么是微服务注册中心_maven_03

3. 修改三个eureka服务的service-url地址

# 配置eureka的相关地址
eureka.client.service-url.defaultZone: http://eureka1:20000/eureka,http://eureka2:20001/eureka,http://eureka3:20002/eureka

4. 启动三台eureka服务

微服务审批流 什么是微服务注册中心_微服务_04

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的自我保护机制

微服务审批流 什么是微服务注册中心_spring_05

微服务审批流 什么是微服务注册中心_微服务审批流_06

微服务审批流 什么是微服务注册中心_微服务审批流_07

什么是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,那么整个集群的业务就会发生混乱

微服务审批流 什么是微服务注册中心_maven_08

eureka的自我保护机制

微服务审批流 什么是微服务注册中心_maven_09

思考:

Eureka的自我保护机制,虽然是为了保证服务间的高可用,但是如果服务器真的挂掉了,那么也被自我保护起来,是不是有问题呢?

自我保护机制一旦启动,确实会保护那些真的出问题的微服务,所以Eureka设置了一个阈值,当15%的心跳都丢失的时候,才会发生自我保护机制,因为这个时候,相对于15%的机器挂掉来说,发生脑裂的概率大一些,但是有没有可能真的是15%机器挂掉了,这个时候Eureka是不能帮我们判断的,需要客户端本身需要一定的容错机制,比如断路器

CP设计好还是AP设计好?

取决于业务,对于注册中心来说,偶尔拿到出问题的微服务,其实对于整个架构来讲没有太大的问题,微服务架构最害怕整个注册中心服务不可用,因此对于注册中心来说AP设计强于CP设计,并不是说一致性不好,对于分布式锁的业务来讲,一定要使用CP,不然整个集群的业务会混乱