第二篇:SpringCloud 核心组件注册中心Eureka实战

第二篇主要以下内容:

1. 什么是注册中心?
2. 分布式应用的CAP理论知识
3. eureka 服务注册与发现实战

1. 什么是注册中心?

Spring Cloud Eureka是Spring Cloud Netflix 子项目的核心组件之一

在这里插入图片描述
1.1 理解注册中心:
在微服务架构中往往会有一个注册中心,每个微服务都会向注册中心去注册自己的地址及端口信息,注册中心维护着服务名称与服务实例的对应关系。每个微服务都会定时从注册中心获取服务列表,同时汇报自己的运行情况,这样当有的服务需要调用其他服务时,就可以从自己获取到的服务列表中获取实例地址进行调用,Eureka实现了这套服务注册与发现机制。
服务提供者provider
项目启动的时候向注册中心上报自己的地址和端口信息
服务消费者consumer
项目启动的时候向注册中心上报自己的地址和端口信息,调用时向注册中心获取服务提供者的接口。
1.2 为什么要用注册中心:
当微服务应用的机器越来越多时,调用方需要知道提供者的接口,而单独靠配置文件去控制地址和端口是很难维护的,一个接口地址的修改就会引发其他配置文件的修改。

2. 分布式应用的CAP理论知识

CAP定理:
指的是在一个分布式系统中,Consistency(一致性)、availability(可用性)、Partition(容错性),三者不可同时获得。

  • 一致性:在分布式系统中所有节点的数据值是否一致。如:主从数据库,主数据库的数据和从数据库的数据需要保证一致。
  • 可用性:在高并发的负载压下,分布式系统依然可以响应客户端的请求,并且服务是一直可用的。如:一个接口的QPS是1000,如果哪一天超过这个值,服务器依然可以处理客户端请求响应。
  • 容错性:分区容错性指的就是高可用,一个节点宕机不影响其他节点的业务流程。如:订单服务其中一个节点挂了,但还有其他订单节点可用,不影响用户正常下单。
    CAP理论就是说在分布式系统中,最多只能实现两点,而由于当前网络的硬件肯定会出现延迟丢包等问题,所以分区容错性我们必须要实现,我们只能在一致性和可用性其中选一。

为什么不能三者同时兼容呢?

  • CA满足的情况下,P不能满足的原因:
    如果集群的机器多,数据的同步就需要消耗时间,因为机器太多数据复制耗时,一旦耗时就没办法正常响应,需要正常时间内响应,那么机器就不能太多,所以不能满足P。
  • CP满足的情况下,A不能满足的原因:
    数据的一致性同步需要消耗时间,机器数量也多,那么服务器就没办法在正常时间内响应,因为服务器的数据复制一台机器是10毫秒,那么一百台机器都需要复制数据,那没办法正常响应客户端的请求,所以可用性无法保证。
  • AP满足的情况下,C不能满足的原因:
    机器数量多,也需要正常时间内响应,那么数据就没办法及时同步到其他的节点,所以一致性不满足。

注册中心选择:
zookeeper
CP设计,保证了一致性,集群搭建的时候,某个节点失效,则会进行选举的leader,或者半数以上的节点不可用,则无法提供服务,因此可用性无法满足。
eureka
AP原则:无主从节点,一个节点挂了,自动切换到其他节点可以使用,去中心化。

3. eureka 服务注册与发现实战:

环境:idea、Java 8、SpringBoot 2.2.5、SpringCloud Hoxton.SR3
注意:SpringBoot的版本需要与SpringCloud版本适配。
在这里插入图片描述

3.1 创建注册中心服务 eureka-server
打开 idea,File --> New -->Project --> Spring initializr
在这里插入图片描述
填好包名和项目名
在这里插入图片描述
选好SpringBoot的版本,选择服务注册依赖,Next之后就 finish。
在这里插入图片描述
编写 application.yml 配置文件

server:
  port: 8761
eureka:
  instance:
    hostname: localhost #服务名
  client:
    register-with-eureka: false # 是服务端,不向注册中心注册自己的信息
    fetch-registry: false # 是服务端,不向注册中心拉取自己的信息
    service-url: # 注册中心地址
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/

在主程序入口 EurekaServerApplication,使用@EnableEurekaServer开启 eureka 服务端

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

打开浏览器访问:http://localhost:8761/
在这里插入图片描述
Application:No instances available
指的是没有可用服务注册进来

3.2 创建商品服务 product_service
3.2.1 FIle --> New --> Project --> Spring initializr
填写包名和项目名
在这里插入图片描述
3.2.2 添加 Spring Web、eureka client 客户端依赖
在这里插入图片描述
3.2.3 创建 controller、service、serviceImpl、domain 这些包
3.2.4 在 domain 下编写 Product 实体类

