精华内容
下载资源
问答
  • 服务注册与发现

    2020-03-15 03:22:39
    服务注册与发现 概述 在这里,我们需要用的组件是 Spring Cloud Netflix 的 Eureka,Eureka 是一个服务注册和发现模块 创建服务注册中心 其 pom.xml 文件配置如下: <?xml version="1.0" encoding="UTF...

    服务注册与发现

     

    概述

    在这里,我们需要用的组件是 Spring Cloud Netflix 的 Eureka,Eureka 是一个服务注册和发现模块

    创建服务注册中心

    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">
        <modelVersion>4.0.0</modelVersion>
    
        <parent>
            <groupId>com.funtl</groupId>
            <artifactId>hello-spring-cloud-dependencies</artifactId>
            <version>1.0.0-SNAPSHOT</version>
            <relativePath>../hello-spring-cloud-dependencies/pom.xml</relativePath>
        </parent>
    
        <artifactId>hello-spring-cloud-eureka</artifactId>
        <packaging>jar</packaging>
    
        <name>hello-spring-cloud-eureka</name>
        <url>http://www.funtl.com</url>
        <inceptionYear>2018-Now</inceptionYear>
    
        <dependencies>
            <!-- Spring Boot Begin -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
            <!-- Spring Boot End -->
    
            <!-- Spring Cloud Begin -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
            </dependency>
            <!-- Spring Cloud End -->
        </dependencies>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                    <configuration>
                        <mainClass>com.funtl.hello.spring.cloud.eureka.EurekaApplication</mainClass>
                    </configuration>
                </plugin>
            </plugins>
        </build>
    </project>
    

    Application

    启动一个服务注册中心,只需要一个注解 @EnableEurekaServer  在类EurekaApplication

    package com.funtl.hello.spring.cloud.eureka;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
    
    @SpringBootApplication
    @EnableEurekaServer
    public class EurekaApplication {
        public static void main(String[] args) {
            SpringApplication.run(EurekaApplication.class, args);
        }
    }
    

    application.yml

    Eureka 是一个高可用的组件,它没有后端缓存,每一个实例注册之后需要向注册中心发送心跳(因此可以在内存中完成),在默认情况下 Erureka Server 也是一个 Eureka Client ,必须要指定一个 Server。

    spring:
      application:
        name: hello-spring-cloud-eureka
    
    server:
      port: 8761
    
    eureka:
      instance:
        hostname: localhost
      client:
        registerWithEureka: false
        fetchRegistry: false
        serviceUrl:
          defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
    

    通过 eureka.client.registerWithEureka:falsefetchRegistry:false 来表明自己是一个 Eureka Server.

    操作界面

    Eureka Server 是有界面的,启动工程,打开浏览器访问:

    http://localhost:8761

     

    展开全文
  • 随着业务的发展,用户量日益上升,...第一篇:架构演进在分布式体系下服务注册与发现将会以核心组件而存在,也将是接下来讨论的话题。Lazy服务注册与发现(一)由于应用的分解,微服务的引入,服务越来越多,业务系统...

    随着业务的发展,用户量日益上升,单一的系统越来越复杂,越来越庞大,单纯的提升服务器性能始终有顶天的一天,我们可以通过分布式技术,例如:服务器集群,水平业务划分,应用分解,系统分流,微服务架构等方式来解决系统性能问题和复杂业务问题。

    第一篇:架构演进

    在分布式体系下服务注册与发现将会以核心组件而存在,也将是接下来讨论的话题。

    Lazy服务注册与发现(一)

    由于应用的分解,微服务的引入,服务越来越多,业务系统与服务系统之间的调用,都需要有效管理。

    在服务化的早期,服务不是很多,服务的注册与发现并不是什么新鲜的名词,Nginx+内部域名服务器方式,甚至Nginx+host文件配置方式也能完成服务的注册与发现。

    架构图如下:

    c144a577f3d1

    (架构一)

    各组件角色如下:

    Nginx通过多域名配置实现生产者服务路由,通过upstream对生产者提供负载均衡,通过checkhealth对生产者提供健康检查。

    在内部域名服务器/本地host文件配置服务域名的方式,实现域名与服务的绑定。

    生产者提供服务给消费者访问,并通过Nginx来进行请求分发。在服务化的早期,服务较少,访问量较小,解决了服务的注册与发现与负载均衡等问题。随着业务的发展,用户量日益上升,服务也越来越多,该架构的问题暴露出来:

    1)最明显的问题是所有的请求都需要nginx来转发,同时随着访问量的提升,会成为一个性能瓶颈。

    2)随着内部服务的越来越多,服务上线nginx的配置,内部域名的配置也越来越多,不利于快速部署。

    3)一旦内部网络调整,nginx upstream也需要做对应的配置调整。

    Lazy服务注册与发现(二)

    由于所有的请求都需要nginx来转发,同时随着访问量的提升,会成为一个性能瓶颈,为了解决这个瓶颈,引入下面这个架构。

    c144a577f3d1

    (架构二)

    这个架构在nginx的上层加入了LVS,LVS基于第四层的IP转发,一定限度提高了并发能力,但是所有请求都通过LVS来转发。

    同时nginx分组,服务分组,虽然nginx不再是瓶颈的所在,但是这样带来的代价太高,配置越来越多,工作量越来越大,对系统压力需要有预见性,有效nginx分组,服务分组部署。

    Lazy服务注册与发现(三)

    由于所有的请求都需要LVS来转发,同时随着访问量的提升,会成为一个性能瓶颈,为了解决这个瓶颈,引入下面这个架构。

    c144a577f3d1

    (架构三)

    在这个架构基础上需要做两件事情:

    对系统压力需要有预见性,有效nginx分组,服务分组部署。

    消费端需要编程实现分组选择,可以是轮训,random等实现,我们每一个消费者同时承担了的负载均衡的职责。

    ZK服务注册与发现 (一)

    通过架构三解决了nginx的瓶紧,但是服务上下线需要在nginx,域名服务器做相应的配置,一旦服务的IP端口发生变化,都需要在nginx上做相应的配置,为了解决这个问题引入下面这个架构。

    c144a577f3d1

    (架构四)

    服务在启动的时候就将endpoint注册到Zookeeper对服务进行统一管理。

    服务节点增加Endpoint不需要做任何配置,ZK将以Watch机制通知消费者。

    消费者本地缓存了提供者服务列表,不需要转发,直接发起服务调用。

    缺点:

    需要通过zookeeper API来实现服务注册与发现,负载均衡,以及容错,为了解决nginx的瓶紧架构三也是需要通过编程的方式实现负载均衡。

    ZK服务注册与发现 (二)

    Zookeeper数据模型结构是一个树状层次结构。每个节点叫做Znode,节点可以拥有子节点,同时允许将少量数据存储在该节点下,客户端可以通过NodeCacheListener监听节点的数据变更,PathChildrenCacheListener监听子节点变更来实时获取Znode的变更(Wather机制)。

    以下是点融成都服务注册结构,见下图,接下来的讲解也将以这个结构为基础:

    c144a577f3d1

    ZK服务注册与发现 (三)

    1./com/dianrong/cfg/1.0.0/rpcservice: 命名空间,用来跟其他用途区分。

    2./com/dianrong/cfg/1.0.0/rpcservice下的所有子目录由两部分组成,

    “应用名称” + “-” +  “分组名称”例如:ProductService-SG1,ProductService-SG2, 对应Nginx注册中心Nginx-SG1, Nginx-SG2

    c144a577f3d1

    3. 服务分组下的所有子节点为临时节点,key为“PROVIDER”+ IP(去符号.)  + “-” + 端口,Value为endpoint信息。

    例如:PROVIDER1921681010-8080   = http://192.168.10.10:8080

    第二篇:代码分析

    项目说明

    有了上面的理论我们接下来针对基于ZK的服务与发现的代码分析,代码已经提交到git

    GIT地址:

    https://code.dianrong.com/projects/PLAT/repos/platform/compare/commits?sourceBranch=refs%2Fheads%2FEVER-81-zk&targetBranch=refs%2Fheads%2Fmaster

    说明:

    1. 该组件建立在Curator基础之上,Curator是Netflix开源的一套ZooKeeper客户端框架封装ZooKeeper client与ZooKeeper server之间的连接处理。

    2. Curator提供如下机制,保证我们不需要关注网络通信,而把主要精力放在业务逻辑的处理。

    重试机制:提供可插拔的重试机制, 它将给捕获所有可恢复的异常配置一个重试策略, 并且内部也提供了几种标准的重试策略

    连接状态监控: Curator初始化之后会一直的对zk连接进行监听, 一旦发现连接状态发生变化, 将作出相应的处理

    ZK客户端实例管理:Curator对zk客户端到server集群连接进行管理. 并在需要的情况, 透明重建zk实例, 保证与zk集群的可靠连接

    基于ZK的服务与发现UML类图:

    c144a577f3d1

    目标

    1. 统一配置中心

    数据实时性,一旦zk节点发生变化,实时通知本地hash同步刷新。

    2. 服务注册

    服务启动完成,服务IP,端口以临时节点的形式注册到zk,在网络正常的情况下,一直存在。

    3. 服务发现

    服务启动完成,将服务注册信息刷新到本地hash。

    4. 服务上下线

    服务注册到zk将实时通知服务发现方,更新本地hash,服务下线也将实时通知服务发现方,更新本地hash。

    5. 负载均衡

    服务发现方获取服务缓存在本地hash,通过random,robin等负载均衡算法完成服务选择性调用。

    6. 网络中断容灾

    针对注册方网络中断,服务下线,网络恢复,服务上线,并通知服务发现方更新本地Hash;

    针对发现方网络中断,通过本地hash负载均衡,网络恢复重刷hash,负载均衡重新分配。

    7. Zookeeper宕机容灾

    针对注册方Zookeeper宕机,服务下线,尝试重连, Zookeeper 启动重连成功,服务上线,并通知服务发现方更新本地hash,针对发现方Zookeeper宕机,通过本地hash负载均衡,尝试重连,  Zookeeper 启动重连成功,重刷hash,负载均衡重新分配。

    基本配置

    PathConfig.java

    包含服务注册的命名空间和统一配置的命名空间的配置。

    SgConfig.java

    包含服务名和分组名的配置

    ZookeeperConfig.java

    包含zookeeper地址,会话超时时间,连接超时时间,命名空间以及认证信息的配置

    ZK操作框架

    IzookeeperManager.java

    定义了一套zookeeper操作规范(类似JDBC操作数据数据库规范),有待继续完善。

    ZookeeperManager.java

    针对IzookeeperManager接口规范的实现(类似Mysql驱动对Mysql操作的实现)

    ZookeeperManagerPool.java

    针对ZookeeperManager实例的缓存,不同配置缓存不同ZookeeperManager实例,避免zookeeper连接创建的开销,同时可以根据zookeeper水平分组扩展zookeeper

    实例。

    统一配置,服务注册与发现

    AbstractZookeeperFeature.java

    内部两个接口定义:

    IConfigService 提供针对统一配置接口的定义, IManagementService提供服务注册与发现接口的定义。

    ConfigService.java

    统一配置的实现。

    ManagementService.java

    服务注册与发现的实现。

    负载均衡

    LbStrategy.java

    负载均衡策略接口定义,目前实现了两种负载均衡算法,Random负载均衡和Robin负载均衡。

    RandomStrategy.java

    基于随机负载均衡的实现。

    RobinStrategy.java

    基于轮循负载均衡的实现。

    统一配置Listener

    ConfigPathChildrenCacheListener.java

    统一配置结点监听, 针对CHILD_REMOVED,CHILD_ADDED,CHILD_UPDATED事件对本地hash实时更新。

    服务注册与发现Listener

    ZookeeperStateListener.java

    Zookeeper状态监听接口定义,定义需要关心的三种事件:

    LOST-断开连接达到一定时间

    CONNECTED-第一次连接成功

    RECONNECTED-重连成功触发事件。

    ServiceRegistStateListener.java

    服务注册状态监听实现:

    1.一旦网络丢包严重/ zk宕机/ zk重启,客户端将会与zk断开,服务下线,网络恢复将触发reconnected连接,服务重新注册。

    2.一旦zk断开服务下线,长时间连接不上触发Lost事件,ServiceRegistStateListener将会尝试不断连接直到连上为止,服务重新注册。

    ServiceDiscoverStateListener.java

    服务发现状态监听实现:

    1.一旦网络丢包严重/ zk宕机/ zk重启,客户端将会与zk断开,网络恢复将触发reconnected连接,重新获取服务列表,刷新本地hash。

    2.一旦zk断开服务下线,长时间连接不上触发Lost事件,ServiceDiscoverStateListener将会尝试不断连接直到连上为止,以便刷新本地hash。

    ServicePathChildrenCacheListener.java

    服务发现结点监听, 针对CHILD_REMOVED,CHILD_ADDED,CHILD_UPDATED事件消费者对本地hash实时更新,以便及时刷新服务上下线。

    第三篇:单元测试

    环境准备

    1. 在zookeeper中准备结点 com/dianrong/cfg/1.0.0/rpcservice

    create /com/dianrong/cfg/1.0.0/rpcservice  “”

    2. 模拟docker/JVM启动参数设置

    由于点融网是通过物理机IP加端口映射到docker实例IP加端口的方式对外提供服务,因此需要通过java -D配置宿主机的IP加端口以便应用程序获取服务IP加端口用来进行服务注册。

    c144a577f3d1

    服务注册

    1. 在服务注册之前通过zookeeper控制台查看,期望的注册节点目前为空。

    c144a577f3d1

    2. 启动服务注册单元测试,sleep 10s。

    c144a577f3d1

    3. 观察zookeeper中注册结点,期望的临时节点已经存在。

    c144a577f3d1

    服务发现

    通过服务注册以后然后服务发现,发现节点与预期注册结点一致。

    c144a577f3d1

    负载均衡

    通过服务注册以后然后负载均衡,负载均衡获取节点与预期节点一致。

    c144a577f3d1

    服务上下线

    1. 准备两套单元测试并模拟docker/JVM启动参数设置。

    c144a577f3d1

    c144a577f3d1

    2.启动服务注册,服务发现,负载均衡集成单元测试,测试控制台按照预期打印出服务注册信息,注册了两个服务节点通过负载均衡交叉出现。

    c144a577f3d1

    c144a577f3d1

    3. 通过zookeeper控制台查看成功注册两个节点。

    c144a577f3d1

    4.关闭机器1单元测试,结点1在zookeeper离线,结点2在zookeeper在线。

    c144a577f3d1

    c144a577f3d1

    负载均衡只有一个节点存在达到预期目的

    c144a577f3d1

    网络中断

    1. 启动服务注册,服务发现,负载均衡集成单元测试,测试控制台按照预期打印出服务注册信息。

    c144a577f3d1

    2. 通过Linux iptables开启防火墙,模拟网络中断。

    c144a577f3d1

    服务掉线,通过zookeeper控制台查看注册节点消失。

    c144a577f3d1

    服务发现方任然可以从本地Hash中获取服务节点。

    c144a577f3d1

    3. 关闭Iptables,服务上线。

    c144a577f3d1

    服务上线,通过zookeeper控制台查看注册节点出现。

    c144a577f3d1

    服务发现方获取服务节点重刷本地Hash中。

    c144a577f3d1

    Zookeeper宕机

    1. 启动服务注册,服务发现,负载均衡集成单元测试,测试控制台按照预期打印出服务注册信息。

    c144a577f3d1

    2.关闭zookeeper,单元测试出现连接拒绝错误,但是任然能按照预期获取本地hash中的服务注册信息。

    c144a577f3d1

    c144a577f3d1

    3. 启动zookeeper,单元测试打印出重连信息,并重刷本地服务hash。

    c144a577f3d1

    c144a577f3d1

    本文作者:秦瑜 Chris.Qin(点融黑帮),来自点融BE Team, 2015年10月加入点融,多年大并发分布式互联网架构经验。

    展开全文
  • B站服务注册与发现DiscoveryB站服务注册与发现Discovery
  • Dubbo服务注册与发现.doc,这份文档讲解Dubbo服务注册与发现的例子
  • Eureka 服务注册与发现

    千次阅读 2019-02-12 19:46:39
    Eureka 服务注册与发现

    SpringCloud 2018

    GitHub



    1-Eureka 概述

    1.1-是什么

    Eureka 是 Netflix 的一个子模块,也是核心模块之一。Eureka 是一个基于 Rest 的服务,用于定位服务,以实现云端中间层服务发现和故障转移。服务注册与发现对于微服务架构来说是非常重要的,有了服务发现与注册,只需要使用服务的标识符,就可以访问到服务,而不需要修改服务调用的配置文件了。功能类似于 Dubbo 的注册中心,比如 Zookeeper

    Netflix 在设计 Eureka 时遵守的就是AP原则。 CAP 原则又称 CAP 定理,指的是在一个分布式系统中:Consistency(一致性)、Availability(可用性)、Partition tolerance(分区容错性)三者不可兼得

    1.2-基本架构

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

    Eureka 采用了 C-S 的设计架构。Eureka Server 作为服务注册功能的服务器,它是服务注册中心。而系统中的其他微服务,使用 Eureka 的客户端连接到 Eureka Server 并维持心跳连接。这样系统的维护人员就可以通过 Eureka Server 来监控系统中各个微服务是否正常运行。SpringCloud 的一些其他模块(比如 Zuul)就可以通过 Eureka Server 来发现系统中的其他微服务,并执行相关的逻辑。

    请注意和 Dubbo 的架构对比
    在这里插入图片描述
    在这里插入图片描述
    Eureka 包含两个组件:Eureka Server 和 Eureka Client。

    • Eureka Server 提供服务注册服务

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

    • Eureka Client 是一个 Java 客户端

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

    1.3-三大角色

    • Eureka Server:提供服务注册和发现。
    • Service Provider:服务提供方将自身服务注册到 Eureka,从而使服务消费方能够找到。
    • Service Consumer:服务消费方从 Eureka 获取注册服务列表,从而能够消费服务。

    1.4-工程情况

    目前工程情况(微服务工程搭建:https://hjyang.blog.csdn.net/article/details/83549746):

    • 父工程 microservicecloud

    • 公共模块 microservicecloud-api

    • 提供者服务 microservicecloud-provider-dept-8001

    • 消费者服务 microservicecloud-consumer-dept-80


    2-Eureka 单机

    2.1-注册中心服务 microservicecloud-eureka-7001

    a、右击父工程 microservicecloud,新建子模块 microservicecloud-eureka-7001
    在这里插入图片描述
    b、修改子模块 microservicecloud-eureka-7001 中 pom.xml

    <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">
        <modelVersion>4.0.0</modelVersion>
    
        <parent>
            <groupId>com.atguigu.springcloud</groupId>
            <artifactId>microservicecloud</artifactId>
            <version>1.0-SNAPSHOT</version>
        </parent>
    
        <artifactId>microservicecloud-eureka-7001</artifactId>
    
        <dependencies>
            <!-- Eureka-server 服务端 -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-eureka-server</artifactId>
            </dependency>
            <!-- 热部署:修改后立即生效 -->
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>springloaded</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-devtools</artifactId>
            </dependency>
        </dependencies>
    </project>
    

    c、修改子模块 microservicecloud-eureka-7001,目录 /src/main/resources 中新建 application.yml

    server:
      port: 7001
    
    eureka:
      instance:
        # Eureka 服务端的实例名称
        hostname: localhost
      client:
        # false 表示不向注册中心注册自己
        register-with-eureka: false
        # false 表示自己端就是注册中心,职责就是维护服务实例,并不需要去检索服务
        fetch-registry: false
        service-url:
          # 设置与 Eureka Server 交互的地址:查询服务和注册服务都需要依赖这个地址
          defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
    

    d、修改子模块 microservicecloud-eureka-7001,目录 /src/main/java 中新建包 com.atguigu.springcloud

    e、修改子模块 microservicecloud-eureka-7001,包 com.atguigu.springcloud 中新建启动类 EurekaServer7001_App.java
    在这里插入图片描述

    package com.atguigu.springcloud;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
    
    @SpringBootApplication
    @EnableEurekaServer// EurekaServer 服务器端启动类,接受其它微服务注册进来
    public class EurekaServer7001_App {
        public static void main(String[] args) {
            SpringApplication.run(EurekaServer7001_App.class, args);
        }
    }
    

    f、测试子模块 microservicecloud-eureka-7001

    • 启动 microservicecloud-eureka-7001

    • http://localhost:7001/
      在这里插入图片描述
      No application available(没有服务被发现):因为没有注册服务进来当然不可能有服务被发现。

    2.2-提供者服务 microservicecloud-provider-dept-8001 服务注册

    a、修改子模块 microservicecloud-provider-dept-8001 中 pom.xml
    在这里插入图片描述

    <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">
        <modelVersion>4.0.0</modelVersion>
    
        <parent>
            <groupId>com.atguigu.springcloud</groupId>
            <artifactId>microservicecloud</artifactId>
            <version>1.0-SNAPSHOT</version>
        </parent>
    
        <artifactId>microservicecloud-provider-dept-8001</artifactId>
    
        <dependencies>
            <!-- 引入自定义模块 microservicecloud-api 包,可使用 Dept 部门 Entity -->
            <dependency>
                <groupId>com.atguigu.springcloud</groupId>
                <artifactId>microservicecloud-api</artifactId>
                <version>${project.version}</version>
            </dependency>
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
            </dependency>
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
            </dependency>
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid</artifactId>
            </dependency>
            <dependency>
                <groupId>ch.qos.logback</groupId>
                <artifactId>logback-core</artifactId>
            </dependency>
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-jetty</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
            </dependency>
            <!-- 热部署:修改后立即生效 -->
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>springloaded</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-devtools</artifactId>
            </dependency>
            <!-- 将微服务 Provider 注册进 Eureka -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-eureka</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-config</artifactId>
            </dependency>
        </dependencies>
    </project>
    

    b、修改子模块 microservicecloud-provider-dept-8001,目录 /src/main/resources 中 application.yml
    在这里插入图片描述

    server:
      port: 8001
    
    eureka:
      # 客户端注册进 Eureka 服务列表内
      client:
        service-url:
          defaultZone: http://localhost:7001/eureka
    
    spring:
      application:
        name: microservicecloud-dept
      datasource:
        # 数据源操作类型
        type: com.alibaba.druid.pool.DruidDataSource
        # MySQL 驱动包
        driver-class-name: org.gjt.mm.mysql.Driver
        # 数据库名称
        url: jdbc:mysql://localhost:3306/cloudDB01
        username: root
        password: 123456
        dbcp2:
          # 数据库连接池的最小维持连接数
          min-idle: 5
          # 初始化连接数
          initial-size: 5
          # 最大连接数
          max-total: 5
          # 等待连接获取的最大超时时间
          max-wait-millis: 200
    
    mybatis:
      # Mybatis 配置文件路径
      config-location: classpath:mybatis/mybatis.cfg.xml
      # 所有 Entity 别名类所在包
      type-aliases-package: com.atguigu.springcloud.entities
      mapper-locations:
        # Mapper 映射文件
        - classpath:mybatis/mapper/**/*.xml
    

    c、修改子模块 microservicecloud-provider-dept-8001,包 com.atguigu.springcloud 中启动类 DeptProvider8001_App.java
    在这里插入图片描述

    package com.atguigu.springcloud;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
    
    @SpringBootApplication
    @EnableEurekaClient // 本服务启动后会自动注册进 Eureka 服务中
    public class DeptProvider8001_App {
        public static void main(String[] args) {
            SpringApplication.run(DeptProvider8001_App.class, args);
        }
    }
    

    d、测试子模块 microservicecloud-provider-dept-8001 是否注册

    • 启动子模块(Eureka Server) microservicecloud-eureka-7001

    • 启动子模块 microservicecloud-provider-dept-8001

    • http://localhost:7001/
      在这里插入图片描述
      微服务注册名称配置说明:子模块 microservicecloud-provider-dept-8001 中 application.yml
      在这里插入图片描述

    2.3-Actuator 监控与微服务注册信息完善

    2.3.1-主机名称:服务名称修改

    在这里插入图片描述
    a、修改子模块 microservicecloud-provider-dept-8001,目录 /src/main/resources 中 application.yml
    在这里插入图片描述

    server:
      port: 8001
    
    eureka:
      # 客户端注册进 Eureka 服务列表内
      client:
        service-url:
          defaultZone: http://localhost:7001/eureka
      instance:
        # 自定义服务名称信息
        instance-id: microservicecloud-dept8001
    
    spring:
      application:
        name: microservicecloud-dept
      datasource:
        # 数据源操作类型
        type: com.alibaba.druid.pool.DruidDataSource
        # MySQL 驱动包
        driver-class-name: org.gjt.mm.mysql.Driver
        # 数据库名称
        url: jdbc:mysql://localhost:3306/cloudDB01
        username: root
        password: 123456
        dbcp2:
          # 数据库连接池的最小维持连接数
          min-idle: 5
          # 初始化连接数
          initial-size: 5
          # 最大连接数
          max-total: 5
          # 等待连接获取的最大超时时间
          max-wait-millis: 200
    
    mybatis:
      # Mybatis 配置文件路径
      config-location: classpath:mybatis/mybatis.cfg.xml
      # 所有 Entity 别名类所在包
      type-aliases-package: com.atguigu.springcloud.entities
      mapper-locations:
        # Mapper 映射文件
        - classpath:mybatis/mapper/**/*.xml
    

    b、查看效果
    在这里插入图片描述

    2.3.2-访问信息:添加 IP 信息提示

    a、修改子模块 microservicecloud-provider-dept-8001,目录 /src/main/resources 中 application.yml
    在这里插入图片描述

    server:
      port: 8001
    
    eureka:
      # 客户端注册进 Eureka 服务列表内
      client:
        service-url:
          defaultZone: http://localhost:7001/eureka
      instance:
        # 自定义服务名称信息
        instance-id: microservicecloud-dept8001
        # 访问路径可以显示IP地址
        prefer-ip-address: true
    
    spring:
      application:
        name: microservicecloud-dept
      datasource:
        # 数据源操作类型
        type: com.alibaba.druid.pool.DruidDataSource
        # MySQL 驱动包
        driver-class-name: org.gjt.mm.mysql.Driver
        # 数据库名称
        url: jdbc:mysql://localhost:3306/cloudDB01
        username: root
        password: 123456
        dbcp2:
          # 数据库连接池的最小维持连接数
          min-idle: 5
          # 初始化连接数
          initial-size: 5
          # 最大连接数
          max-total: 5
          # 等待连接获取的最大超时时间
          max-wait-millis: 200
    
    mybatis:
      # Mybatis 配置文件路径
      config-location: classpath:mybatis/mybatis.cfg.xml
      # 所有 Entity 别名类所在包
      type-aliases-package: com.atguigu.springcloud.entities
      mapper-locations:
        # Mapper 映射文件
        - classpath:mybatis/mapper/**/*.xml
    

    b、查看效果

    鼠标停留在服务名称 microservicecloud-dept8001 上显示左下角地址
    在这里插入图片描述

    2.3.3-微服务 Info 详细信息

    当前问题:点击服务名称超链接跳转 Error Page。
    在这里插入图片描述
    a、修改父工程 microservicecloud 中 pom.xml

    添加构建 Build 信息:
    在这里插入图片描述

    <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">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>com.atguigu.springcloud</groupId>
        <artifactId>microservicecloud</artifactId>
        <version>1.0-SNAPSHOT</version>
        <modules>
            <module>microservicecloud-api</module>
            <module>microservicecloud-provider-dept-8001</module>
            <module>microservicecloud-consumer-dept-80</module>
            <module>microservicecloud-eureka-7001</module>
        </modules>
        <packaging>pom</packaging>
    
        <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <maven.compiler.source>1.8</maven.compiler.source>
            <maven.compiler.target>1.8</maven.compiler.target>
            <junit.version>4.12</junit.version>
            <log4j.version>1.2.17</log4j.version>
            <lombok.version>1.16.18</lombok.version>
        </properties>
    
        <dependencyManagement>
            <dependencies>
                <dependency>
                    <groupId>org.springframework.cloud</groupId>
                    <artifactId>spring-cloud-dependencies</artifactId>
                    <version>Dalston.SR1</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
                <dependency>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-dependencies</artifactId>
                    <version>1.5.9.RELEASE</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
                <dependency>
                    <groupId>mysql</groupId>
                    <artifactId>mysql-connector-java</artifactId>
                    <version>5.0.4</version>
                </dependency>
                <dependency>
                    <groupId>com.alibaba</groupId>
                    <artifactId>druid</artifactId>
                    <version>1.0.31</version>
                </dependency>
                <dependency>
                    <groupId>org.mybatis.spring.boot</groupId>
                    <artifactId>mybatis-spring-boot-starter</artifactId>
                    <version>1.3.0</version>
                </dependency>
                <dependency>
                    <groupId>ch.qos.logback</groupId>
                    <artifactId>logback-core</artifactId>
                    <version>1.2.3</version>
                </dependency>
                <dependency>
                    <groupId>junit</groupId>
                    <artifactId>junit</artifactId>
                    <version>${junit.version}</version>
                    <scope>test</scope>
                </dependency>
                <dependency>
                    <groupId>log4j</groupId>
                    <artifactId>log4j</artifactId>
                    <version>${log4j.version}</version>
                </dependency>
            </dependencies>
        </dependencyManagement>
        <build>
            <finalName>microservicecloud</finalName>
            <resources>
                <resource>
                    <directory>src/main/resources</directory>
                    <filtering>true</filtering>
                </resource>
            </resources>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-resources-plugin</artifactId>
                    <configuration>
                        <delimiters>
                            <delimit>$</delimit>
                        </delimiters>
                    </configuration>
                </plugin>
            </plugins>
        </build>
    </project>
    

    b、修改子模块 microservicecloud-provider-dept-8001 中 pom.xml
    在这里插入图片描述

    <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">
        <modelVersion>4.0.0</modelVersion>
    
        <parent>
            <groupId>com.atguigu.springcloud</groupId>
            <artifactId>microservicecloud</artifactId>
            <version>1.0-SNAPSHOT</version>
        </parent>
    
        <artifactId>microservicecloud-provider-dept-8001</artifactId>
    
        <dependencies>
            <!-- 引入自定义模块 microservicecloud-api 包,可使用 Dept 部门 Entity -->
            <dependency>
                <groupId>com.atguigu.springcloud</groupId>
                <artifactId>microservicecloud-api</artifactId>
                <version>${project.version}</version>
            </dependency>
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
            </dependency>
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
            </dependency>
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid</artifactId>
            </dependency>
            <dependency>
                <groupId>ch.qos.logback</groupId>
                <artifactId>logback-core</artifactId>
            </dependency>
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-jetty</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
            </dependency>
            <!-- 热部署:修改后立即生效 -->
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>springloaded</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-devtools</artifactId>
            </dependency>
            <!-- 将微服务 Provider 注册进 Eureka -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-eureka</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-config</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-actuator</artifactId>
            </dependency>
        </dependencies>
    </project>
    

    c、修改子模块 microservicecloud-provider-dept-8001,目录 /src/main/resources 中 application.yml
    在这里插入图片描述

    server:
      port: 8001
    
    eureka:
      # 客户端注册进 Eureka 服务列表内
      client:
        service-url:
          defaultZone: http://localhost:7001/eureka
      instance:
        # 自定义服务名称信息
        instance-id: microservicecloud-dept8001
        # 访问路径可以显示IP地址
        prefer-ip-address: true
    
    info:
      app.name: atguigu-microservicecloud
      company.name: www.atguigu.com
      build.artifactId: "@project.artifactId@"
      build.version: "@project.version@"
    
    spring:
      application:
        name: microservicecloud-dept
      datasource:
        # 数据源操作类型
        type: com.alibaba.druid.pool.DruidDataSource
        # MySQL 驱动包
        driver-class-name: org.gjt.mm.mysql.Driver
        # 数据库名称
        url: jdbc:mysql://localhost:3306/cloudDB01
        username: root
        password: 123456
        dbcp2:
          # 数据库连接池的最小维持连接数
          min-idle: 5
          # 初始化连接数
          initial-size: 5
          # 最大连接数
          max-total: 5
          # 等待连接获取的最大超时时间
          max-wait-millis: 200
    
    mybatis:
      # Mybatis 配置文件路径
      config-location: classpath:mybatis/mybatis.cfg.xml
      # 所有 Entity 别名类所在包
      type-aliases-package: com.atguigu.springcloud.entities
      mapper-locations:
        # Mapper 映射文件
        - classpath:mybatis/mapper/**/*.xml
    

    d、查看效果
    在这里插入图片描述

    2.4-Eureka 自我保护机制

    2.4.1-故障现象

    在这里插入图片描述
    在这里插入图片描述

    2.4.2-导致原因

    什么是自我保护模式?

    默认情况下,如果 Eureka Server 在一定时间内没有接收到某个微服务实例的心跳,Eureka Server 将会注销该实例(默认 90 秒)。但是当网络分区故障发生时,微服务与 Eureka Server 之间无法正常通信,以上行为可能变得非常危险了,因为微服务本身其实是健康的,此时本不应该注销这个微服务

    Eureka 通过自我保护模式来解决这个问题,当 Eureka Server 节点在短时间内丢失过多客户端时(可能发生了网络分区故障),那么这个节点就会进入自我保护模式。一旦进入该模式,Eureka Server 就会保护服务注册表中的信息,不再删除服务注册表中的数据(也就是不会注销任何微服务)。当网络故障恢复后,该 Eureka Server 节点会自动退出自我保护模式。

    在自我保护模式中,Eureka Server 会保护服务注册表中的信息,不再注销任何服务实例。当它收到的心跳数重新恢复到阈值以上时,该 Eureka Server 节点就会自动退出自我保护模式。它的设计哲学就是宁可保留错误的服务注册信息,也不盲目注销任何可能健康的服务实例。一句话讲解:好死不如赖活着。

    综上:自我保护模式是一种应对网络异常的安全保护措施。它的架构哲学是宁可同时保留所有微服务(健康的微服务和不健康的微服务都会保留),也不盲目注销任何健康的微服务。使用自我保护模式,可以让 Eureka 集群更加的健壮、稳定。一句话:某时刻某一个微服务不可用了,Eureka 不会立刻清理,依旧会对该微服务的信息进行保存。

    在 SpringCloud 中可以使用 eureka.server.enable-self-preservation = false 禁用自我保护模式。

    2.5-提供者服务 microservicecloud-provider-dept-8001 服务发现

    对于注册进 Eureka 里面的微服务,可以通过服务发现来获得该服务的信息。

    a、修改子模块 microservicecloud-provider-dept-8001,包 com.atguigu.springcloud.controller 中 DeptController.java
    在这里插入图片描述

    package com.atguigu.springcloud.controller;
    
    import com.atguigu.springcloud.entities.Dept;
    import com.atguigu.springcloud.service.DeptService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.cloud.client.ServiceInstance;
    import org.springframework.cloud.client.discovery.DiscoveryClient;
    import org.springframework.web.bind.annotation.*;
    
    import java.util.List;
    
    @RestController
    public class DeptController {
        @Autowired
        private DeptService service;
        @Autowired
        private DiscoveryClient client;
    
        @RequestMapping(value = "/dept/add", method = RequestMethod.POST)
        public boolean add(@RequestBody Dept dept) {
            return service.add(dept);
        }
    
        @RequestMapping(value = "/dept/get/{id}", method = RequestMethod.GET)
        public Dept get(@PathVariable("id") Long id) {
            return service.get(id);
        }
    
        @RequestMapping(value = "/dept/list", method = RequestMethod.GET)
        public List<Dept> list() {
            return service.list();
        }
    
        @RequestMapping(value = "/dept/discovery", method = RequestMethod.GET)
        public Object discovery() {
            List<String> list = client.getServices();
            System.out.println("**********" + list);
    
            List<ServiceInstance> srvList = client.getInstances("MICROSERVICECLOUD-DEPT");
            for (ServiceInstance element : srvList) {
                System.out.println(element.getServiceId() + "\t" + element.getHost() + "\t"
                        + element.getPort() + "\t" + element.getUri());
            }
            return this.client;
        }
    }
    

    b、修改子模块 microservicecloud-provider-dept-8001,包 com.atguigu.springcloud 中启动类 DeptProvider8001_App.java
    在这里插入图片描述

    package com.atguigu.springcloud;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
    import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
    
    @SpringBootApplication
    @EnableEurekaClient // 本服务启动后会自动注册进 Eureka 服务中
    @EnableDiscoveryClient // 服务发现
    public class DeptProvider8001_App {
        public static void main(String[] args) {
            SpringApplication.run(DeptProvider8001_App.class, args);
        }
    }
    

    c、测试子模块 microservicecloud-provider-dept-8001 服务发现

    d、修改子模块 microservicecloud-consumer-dept-80,包 com.atguigu.springcloud.controller 中 DeptController_Consumer.java
    在这里插入图片描述

    package com.atguigu.springcloud.controller;
    
    import com.atguigu.springcloud.entities.Dept;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    import org.springframework.web.client.RestTemplate;
    
    import java.util.List;
    
    @RestController
    public class DeptController_Consumer {
        private static final String REST_URL_PREFIX = "http://localhost:8001";
    
        @Autowired
        private RestTemplate restTemplate;
    
        @RequestMapping(value = "/consumer/dept/add")
        public boolean add(Dept dept) {
            return restTemplate.postForObject(REST_URL_PREFIX + "/dept/add", dept, Boolean.class);
        }
    
        @RequestMapping(value = "/consumer/dept/get/{id}")
        public Dept get(@PathVariable("id") Long id) {
            return restTemplate.getForObject(REST_URL_PREFIX + "/dept/get/" + id, Dept.class);
        }
    
        @SuppressWarnings("unchecked")
        @RequestMapping(value = "/consumer/dept/list")
        public List<Dept> list() {
            return restTemplate.getForObject(REST_URL_PREFIX + "/dept/list", List.class);
        }
    
        // 测试 @EnableDiscoveryClient 消费端可以调用服务发现
        @RequestMapping(value = "/consumer/dept/discovery")
        public Object discovery() {
            return restTemplate.getForObject(REST_URL_PREFIX + "/dept/discovery", Object.class);
        }
    }
    

    e、测试子模块 microservicecloud-consumer-dept-80 调用子模块 microservicecloud-provider-dept-8001 服务发现


    3-Eureka 集群

    3.1-基本原理

    在这里插入图片描述
    上图是来自 Eureka 的官方架构图,这是基于集群配置的 Eureka:

    • 处于不同节点的 Eureka 通过 Replicate 进行数据同步。
    • Application Service 为服务提供者。
    • Application Client 为服务消费者。
    • Make Remote Call 完成一次服务调用。

    服务启动后向 Eureka 注册,Eureka Server 会将注册信息向其他 Eureka Server 进行同步,当服务消费者要调用服务提供者,则向服务注册中心获取服务提供者地址,然后会将服务提供者地址缓存在本地,下次再调用时,则直接从本地缓存中取,完成一次调用。

    当服务注册中心 Eureka Server 检测到服务提供者因为宕机、网络原因不可用时,则在服务注册中心将服务置为 DOWN 状态,并把当前服务提供者状态向订阅者发布,订阅过的服务消费者更新本地缓存。

    服务提供者在启动后,周期性(默认 30 秒)向 Eureka Server 发送心跳,以证明当前服务是可用状态。Eureka Server 在一定的时间(默认 90 秒)未收到客户端的心跳,则认为服务宕机,注销该实例。

    3.2-集群配置

    a、右击父工程 microservicecloud,新建子模块 microservicecloud-eureka-7002、microservicecloud-eureka-7003
    在这里插入图片描述
    在这里插入图片描述
    b、复制子模块 microservicecloud-eureka-7001 中 pom.xml 内容到子模块 microservicecloud-eureka-7002、microservicecloud-eureka-7003 中 pom.xml

    c、修改子模块 microservicecloud-eureka-7002、microservicecloud-eureka-7003 中 pom.xml
    在这里插入图片描述
    在这里插入图片描述
    d、修改子模块 microservicecloud-eureka-7002、microservicecloud-eureka-7003,目录 /src/main/java 中新建包 com.atguigu.springcloud

    e、复制子模块 microservicecloud-eureka-7001 中包 com.atguigu.springcloud 中启动类 EurekaServer7001_App.java 到子模块 microservicecloud-eureka-7002、microservicecloud-eureka-7003 包 com.atguigu.springcloud

    f、子模块 microservicecloud-eureka-7002、microservicecloud-eureka-7003,包 com.atguigu.springcloud 中启动类重命名为 EurekaServer7002_App.java、EurekaServer7003_App.java

    g、修改 Windows 网络映射配置

    找到 C:\Windows\System32\drivers\etc 路径下的 hosts 文件,添加内容:

    127.0.0.1 eureka7001.com
    127.0.0.1 eureka7002.com
    127.0.0.1 eureka7003.com
    

    h、修改子模块 microservicecloud-eureka-7001,目录 /src/main/resources 中 application.yml
    在这里插入图片描述

    server:
      port: 7001
    
    eureka:
      instance:
        # Eureka 服务端的实例名称
        hostname: eureka7001.com
      client:
        # false 表示不向注册中心注册自己
        register-with-eureka: false
        # false 表示自己端就是注册中心,职责就是维护服务实例,并不需要去检索服务
        fetch-registry: false
        service-url:
          # 设置与 Eureka Server 交互的地址查询服务和注册服务都需要依赖这个地址(单机)。
          # 单机 defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/       
          defaultZone: http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
    

    i、修改子模块 microservicecloud-eureka-7002,目录 /src/main/resources 中新建 application.yml
    在这里插入图片描述

    server:
      port: 7002
    
    eureka:
      instance:
        # Eureka 服务端的实例名称
        hostname: eureka7002.com
      client:
        # false 表示不向注册中心注册自己
        register-with-eureka: false
        # false 表示自己端就是注册中心,职责就是维护服务实例,并不需要去检索服务
        fetch-registry: false
        service-url:
          # 设置与 Eureka Server 交互的地址:查询服务和注册服务都需要依赖这个地址(单机)
          # 单机 defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
          defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7003.com:7003/eureka/
    

    j、修改子模块 microservicecloud-eureka-7003,目录 /src/main/resources 中新建 application.yml
    在这里插入图片描述

    server:
      port: 7003
    
    eureka:
      instance:
        # Eureka 服务端的实例名称
        hostname: eureka7003.com
      client:
        # false 表示不向注册中心注册自己
        register-with-eureka: false
        # false 表示自己端就是注册中心,职责就是维护服务实例,并不需要去检索服务
        fetch-registry: false
        service-url:
          # 设置与 Eureka Server 交互的地址:查询服务和注册服务都需要依赖这个地址(单机)
          # 单机 defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
          defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/
    

    k、修改子模块 microservicecloud-provider-dept-8001,目录 /src/main/resources 中 application.yml
    在这里插入图片描述

    server:
      port: 8001
    
    eureka:
      # 客户端注册进 Eureka 服务列表内
      client:
        service-url:
          defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
      instance:
        # 自定义服务名称信息
        instance-id: microservicecloud-dept8001
        # 访问路径可以显示IP地址
        prefer-ip-address: true
    
    info:
      app.name: atguigu-microservicecloud
      company.name: www.atguigu.com
      build.artifactId: "@project.artifactId@"
      build.version: "@project.version@"
    
    spring:
      application:
        name: microservicecloud-dept
      datasource:
        # 数据源操作类型
        type: com.alibaba.druid.pool.DruidDataSource
        # MySQL 驱动包
        driver-class-name: org.gjt.mm.mysql.Driver
        # 数据库名称
        url: jdbc:mysql://localhost:3306/cloudDB01
        username: root
        password: 123456
        dbcp2:
          # 数据库连接池的最小维持连接数
          min-idle: 5
          # 初始化连接数
          initial-size: 5
          # 最大连接数
          max-total: 5
          # 等待连接获取的最大超时时间
          max-wait-millis: 200
    
    mybatis:
      # Mybatis 配置文件路径
      config-location: classpath:mybatis/mybatis.cfg.xml
      # 所有 Entity 别名类所在包
      type-aliases-package: com.atguigu.springcloud.entities
      mapper-locations:
        # Mapper 映射文件
        - classpath:mybatis/mapper/**/*.xml
    

    l、测试 Eureka 集群


    4-Eureka 与 Zookeeper比较

    作为服务注册中心,Eureka 比 Zookeeper 好在哪里?著名的 CAP 理论指出,一个分布式系统不可能同时满足 C(一致性)、A(可用性)、P(分区容错性)。由于 P 在分布式系统中必须要保证的,因此我们只能在 A 和 C 之间进行权衡。Eureka 则是 AP,而Zookeeper 保证的是 CP

    4.1-Zookeeper 保证 CP

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

    4.2-Eureka 保证 AP

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

    • Eureka 不再从注册列表中移除因为长时间没收到心跳而应该过期的服务 。

    • Eureka 仍然能够接受新服务的注册和查询请求,但是不会被同步到其它节点上(即保证当前节点依然可用)。

    • 当网络稳定时,当前实例新的注册信息会被同步到其它节点中。

    因此 Eureka 可以很好的应对因网络故障导致部分节点失去联系的情况,而不会像 Zookeeper 那样使整个注册服务瘫痪。


    展开全文
  • 服务注册与发现组件

    2020-12-10 14:26:46
    对于微服务架构,服务注册与发现组件是必不可少的。在传统的服务架构中,服务的规模处于运维人员的可控范围内。当部署服务的多个节点时,一般使用静态配置的方式实现服务信息的设定。在微服务应用中,服务实例的数量...

    一、基本功能

    对于微服务架构,服务注册与发现组件是必不可少的。在传统的服务架构中,服务的规模处于运维人员的可控范围内。当部署服务的多个节点时,一般使用静态配置的方式实现服务信息的设定。在微服务应用中,服务实例的数量和网络地址都是动态变化的。

    服务注册与发现

    在一个分布式系统中,服务注册与发现组件主要解决两个问题:服务注册和服务发现。

    服务注册:服务实例将自身服务信息注册到注册中心。这部分服务信息包括服务所在主机IP和提供服务的Port,以及暴露服务自身状态以及访问协议等信息。

    服务发现:服务实例请求注册中心获取所依赖服务信息。服务实例通过注册中心,获取到注册到其中的服务实例的信息,通过这些信息去请求它们提供的服务。

    除此之外,服务注册与发现需要关注监控服务实例运行状态、负载均衡等问题。

    监控:微服务应用中,服务处于动态变化的情况,需要一定机制处理无效的服务实例。一般来讲,服务实例与注册中心在注册后通过心跳的方式维系联系,一旦心跳缺少,对应的服务实例会被注册中心剔除。

    负载均衡:同一服务可能同时存在多个实例,需要正确处理对该服务的负载均衡。

    CAP原则

    CAP原则,指的是在一个分布式系统中,Consistency(一致性)、Availability(可用性)、Partition Tolerance(分区容错性),不能同时成立。

    一致性:它要求在同一时刻点,分布式系统中的所有数据备份都处于同一状态。

    可用性:在系统集群的一部分节点宕机后,系统依然能够响应用户的请求。

    分区容错性:在网络区间通信出现失败,系统能够容忍。

    一般来讲,基于网络的不稳定性,分布容错是不可避免的,所以我们默认CAP中的P总是成立的。

    一致性的强制数据统一要求,必然会导致在更新数据时部分节点处于被锁定状态,此时不可对外提供服务,影响了服务的可用性,反之亦然。因此一致性和可用性不能同时满足(即只存在AP或CP)。

    接下来介绍的服务注册和发现组件中,Eureka满足了其中的AP,Consul和Zookeeper满足了其中的CP。

    二、Eureka

    Eureka是在Java语言上,基于Restful Api开发的服务注册与发现组件,由Netflix开源。

    Eureka采用的是Server/Client的模式进行设计。Server扮演了服务注册中心的角色,为Client提供服务注册和发现的功能,维护着注册到自身的Client的相关信息,同时提供接口给Client获取到注册表中其他服务的信息。Client将有关自己的服务的信息通过一定的方式登记到Server上,并在正常范围内维护自己信息的一致性,方便其他服务发现自己,同时可以通过Server获取到自己的依赖的其他服务信息,从而完成服务调用。

    eureka架构图

    Application Service: 作为Eureka Client,扮演了服务的提供者,提供业务服务,向Eureka Server注册和更新自己的信息,同时能从Eureka Server的注册表中获取到其他服务的信息。

    Eureka Server:扮演服务注册中心的角色,提供服务注册和发现的功能,每个Eureka Cient向Eureka Server注册自己的信息,也可以通过Eureka Server获取到其他服务的信息达到发现和调用其他服务的目的。

    Application Client:作为Eureka Client,扮演了服务消费者,通过Eureka Server获取到注册到上面的其他服务的信息,从而根据信息找到所需的服务发起远程调用。

    Replicate: Eureka Server中的注册表信息的同步拷贝,保持不同的Eureka Server集群中的注册表中的服务实例信息的一致性。提供了数据的最终一致性。

    Make Remote Call: 服务之间的远程调用。

    Register: 注册服务实例,Client端向Server端注册自身的元数据以进行服务发现。

    Renew:续约,通过发送心跳到Server维持和更新注册表中的服务实例元数据的有效性。当在一定时长内Server没有收到Client的心跳信息,将默认服务下线,将服务实例的信息从注册表中删除。

    Cancel:服务下线,Client在关闭时主动向Server注销服务实例元数据,这时Client的的服务实例数据将从Server的注册表中删除。

    Eureka中没有使用任何的数据强一致性算法保证不同集群间的Server的数据一致,仅通过数据拷贝的方式争取注册中心数据的最终一致性,虽然放弃数据强一致性但是换来了Server的可用性,降低了注册的代价,提高了集群运行的健壮性。

    三、Consul

    Consul是由HashiCorp基于Go语言开发的支持多数据中心分布式高可用的服务发布和注册服务软件,采用Raft算法保证服务的一致性,且支持健康检查。 

    Consul采用主从模式的设计,使得集群的数量可以大规模扩展,集群间通过RPC的方式调用(HTTP和DNS)。它的结构图如下所示:

    Client:作为一个代理(非微服务实例),它将转发所有的RPC请求到Server中。作为相对无状态的服务,它不持有任何注册信息。

    Server:作为一个具备扩展功能的代理,它将响应RPC查询、参与Raft选举、维护集群状态和转发查询给Leader等。

    Leader-Server:一个数据中心的所有Server都作为Raft节点集合的一部分。其中Leader将负责所有的查询和事务(如服务注册),同时这些事务也会被复制到所有其他的节点。

    Data Center:数据中心作为一个私有的,低延迟和高带宽的一个网络环境。每个数据中心会存在Consul集群,一般建议Server是3-5台(考虑到Raft算法在可用性和性能上取舍),而Leader只能唯一,Client的数量没有限制,可以轻松扩展。

    Raft算法

    Raft算法将Server分为三种类型:Leader、Follower和Candidate。Leader处理所有的查询和事务,并向Follower同步事务。Follower会将所有的RPC查询和事务转发给Leader处理,它仅从Leader接受事务的同步。数据的一致性以Leader中的数据为准实现。

    在节点初始启动时,节点的Raft状态机将处于Follower状态等待来自Leader节点的心跳。如果在一定时间周期内没有收到Leader节点的心跳,节点将发起选举。

    Follower节点选举时会将自己的状态切换为Candidate,然后向集群中其它Follower节点发送请求,询问其是否选举自己成为Leader。当收到来自集群中过半数节点的接受投票后,节点即成为Leader,开始接收Client的事务处理和查询并向其它的Follower节点同步事务。Leader节点会定时

    Follower发送心跳来保持其地位。

    Gossip协议

    Gossip协议是为了解决分布式环境下监控和事件通知的瓶颈。Gossip协议中的每个Agent会利用Gossip协议互相检查在线状态,分担了服务器节点的心跳压力,通过Gossip广播的方式发送消息。

    所有的Agent都运行着Gossip协议。服务器节点和普通Agent都会加入这个Gossip集群,收发Gossip消息。每隔一段时间,每个节点都会随机选择几个节点发送Gossip消息,其他节点会再次随机选择其他几个节点接力发送消息。这样一段时间过后,整个集群都能收到这条消息。

    基于Raft算法,Consul提供强一致性的注册中心服务,但是由于Leader节点承担了所有的处理工作,势必加大了注册和发现的代价,降低了服务的可用性。通过Gossip协议,Consul可以很好地监控Consul集群的运行,同时可以方便通知各类事件,如Leader选择发生、Server地址变更等。

    四、Zookeeper

    Zookeeper是由Google开源的在Java语言上实现的分布式协调服务,是Hadoop和Hbase的重要组件,提供了数据/发布订阅、负载均衡、分布式同步等功能。

    Zookeeper也是基于主从架构,搭建了一个可高扩展的服务集群,其服务架构如下:

    Leader-Server:Leader负责进行投票的发起和决议,更新系统中的数据状态

    Server:Server中存在两种类型:Follower和Observer。其中Follower接受客户端的请求并返回结果(事务请求将转发给Leader处理),并在选举过程中参与投票;Observer与Follower功能一致,但是不参与投票过程,它的存在是为了提高系统的读取速度

    Client:请求发起方,Server和Client之间可以通过长连接的方式进行交互。如发起注册或者请求集群信息等。

    Zab协议

    ZooKeeper Atomic Broadcast protocol是专门设计给Zookeeper用于实现分布式系统数据的一致性,是在Paxos算法基础上发展而来。它使用了单一的Leader来接受和处理客户端的所有事务请求,并将服务器数据的状态变更以事务Proposal的形式广播到所有的Server中。同时它保证Leader出现异常时,集群依旧能够正常工作。Zab包含两种基本模式:崩溃恢复和消息广播。

    崩溃恢复:Leader服务器出现宕机,或者因为网络原因导致Leader服务器失去了与过半 Follower的联系,那么就会进入崩溃恢复模式从而选举新的Leader。Leader选举算法不仅仅需要让Leader自己知道其自身已经被选举为Leader,同时还需要让集群中的所有其他服务器也能够快速地感知到选举产生的新的Leader。当选举产生了新的Leader,同时集群中有过半的服务器与该Leader完成了状态同步之后,Zab协议就会退出崩溃恢复模式,进入消息广播模式。

    消息广播:Zab协议的消息广播过程类似二阶段提供过程,是一种原子广播的协议。当接受到来自Client的事务请求(如服务注册)(所有的事务请求都会转发给Leader),Leader会为事务生成对应的Proposal,并为其分配一个全局唯一的ZXID。Leader服务器与每个Follower之间都有一个单独的队列进行收发消息,Leader将生成的Proposal发送到队列中。Follower从队列中取出Proposal进行事务消费,消费完毕后发送一个ACK给Leader。当Leader接受到半数以上的Follower发送的ACK投票,它将发送Commit给所有Follower通知其对事务进行提交,Leader本身也会提交事务,并返回给处理成功给对应的客户端。Follower只有将队列中Proposal都同步消费后才可用。

    基于Zab协议,Zookeeper可以用于构建具备数据强一致性的服务注册与发现中心,而与此相对地牺牲了服务的可用性和提高了注册需要的时间。

    展开全文
  • 四、服务注册与发现Consul

    万次阅读 2020-04-16 12:23:06
    服务注册与发现框架Consul的使用
  • 服务注册与发现中,有一个注册中心,当服务器启动的时候,会把当前自已服务器的信息 比如 服务地址通讯地址等以别名方式注册到注册中心上。 另一方(消费者|服务提供者),以该别名的方式去注册中心上获取到实...
  • 本次分享的是关于springcloud服务注册与发现的内容,将通过分别搭建服务中心,服务注册,服务发现来说明,非常具有实用价值,需要的朋友可以参考下
  • 服务注册与发现Nacos

    2021-02-08 23:31:25
    服务注册与发现Nacos服务注册与发现Nacos服务治理的基本概念服务注册中心的概念微服务调用接口常用名词服务注册原理实现Nacos的基本介绍Nacos的环境准备SpringCloud整合nacos创建父工程(普通的maven项目):alibaba-...
  • Eureka服务注册与发现

    2020-09-18 16:28:01
    Eureka服务注册与发现 Eureka基础知识 1. 什么是服务治理? Springcloud 封装了Netflix 公司开发的Eureka模块来实现服务治理。 在传统的rpc 远程调用框架中,管理每个服务与服务之间依赖关系比较复杂,管理比较复杂...
  • 服务注册与发现原理

    千次阅读 2019-02-23 12:34:42
    什么是服务治理 ... 在服务注册与发现中,有一个注册中心,当服务器启动的时候,会把当前自已服务器的信息 比如 服务地址通讯地址等以 别名方式注册到注册中心上。另一方(消费者|服务提供者),以该...
  • springcloud服务注册与发现eureka 接下来,我们一块进入springcloud系列的学习中,关于springcloud微服务的理论知识这里不在描述。 同时欢迎加入qq交流群:springcloud&boot2有问必答,群聊号码:779283684 ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 14,080
精华内容 5,632
关键字:

服务注册与发现