zoukankan      html  css  js  c++  java
  • springcloud组件-eureka

    1、eureka什么?

    2、eureka单节点如何使用?

    3、eureka集群配置?

    4、zookeeper的cp性与eureka的ap性

    5、关于eureka的自我保护机制


    1、eureka是什么?

      springcloud中的eureka就相当于之前dubbo中的zookeeper,也是一个注册中心。

    一个基于REST的服务,用于定位服务,以实现云端中间层服务发现和故障转移,并且支持集群部署。

    2、eureka单节点?

      以自身所写的项目来说:

       首先新建一个父项目Springcloud,分别去新建子项目:

        springcloud-consumer-management:各个消费者项目

        springcloud-provider-management:各个提供者项目

        springcloud-management:MVC层

        springcloud-eureka-management:eureka项目

      下一步所要做的是:

        (1)在父项目中引入所需要的所有jar包

        (2)在springcloud-management中将Mapper、model、service层新建出来,

          并进行层级依赖的建立:mapper-->model    service-->mapper

        (3)在consumer-management中去引入对应的依赖,并新建一个consumer的子工程:6081

        (4)在provider-management中去引入对应的依赖,并新建一个consumer的子工程:8081

      实现:

      (1)父项目的依赖:

     1 <!--
     2         项目jar包的构建:
     3             之前使用的parent标签直接引入项目中,可以继承父项目的jar包
     4             但是项目中已经使用到了springcloud和springboot
     5             springcloud和springboot需要些两个parent,但是在pom工程中不能这样实现
     6             所以直接引入springboot和springcloud的jar包工程,并且使用dependencyManagement标签进行管理,用到了什么jar包直接重写
     7 
     8             springboot-parent, springcloud-parent的父级工程都是dependencies
     9     -->
    10 
    11     <dependencyManagement>
    12         <dependencies>
    13             <dependency>
    14                 <groupId>org.springframework.boot</groupId>
    15                 <artifactId>spring-boot-dependencies</artifactId>
    16                 <version>2.1.8.RELEASE</version>
    17                 <type>pom</type>
    18                 <scope>import</scope>
    19             </dependency>
    20             <dependency>
    21                 <groupId>org.springframework.cloud</groupId>
    22                 <artifactId>spring-cloud-dependencies</artifactId>
    23                 <version>Greenwich.SR3</version>注意版本号
    24                 <type>pom</type>
    25                 <scope>import</scope>
    26             </dependency>
    27             <dependency>
    28                 <groupId>io.zipkin.java</groupId>
    29                 <artifactId>zipkin-server</artifactId>
    30                 <version>2.11.8</version>
    31                 <exclusions>
    32                     <exclusion>
    33                         <groupId>org.apache.logging.log4j</groupId>
    34                         <artifactId>log4j-slf4j-impl</artifactId>
    35                     </exclusion>
    36                 </exclusions>
    37             </dependency>
    38             <dependency>
    39                 <groupId>io.zipkin.java</groupId>
    40                 <artifactId>zipkin-autoconfigure-ui</artifactId>
    41                 <version>2.11.8</version>
    42             </dependency>
    43             <dependency>
    44                 <groupId>mysql</groupId>
    45                 <artifactId>mysql-connector-java</artifactId>
    46                 <version>5.0.4</version>
    47             </dependency>
    48             <dependency>
    49                 <groupId>com.alibaba</groupId>
    50                 <artifactId>druid</artifactId>
    51                 <version>1.0.31</version>
    52             </dependency>
    53             <dependency>
    54                 <groupId>org.mybatis.spring.boot</groupId>
    55                 <artifactId>mybatis-spring-boot-starter</artifactId>
    56                 <version>1.3.0</version>
    57             </dependency>
    58         </dependencies>
    59     </dependencyManagement>

    (2)springcloud-management中的各层级:

    Mapper层的pom: 
    1
    <?xml version="1.0" encoding="UTF-8"?> 2 <project xmlns="http://maven.apache.org/POM/4.0.0" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 5 <parent> 6 <artifactId>springcloud-management</artifactId> 7 <groupId>com.aaa.liu.springcloud</groupId> 8 <version>1.0-SNAPSHOT</version> 9 </parent> 10 <modelVersion>4.0.0</modelVersion> 11 12 <artifactId>springcloud-mapper</artifactId> 13 14 15 <dependencies> 16 <dependency> 17 <groupId>com.aaa.liu.springcloud</groupId> 18 <artifactId>springcloud-model</artifactId> 19 <version>1.0-SNAPSHOT</version> 20 </dependency> 21 <!-- 22 需要引入mysql mybatis springboot druid 23 --> 24 <dependency> 25 <groupId>mysql</groupId> 26 <artifactId>mysql-connector-java</artifactId> 27 </dependency> 28 <dependency> 29 <groupId>com.alibaba</groupId> 30 <artifactId>druid</artifactId> 31 </dependency> 32 <dependency> 33 <groupId>org.mybatis.spring.boot</groupId> 34 <artifactId>mybatis-spring-boot-starter</artifactId> 35 </dependency> 36 <dependency> 37 <groupId>org.springframework.boot</groupId> 38 <artifactId>spring-boot-starter-web</artifactId> 39 </dependency> 40 </dependencies> 41 </project>
     service层的pom:
    1
    <?xml version="1.0" encoding="UTF-8"?> 2 <project xmlns="http://maven.apache.org/POM/4.0.0" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 5 <parent> 6 <artifactId>springcloud-management</artifactId> 7 <groupId>com.aaa.liu.springcloud</groupId> 8 <version>1.0-SNAPSHOT</version> 9 </parent> 10 <modelVersion>4.0.0</modelVersion> 11 12 <artifactId>springcloud-service</artifactId> 13 14 <dependencies> 15 <dependency> 16 <groupId>com.aaa.liu.springcloud</groupId> 17 <artifactId>springcloud-mapper</artifactId> 18 <version>1.0-SNAPSHOT</version> 19 </dependency> 20 </dependencies> 21 </project>

    (3)consumer-management依赖:

     1 <dependencies>
     2         <dependency>
     3             <groupId>com.aaa.liu.springcloud</groupId>
     4             <artifactId>springcloud-model</artifactId>
     5             <version>1.0-SNAPSHOT</version>
     6         </dependency>
     7         <dependency>
     8             <groupId>org.springframework.boot</groupId>
     9             <artifactId>spring-boot-starter-web</artifactId>
    10         </dependency>
    11     </dependencies>

    (4)provider-management项目的依赖:

     1 <dependencies>
     2         <dependency>
     3             <groupId>org.springframework.cloud</groupId>
     4             <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
     5         </dependency>
     6         <dependency>
     7             <groupId>org.springframework.boot</groupId>
     8             <artifactId>spring-boot-starter-actuator</artifactId>
     9         </dependency>
    10         <dependency>
    11             <groupId>com.aaa.liu.springcloud</groupId>
    12             <artifactId>springcloud-service</artifactId>
    13             <version>1.0-SNAPSHOT</version>
    14         </dependency>
    15     </dependencies>

    正式开始:

    先进行尝试consumer是否能够直接调用到provider中的方法

      在provider-management新建的第一个provider为provider-8081,

    在Java下的包中只需要添加controller包和一个主启动类:

    主启动类:

    @SpringBootApplication
    @MapperScan("com.aaa.liu.springcloud.mapper")
    public class ApplicationRun8081 {
        public static void main(String[] args) {
            SpringApplication.run(ApplicationRun8081.class,args);
        }
    }

    controller层下的UserController:

    @RestController
    public class UserController {
        @Autowired
        private UserService userService;
    
        @RequestMapping("/userAll")
        public List<User> selectAllUsers(){
            System.out.println("8081");
            return userService.selectAllUsers();
        }
    }

    然后在provider下的resources中新建config包,包下是application.properties:

    基本的一些配置:
    server.port=8081
    server.servlet.context-path=/
    
    spring.datasource.driver-class-name=com.mysql.jdbc.Driver
    spring.datasource.url=jdbc:mysql://localhost:3306/mybatis?useSSL=false
    spring.datasource.username=root
    spring.datasource.password=123456
    spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
    
    mybatis.type-aliases-package=com.aaa.liu.springcloud.model
    mybatis.mapper-locations=classpath:mapper/*Mapper.xml

    下面是consumer-management中新建一个consumer6081:

    主启动类:

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

    在Java包下新建了一个config包和controller包

    config包下的ConfigRest:

    /**
     * 对配置类,需要加上configuration或者SpringbootApplication
     * RestTemplate:模拟http协议,使得两个controller调用
     */
    @SpringBootApplication
    public class ConfigRest {
        @Bean
        public RestTemplate getTemplate(){
            return  new RestTemplate();
        }
    }

    controller包下的UserController:

    @RestController
    public class UserController {
    
        @Autowired
        private RestTemplate restTemplate;
        //调用service,consumer项目的controller调用的是provider项目的controller(使用的是http协议)
        //如果可以模拟http协议,就可以实现两个controller之间的调用
        //getForObject:(使用get请求方式)该方法有两个参数
        //第一个参数:URL(请求路径(localhost:8081/userAll))
        //第二个参数:规定返回值的类型
    
        @RequestMapping("/userAll")
        public List<User> selectAllUsers(){
            return restTemplate.getForObject("http://localhost:8081/userAll",List.class);
        }
    }

    resource下的application.properties(由于只是请求服务,不用与数据打交道,不用数据源):

    server.port=6081
    server.servlet.context-path=/

    完事!分别启动provider和consumer,在浏览器中访问localhost:6081/userAll,请求到数据,则调用无碍。

    下面开始eureka的单节点设置:

      代码很简单,在eureka-management中新建一个eureka7081项目

    在Java中只有一个主启动类:

    /**
     * @EnableEurekaServer:就是开启eureka的服务器
     * @EnableEurekaClient:不让用,因为springcloud1.x的注解(我们使用的是格林威治RS3版本)
     */
    @SpringBootApplication
    @EnableEurekaServer
    public class ApplicationRun7081 {
        public static void main(String[] args) {
            SpringApplication.run(ApplicationRun7081.class,args);
        }
    }

    resource中的properties.properties:

    server.port=7081
    server.servlet.context-path=/
    
    # eureka服务器端的实例名称
    eureka.instance.hostname=eureka01
    
    # eureka也会把自己注册进注册中心里,这里因为最终eureka是不需要被发现的服务,
    # 所以不再需要把自己注册到注册中心里
    # 默认值为true,表示把自己注册进注册中心
    eureka.client.register-with-eureka=false
    # 表示自己就是注册中心,注册中心的职责是维护服务实例,并不需要从注册中心里去发现自己
    eureka.client.fetch-registry=false
    # 配置eureka的注册地址
    # zookeeper需要在linux服务器上进行配置,最终的情况下使用zookeeper的时候必须要指向zookeeper的IP地址
    # eureka不需要做任何服务器配置,但是也必须要指向地址(直接指向eureka的项目即可:http://localhost:7081/eureka)
    # 该地址中的localhost就是eureka.instance.hostname的值,端口号就是server.port的值,/eureka:固定的(eureka自己提供)
    # defaultZone:eureka默认所提供的命名空间
    # 在eureka的注册地址中,是可以分空间(zone)的,是命名空间,根据空间的不同来配置不同集群的eureka来实现不同的作用
    # 如果为单节点可以随意配置,但是如果为集群则目前为止必须要配置成defaultZone(因为如果是集群版就必须先要声明命名空间,如果不声明则无法使用)
    eureka.client.service-url.defaultZone=http://localhost:7081/eureka

    在provider8081中进行配置:

      现在主启动类中添加:@EnableDiscoveryClient 注解,与eureka的主启动类的@EnableEurekaServer对应

    (对于eureka来说,provider就是客户端,而eureka是服务端)

    然后就是.properties配置文件了:

    spring.datasource.password=123456
    spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
    
    mybatis.type-aliases-package=com.aaa.liu.springcloud.model
    mybatis.mapper-locations=classpath:mapper/*Mapper.xml
    
    # 配置的是在eureka中显示的服务名(Application)
    # 如果不配置,则会显示UNKNOWN
    spring.application.name=user-provider
    
    # 配置eureka的注册地址(实现provider这个客户端注册进了eureka中)
    # GreenWich rs.3:无论是单节点还是集群模式,
    # eureka的服务器端和客户端的命名空间务必要保持一致,否则会报错(找不到服务实例)
    eureka.client.service-url.defaultZone=http://localhost:7081/eureka
    
    # 是在eureka中配置实例的名字(也就是说Eureka的Status下的显示的名字)
    # 不允许重复  (相当于mysql数据库中的表的主键id)
    eureka.instance.instance-id=user-provider-8081
    
    # 在eureka中显示IP地址
    eureka.instance.prefer-ip-address=true
    
    # 点击eureka的服务名显示出该服务的具体信息
    # 根据服务的具体内容,作者,公司,以及对整个服务的描述来进行
    # 相当于在HTML页面上有一个a标签<a href="/actuator/info"></a>--> 跳转到controller:@RequestMapping("/actuator/info">
    # 开头用info  其他的随便输入
    info.author.name=Liu
    info.company.name=AAA SOFTWARE EDU
    info.project.description=this is Demo

    !这个颜色标注的配置信息是可以不用配置的!

    OK!接下类分别启动eureka、provider、consumer(顺序不要错了,否则会报出无法发现服务异常)

    在浏览器中访问localhost:7081就可以看到eureka的界面了,在上面可以看到关于注册进eureka的provider信息

    3、集群版eureka:

    在eureka-management中再新建两个eureka项目,分别为7082、7083

    将eureka组成一个集群,eureka与zookeeper不同,eureka组成集群,是需要在eureka配置信息里分别

    注入其他两台的信息,让他们能够互相知道。

    server.port=7081
    server.servlet.context-path=/
    
    # eureka服务器端的实例名称
    eureka.instance.hostname=eureka01-->三台分别为eureka01、eureka02、eureka03
    
    # eureka也会把自己注册进注册中心里,这里因为最终eureka是不需要被发现的服务,
    # 所以不再需要把自己注册到注册中心里
    # 默认值为true,表示把自己注册进注册中心
    eureka.client.register-with-eureka=false
    # 表示自己就是注册中心,注册中心的职责是维护服务实例,并不需要从注册中心里去发现自己
    eureka.client.fetch-registry=false
    # 配置eureka的注册地址
    # zookeeper需要在linux服务器上进行配置,最终的情况下使用zookeeper的时候必须要指向zookeeper的IP地址
    # eureka不需要做任何服务器配置,但是也必须要指向地址(直接指向eureka的项目即可:http://localhost:7081/eureka)
    # 该地址中的localhost就是eureka.instance.hostname的值,端口号就是server.port的值,/eureka:固定的(eureka自己提供)
    # defaultZone:eureka默认所提供的命名空间
    # 在eureka的注册地址中,是可以分空间(zone)的,是命名空间,根据空间的不同来配置不同集群的eureka来实现不同的作用
    # 如果为单节点可以随意配置,但是如果为集群则目前为止必须要配置成defaultZone(因为如果是集群版就必须先要声明命名空间,如果不声明则无法使用)
    #eureka.client.service-url.defaultZone=http://localhost:7081/eureka
    eureka.client.service-url.defaultZone=http://eureka02:7082/eureka,http://eureka03:7083/eureka

    与单机版的.properties配置改动很少,主要在两个地方,一个是名字上的区分,一个是最后一行命名空间的配置。

    4、zookeeper和eureka的区别?

      zookeeper保证的是数据CP性,即数据一致性,而eureka保证的是AP性,即服务可用性。

    5、关于eureka的自我保护机制

      如果长时间不去连接(激活)eureka的时候,会出现自我保护机制,在eureka页面上显示:

    EMERGENCY! EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ARE UP WHEN THEY'RE NOT. RENEWALS ARE LESSER THAN THRESHOLD AND HENCE THE INSTANCES ARE NOT BEING EXPIRED JUST TO BE SAFE.

    那么为什么会出现自我保护机制呢?

      在eureka中注册过的服务会定时向eureka发送心跳,当网络故障/网络延迟/服务宕机等情况下,服务器不再向eureka

    发送心跳,eureka从接不到心跳开始计时,默认在90秒(这个时间可以修改)之后,eureka会将这个服务剔除。

    但此处有关剔除的机制有一个点:假设现在有100台服务,其中三台别检测认为宕机,eureka会剔除这三台;

      但如果此刻有198台provider都没有心跳,eureka不会把这198台provider剔除,而是会保留,这也是eureka的保护机制,

    也就是说eureka不会大量剔除服务。这就是eureka的AP性。

    为什么eureka不会剔除大量的服务呢

      AP:只保证了服务的可用性,不保证数据的一致性。

      CP:只保证数据的一致性,不保证服务的可用性。

      如果eureka把所有的服务全部剔除,当consumer尽心访问的时候,发现eureka没有任何服务了,整个项目都处于瘫痪状态,

    整个客户端的体验就会很差,也就是相当于500.

      假设当大面积服务都没有心跳,eureka不剔除的情况下,consumer进行访问调用的时候依然可以找到服务,然后就可以获取数据,

    这些数据可能不是最新的数据,但最起码eureka中还存在服务。

    我们是可以将eureka的保护机制关掉的,但通常不允许这么做,一般可以对它进行失效操作。

    关闭eureka的自我保护机制:

      在eureka-7081项目的application.properties配置文件中,添加:

      eureka.server.enable-self-preservation=false

      然后重新请求eureka,可以在页面上看到THE SELF PRESERVATION MODE IS TURNED OFF等信息。

    让eureka的自我保护机制失效:

      首先eureka会定时检测provider的心跳,假如现在eureka检测provider的时间间隔 ,我们给更改为10s.

    即在eureka-7081的配置文件中添加:eureka.server.eviction-interval-timer-in-ms=10000

    注:单位是毫秒

      其次,假如在provider端是一个集群,现在其中一台provider不需要eureka的自我保护机制,也就是说我们要让

    eureka的自我保护机制在这一台上失效。

      在provider的配置文件中进行配置:告诉eureka,我每隔5秒向你发送心跳,你每隔8秒检测一次,如果没有检测到,

    就直接把我剔除。这样一来,eureka会按照我们在provide的配置来执行,我们就打成了让eureka的自我保护失效的目的。

    provide配置:

      # 规定自己向eureka发送心跳的时间,单位是秒,我们设置为5秒

      eureka.instance.lease-renewal-interval-in-seconds=5

      # 当eureka最后一次检测到心跳的时间间隔(单位是秒),我们给他设置成8秒

      eureka.instance.lease-expiration-duration-in-seconds=8

      

    我们现在对provider进行集群搭建:

    在provider-management中新建两个provider8082、provider8083

    由于只是对provider进行集群配置,所以三台provider上的项目应该是一样的,只是相较于单台provider来说,

    我们需要在配置文件中进行一点修改:

    server.port=8081
    server.servlet.context-path=/
    
    spring.datasource.driver-class-name=com.mysql.jdbc.Driver
    spring.datasource.url=jdbc:mysql://localhost:3306/teach?useSSL=false
    spring.datasource.username=root
    spring.datasource.password=root
    spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
    
    mybatis.type-aliases-package=com.aaa.lee.springcloud.model
    mybatis.mapper-locations=classpath:mapper/*Mapper.xml
    
    # 配置的是在eureka中显示的服务名(Application)
    # 如果不配置,则会显示UNKNOWN(这个是细节!!,以后有问题)
    spring.application.name=user-provider
    
    # 配置eureka的注册地址(实现provider这个客户端注册进了eureka中)
    # GreenWich RS.3:无论是单节点还是集群模式,eureka的服务器端和客户端的命名空间必要保持一致,否则会报错(找不到服务实例)
    #eureka.client.service-url.defaultZone=http://localhost:7081/eureka
    eureka.client.service-url.defaultZone=http://eureka01:7081/eureka,http://eureka02:7082/eureka,http://eureka03:7083/eureka
    
    # 是在eureka中配置实例的名字(也就是说Eureka的Status下的显示的名字)
    # !!!不允许重复!!!(相当于mysql数据库中的表的主键id)
    eureka.instance.instance-id=user-provider-8081
    
    # 在eureka中显示IP地址
    eureka.instance.prefer-ip-address=true
    
    # 点击eureka的服务名显示出该服务的具体信息
    # 根据服务的具体内容,作者,公司,以及对整个服务的描述来进行显示
    # 相当于在HTML页面上有一个a标签<a href="/actuator/info"></a> --> 跳转到controller:@RequestMapping("/actuator/info")
    # !!开头用info!!其他的随便输入
    info.author.name=Liu
    info.company.name=AAA SOFTWARE EDU
    info.project.description=This is Demo
    info.dsadasda=eqwewq321312daa
    
    # 规定自己向eureka发送心跳的时间
    # 单位是秒
    #eureka.instance.lease-renewal-interval-in-seconds=5
    # 当eureka最后一次检测到心跳的时间间隔(单位是秒)
    # eg:15:05:20是最后一次检测到心跳-->检测8秒之后还是无法检测心跳的时候直接剔除
    #eureka.instance.lease-expiration-duration-in-seconds=8

    这里要注意一点:eureka的同步问题!!!

      在provider的配置中,我们需要将provider注册进eureka中, 由于eureka是集群,所以我们在添加配置的时候需要这样写:

    eureka.client.service-url.defaultZone=http://eureka01:7081/eureka,http://eureka02:7082/eureka,http://eureka03:7083/eureka

    但其实我们只写http://eureka01:7081,我们会发现,在eureka中其它两台eureka中也能看到这台provider,原因是eureka进行了同步。

    已有的Eureka Server:在运行过程中,Eureka Server之间会定时同步实例的注册信息。
    
    这样即使新的Application Service只向集群中一台注册服务,则经过一段时间会集群中所有的
    
    Eureka Server都会有这个实例的信息。那么Eureka Server节点之间如何相互发现,
    
    各个节点之间定时(时间由eureka.server.peer-eureka-nodes-update-interval-ms决定)更新节点信息,进行相互发现。
    
    Service Consumer:Service Consumer刚启动时,它会从配置文件读取Eureka Server的地址信息。
    
    当集群中新增一个Eureka Server中时,那么Service Provider如何发现这个Eureka Server?Service Consumer会定时(
    
    此值由eureka.client.eureka
    -service-url-poll-interval-seconds决定)调用Eureka Server集群接口,获取所有的Eureka Server信息的并更新本地配置。
    乾坤未定,你我皆是黑马
  • 相关阅读:
    HDU1050
    POJ3528移石头
    CodeForces230A
    lca学习题
    rmq的st算法模板题 nyoj 119
    rmq问题和lca可以相互转化
    rmq算法,利用倍增思想
    poj 1274 基础二分最大匹配
    hdu 1520 树形dp入门题
    poj 1466 最大独立集
  • 原文地址:https://www.cnblogs.com/liuqijia/p/11609924.html
Copyright © 2011-2022 走看看