美文网首页
注册中心Eureka

注册中心Eureka

作者: 放开那个BUG | 来源:发表于2019-01-23 10:12 被阅读5次

    从上一节我们看到,我们存在硬编码的问题,虽然我们可以通过把url配置到配置文件中,再从代码中读取配置的方式来解决。但是,每次我们的地址换的时候,配置文件都需要修改,很不方便。所以,我们可以通过服务的注册、发现机制来完成。

    微服务注册与发现

    最基本的原理图如下:


    可以看出:

    • 服务提供者将服务注册到注册中心。
    • 服务消费者通过注册中心查找服务。
    • 查找到服务后进行调用(这里就是无需硬编码url的解决方案)。
    • 服务消费者与服务注册中心保存心跳连接,一旦服务提供者的地址发生变更,注册中心会通知服务消费者。

    注册中心Eureka

    SpringCloud提供了多种注册中心的实现,例如:Eureka、Zookeeper,但是SpringCloud推荐Eureka。

    Eureka是Netfix开源的服务发现组件,本身就是一个基于REST的服务。它包含Server端和Client端。Server就是注册中心,而Client就是指服务被注册成client。它的原理图如图:


    从上图可以看此,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秒)。

    Eureka Server之间通过复制的方式完成数据的同步,Eureka还提供了客户端缓存机制,即使所有的Eureka Server都挂掉,客户端依然能够利用缓存中的消息消费其他服务的API。综上,Eureka通过心跳检查、客户端缓存等机制,确保了系统的高可用性、灵活性和可伸缩性。

    编写Eureka Server

    第一步,新建一个eureka server的模块,然后编辑pom.xml文件,其中最重要的是加入Eureka服务和Spring Cloud的依赖,如图:


    然后,我们我们只需要再运行文件中加入@EnableEurekaServer,申明这是一个Eureka服务。

    package com.example.eureka;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
    
    @EnableEurekaServer  //申明这是一个Eureka服务
    @SpringBootApplication
    public class EurekaApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(EurekaApplication.class, args);
        }
    
    }
    

    然后我们编辑application.yml文件:

    server:
      port: 6868 #服务端口
    
    eureka:
      client:
        registerWithEureka: false #是否将自己注册到Eureka服务中,本身就是所有无需注册
        fetchRegistry: false #是否从Eureka中获取注册信息
    

    然后启动程序进行测试:


    就可以再控制台中查看信息。

    将商品微服务注册到Eureka中

    有了注册中心,我们不需要向以前那样去指定具体的地址了。所以,我们需要将商品微服务注册到Eureka服务中。所以,我们需要修改商品微服务的pom.xml文件,引入SpringCloud依赖和Eureka服务的依赖。


    然后我们需要修改application.yml文件

    server:
      port: 8081 #服务端口
    
    spring:
      application:
        name: xushu-microservice-item #指定服务名
    
    eureka:
      client:
        registerWithEureka: true #是否将自己注册到Eureka服务中,默认为true
        fetchRegistry: true #是否从Eureka中获取注册信息,默认为true
        serviceUrl: #Eureka客户端与Eureka服务端进行交互的地址
          defaultZone: http://127.0.0.1:6868/eureka/
      instance:
        prefer-ip-address: true #将自己的ip地址注册到Eureka服务中
    

    然后我们需要再启动类增加@EnableDiscoveryClient注解,至此全部完毕。然后进行测试,可以看到我们的微服务已经注册到Eureka Server中了。


    订单系统从Eureka中发现服务

    之前我们在订单系统中对地址进行硬编码,现在由于已经将商品的微服务注册到Eureka中,所以只需要从Eureka中发现服务即可。那么,还是需要添加依赖,和商品微服务一样,接着便修改配置文件

    server:
      port: 8082 #服务端口
    
    spring:
      application:
        name: xushu-microservice-order #指定服务名
    
    eureka:
      client:
        registerWithEureka: false #是否将自己注册到Eureka服务中,默认为true
        fetchRegistry: true #是否从Eureka中获取注册信息,默认为true
        serviceUrl: #Eureka客户端与Eureka服务端进行交互的地址
          defaultZone: http://127.0.0.1:6868/eureka/
    

    修改ItemService的逻辑:

    package com.xushu.microservice.order.service;
    
    import com.xushu.microservice.order.pojo.Item;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.cloud.client.ServiceInstance;
    import org.springframework.cloud.client.discovery.DiscoveryClient;
    import org.springframework.stereotype.Service;
    import org.springframework.web.client.RestTemplate;
    import java.util.List;
    
    @Service
    public class ItemService {
        //Spring框架对RESTful方式的http请求做了封装,来简化操作
        @Autowired
        private RestTemplate restTemplate;
    
        @Autowired
        private DiscoveryClient discoveryClient;
    
        /**
         *调用商品的微服务提供的接口进行查询数据
         * @param id
         * @return
         */
        public Item queryItemById(Long id) {
            String serviceId = "xushu-microservice-item";
            List<ServiceInstance> instances = this.discoveryClient.getInstances(serviceId);
            if(instances.isEmpty()){
                return null;
            }
            // 为了演示,在这里只获取一个实例
            ServiceInstance serviceInstance = instances.get(0);
            String url = serviceInstance.getHost() + ":" + serviceInstance.getPort();
            return this.restTemplate.getForObject("http://" + url + "/item/" + id, Item.class);
        }
    }
    
    

    现在,我们只需要指定服务名称,就能够得到它的实例了。测试如下:


    为Eureka添加用户认证

    在前面的示例中,我们无需登录即可访问Eureka服务,很不安全。所以我们需要为Eureka添加用户认证。首先我们需要为Eureka Server添加依赖:

    <!-- 安全认证 -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-security</artifactId>
            </dependency>
    

    然后修改application.xml文件:

    security: 
      basic:  
        enable: true #开启基于HTTP basic的认证
      user: #配置用户的账号信息
        name: xushu
    password: xushu
    

    但是此时服务注册者会出现错误,所以当有服务注册到注册中心时,需要设置如下信息(eureka地址选择你的服务器地址):http://USER:PASSWORD@127.0.0.1:6868/eureka/

    小插曲
    这里有个小插曲,因为最新的Spring security 会默认开启防csrf攻击,我们需要关闭它,所以我们需要在Eureka Server上写一个配置类,然后手动关闭它:

    package com.example.eureka.config;
    
    import org.springframework.context.annotation.Configuration;
    import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
    import org.springframework.security.config.annotation.web.builders.HttpSecurity;
    import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
    import org.springframework.security.crypto.password.NoOpPasswordEncoder;
    
    @Configuration
    public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http
                    .csrf()
                    .disable()
                    .authorizeRequests()
                    .anyRequest().authenticated()
                    .and()
                    .httpBasic();
        }
    }
    

    配置如图:



    然后就可以了。

    Eureka的自我保护模式

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

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

    一般进入自我保护模式,无需处理。所以,不建议禁用自我保护模式。

    Eureka的高可用

    前面的实例中,Eureka服务是一个单点服务,在实际的生产环境中,为了实现高可用,我们需要Eureka集群。

    简历Eureka机器很简单,只需要启动多个Eureka服务并且让这些服务彼此注册即可。在这里,我们再新建一个anotereureka模块,然后application.yml文件修改如下(eureka修改也差不多):


    测试就会发现有两个eureka服务,多个服务同理。这时,如果一般的功能微服务需要注册到集群,要修改 defaultZone 为多个地址即可。


    相关文章

      网友评论

          本文标题:注册中心Eureka

          本文链接:https://www.haomeiwen.com/subject/shutrqtx.html