/**
 * 商品实体类
 * @author 药岩
 * @date 2020/3/21
 */
public class Product implements Serializable {

    public Product() {
    }

    public Product(int id, String name, int price, int store) {
        this.id = id;
        this.name = name;
        this.price = price;
        this.store = store;
    }

    private int id;
    /**
     * 商品名称
     */
    private String name;
    /**
     * 商品价格
     */
    private int price;
    /**
     * 商品库存
     */
    private int store;
    
    此处 get、set 方法...
}

3.2.5 编写 ProductService 接口

public interface ProductService {

    List<Product> listProduct();

    Product findById(int id);
}

3.2.6 编写 ProductServiceImpl 实现类,基于内存操作,暂时不连接 数据库。

/**
 * ProductServiceImpl 实现类
 * @author 药岩
 * @date 2020/3/21
 */
@Service
public class ProductServiceImpl implements ProductService {

    private static Map<Integer, Product> mapDao = new HashMap<>();

    static {
        Product product1 = new Product(1, "iphone11", 5999, 10);
        Product product2 = new Product(2, "ipad Pro", 6999, 12);
        Product product3 = new Product(3, "MacBook Pro", 17999, 14);
        Product product4 = new Product(4, "洗衣机", 8999, 15);
        Product product5 = new Product(5, "小爱同学", 299, 10);
        Product product6 = new Product(6, "冰箱", 3999, 10);
        Product product7 = new Product(7, "电视", 3999, 10);
        mapDao.put(1, product1);
        mapDao.put(2, product2);
        mapDao.put(3, product3);
        mapDao.put(4, product4);
        mapDao.put(5, product5);
        mapDao.put(6, product6);
        mapDao.put(7, product7);

    }
    
	/**
	 * 获取全部商品列表
	 * @author 药岩
	 * @date 2020/3/21
	 */
    @Override
    public List<Product> listProduct() {
        Collection<Product> collection = mapDao.values();
        List<Product> list = new ArrayList<>(collection);
        return list;
    }

	/**
	 * 根据id获取商品
	 * @author 药岩
	 * @date 2020/3/21
	 */
    @Override
    public Product findById(int id) {
        return mapDao.get(id);
    }
}

3.2.7 在controller 包下,编写 ProductController 控制层

@RestController
@RequestMapping(value = "/api/v1/product")
public class ProductController {

    @Autowired
    private ProductService productService;

	/**
	 * 获取全部商品列表
	 * @author 药岩
	 * @date 2020/3/21
	 */
     @RequestMapping(value = "list")
    public List<Product> listProduct(){
        return productService.listProduct();
    }
    
	/**
	 * ProductServiceImpl 实现类
	 * @author 药岩
	 * @date 2020/3/21
	 */
    @RequestMapping(value = "find")
    public Product findById(@RequestParam("id") int id){
        return productService.findById(id);
    }
}

启动 product_service 项目,确保项目没有问题,浏览器访问:http://localhost:8080/api/v1/product/list
在这里插入图片描述
3.2.8 编写 product_service 项目的 application.yml

server:
  port: 8771
  
spring:
  application:
    name: product-service # 服务名称
    
eureka:
  client:
    service-url: # 指定注册中心地址,往注册中心注册
      defaultZone: http://localhost:8761/eureka/

3.2.9 先启动eureka_server项目 再启动 product_service 项目
访问 eureka_server 打开浏览器:http://localhost:8761/
在这里插入图片描述
可以看到,product-service 服务已经注册到 注册中心去了。
再添加一个 product-service 服务,端口为 8772
在这里插入图片描述
这里的 single instance only 指只能有单个服务实例,把它默认勾选去掉,添加一个端口为8772的product-service 服务
在这里插入图片描述
直接点击运行来启动项目
在这里插入图片描述
再访问 注册中心可以发现有8771、8772 两个端口服务,达到集群模式。
在这里插入图片描述
注意:
上图红色英文是eureka的自我保护模式,当这个模式开启时,如果 product-service 服务由于网络原因无法上报自己的地址和端口时,eureka 并不会将它移除,而把这个自我保护模式关闭后,如果由于网络抖动无法上报,则会把该服务移除。(不建议关闭)
如需要关闭,则配置文件配置以下内容:

# 关闭自我保护模式
eureka:
  server:
    enable-self-preservation: false

问题:
为什么 product-service 在配置文件指定注册中心地址就能注册,而不需要在主程序入口添加 @EnableEurekaClient 注解呢?

@SpringBootApplication
@EnableEurekaClient //可以不需要加这个注解
public class ProductServiceApplication {

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

}

官方文档解释:如果你这个依赖在这个类路径下的会自动去注册,所以不需要添加 @EnableEurekaClient 注解。
在这里插入图片描述

发布了29 篇原创文章 · 获赞 43 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/CSDN_Qiang17/article/details/104980277