• 订单服务源码
    https:///Wasabi1234/SpringCloud_OrderDemo
  • 商品服务源码
  • https:///Wasabi1234/SpringCloud_ProductDemo


0 分布式下服务注册的地位和原理

0.1 分布式系统中为什么需要服务发现

Spring Cloud 微服务实战(三) - 服务注册与发现_Java

Spring Cloud 微服务实战(三) - 服务注册与发现_分布式_02

A 类比青楼中的嫖客, B 类比青楼女子,注册中心呢就相当于青楼中的妈咪

一般 嫖客服务一来,就肯定直接点名春花还是秋月呀,直接问妈咪要花魁就行

0.2 服务发现的两种方式

◆ 客户端发现

  • Eureka

◆ 服务端发现


  • Nginx
  • Zookeeper
  • Kubernetes

我们这里使用Eureka

◆ 基于Netflix Eureka做了二次封装

◆ 两个组件组成:


  • Eureka Server注册中心
  • Eureka Client服务注册

1 启动Eureka服务注册表

首先需要一个Eureka服务注册表。

使用Spring Cloud的@EnableEurekaServer来建立注册表,其他应用程序可以与之通信。

这是一个常规的Spring Boot应用程序,其中添加了一个注解(@EnableEurekaServer)以启用服务注册表。

Spring Cloud 微服务实战(三) - 服务注册与发现_SpringCloud_03

使用​​@EnableEurekaServer​

Spring Cloud 微服务实战(三) - 服务注册与发现_Java_04

就可以让应用变为Eureka服务器,这是因为spring boot封装了Eureka Server,让你可以嵌入到应用中直接使用

  • 直接运行成功如下
    Spring Cloud 微服务实战(三) - 服务注册与发现_架构_05

注册表启动时,它将抱怨(带有stacktrace)注册表没有可连接的副本节点。在生产环境中,需要多个注册表实例。

默认情况下,注册表还会尝试自行注册。

在本地使用此注册表时,最好将此注册表放在单独的端口上。



但不断报异常,why?
Spring Cloud 微服务实战(三) - 服务注册与发现_架构_06
这是因为该应用虽然是 Server 端,但也同时是 Client 端,也需要一个注册中心将自己注册进去
为消除其异常,修改下配置



配置需要注册的地址,也就是往自己身上注册
Spring Cloud 微服务实战(三) - 服务注册与发现_Java_07



通过观察源码,知道其实是一个 map, 所以配置如下
Spring Cloud 微服务实战(三) - 服务注册与发现_微服务_08
启动仍旧报错,其实正常问题,因为服务端自己又是 Server, 又是 Client, 服务端未启动完成时,客户端肯定是无法找到服务端的
但是 eureka 的服务端/客户端采用心跳通信方式
Spring Cloud 微服务实战(三) - 服务注册与发现_架构_09
可看到地址已随配置被改变



接下来配置实例名
Spring Cloud 微服务实战(三) - 服务注册与发现_架构_10



Spring Cloud 微服务实战(三) - 服务注册与发现_Java_11


  • 但是该应用本身就是个注册中心,不需要将其显示在注册实例中,通过以下配置
    Spring Cloud 微服务实战(三) - 服务注册与发现_SpringCloud_12
  • 为防止冲突,将端口号回改为默认
    Spring Cloud 微服务实战(三) - 服务注册与发现_Java_13
    Spring Cloud 微服务实战(三) - 服务注册与发现_微服务_14

2 服务中心

Spring Cloud 微服务实战(三) - 服务注册与发现_微服务_15



为避免每次手动启动,将应用打成 war 包(jar)
Spring Cloud 微服务实战(三) - 服务注册与发现_分布式_16Spring Cloud 微服务实战(三) - 服务注册与发现_SpringCloud_17Spring Cloud 微服务实战(三) - 服务注册与发现_Java_18
Spring Cloud 微服务实战(三) - 服务注册与发现_分布式_19
Spring Cloud 微服务实战(三) - 服务注册与发现_SpringCloud_20
Spring Cloud 微服务实战(三) - 服务注册与发现_SpringCloud_21



如此该应用就方便了我们,不需要每次都去手动启动应用,在后台会重启,若想杀死进程直接 kill
Spring Cloud 微服务实战(三) - 服务注册与发现_Java_22



3 Eureka Client的使用

Spring Cloud 微服务实战(三) - 服务注册与发现_微服务_23

  • ​@EnableDiscoveryClient​​​注解
    这通过​​​META-INF/spring.factories​​​查找​​DiscoveryClient​​​接口的实现
    Discovery Client的实现将在​​​org.springframework.cloud.client.discovery.EnableDiscoveryClient​​​键下的​​spring.factories​​​中添加一个配置类。
    ​​​DiscoveryClient​​​实现的示例是​​Spring Cloud Netflix Eureka​​​,​​Spring Cloud Consul发现​​​和​​Spring Cloud Zookeeper发现​​。

默认情况下,​​DiscoveryClient​​​的实现将使用远程发现服务器自动注册本地Spring Boot服务器。可以通过在​​@EnableDiscoveryClient​​​中设置​​autoRegister=false​​来禁用此功能。


  • 启动Server, 再启动 Client
    Spring Cloud 微服务实战(三) - 服务注册与发现_架构_24
  • 因为没有配置注册目标地址信息
    Spring Cloud 微服务实战(三) - 服务注册与发现_Java_25
  • 之后再次重启,依旧无法注册成功,几经勘察,添加以下依赖后,成功运行,注册到服务器
    Spring Cloud 微服务实战(三) - 服务注册与发现_分布式_26
  • 再指定 client 名字
    Spring Cloud 微服务实战(三) - 服务注册与发现_微服务_27
  • 发现成功注册
    Spring Cloud 微服务实战(三) - 服务注册与发现_SpringCloud_28
  • 此为 client 应用ip 地址
    Spring Cloud 微服务实战(三) - 服务注册与发现_微服务_29
  • 但其实可以自定义
    Spring Cloud 微服务实战(三) - 服务注册与发现_微服务_30
  • 接着点击进入那个链接,URL如下
    Spring Cloud 微服务实战(三) - 服务注册与发现_微服务_31
  • Eureka保证分布式CAP理论中的AP
    有时会发现如下红色警戒!
    Spring Cloud 微服务实战(三) - 服务注册与发现_微服务_32
    Eureka看明白了这一点,因此在设计时就​​优先保证可用性​​ 我们可以容忍注册中心返回的是几分钟以前的注册信息,但不能接受服务直接宕机。也就是说,​​服务注册功能对可用性的要求要高于一致性​​!

如果Eureka服务节点在短时间里丢失了大量的心跳连接(可能发生了网络故障),那么这个 Eureka节点会


  • 进入“自我保护模式”
    但该节点对于新的服务还能提供注册服务, 当网络故障恢复后,这个Eureka节点会退出“自我保护模式”
  • 同时保留那些“心跳死亡”的服务注册信息不过期
    对于“死亡”的仍然保留,以防还有客户端向其发起请求

​Eureka的哲学是,同时保留“好数据”与“坏数据”总比丢掉任何数据要更好​


  • 在开发模式,最好关闭该模式(默认是开启的),注意仅能在开发环境关闭哦!
  • 生产环境禁止关闭!!!
    Spring Cloud 微服务实战(三) - 服务注册与发现_分布式_33

4 Eureka的高可用

如果一台 eureka 宕机了咋办呢,为了实现高可用, 如果直接加一台服务器并无任何卵用,

4.1 考虑将两台 eureka 互相注册

Spring Cloud 微服务实战(三) - 服务注册与发现_Java_34


  • 复制得到两份 eureka,并以端口区分
    Spring Cloud 微服务实战(三) - 服务注册与发现_Java_35
  • 将 eureka1注册到 eureka2上并启动
    Spring Cloud 微服务实战(三) - 服务注册与发现_微服务_36
  • 将 eureka2注册到 eureka1上并启动
    Spring Cloud 微服务实战(三) - 服务注册与发现_分布式_37
    Spring Cloud 微服务实战(三) - 服务注册与发现_Java_38
    Spring Cloud 微服务实战(三) - 服务注册与发现_微服务_39

发现 client 在1,2同时都注册成功了!

假如此时 eureka1宕机了,会发生什么呢?

Spring Cloud 微服务实战(三) - 服务注册与发现_微服务_40



我们来将1给关闭
Spring Cloud 微服务实战(三) - 服务注册与发现_架构_41
Spring Cloud 微服务实战(三) - 服务注册与发现_架构_42



发现2依旧存活,并且 client 还在连接Spring Cloud 微服务实战(三) - 服务注册与发现_SpringCloud_43



若此时再 client 端重启又会发生什么呢?
Spring Cloud 微服务实战(三) - 服务注册与发现_分布式_44



因为无法注册,自然报错了, E2上也没有 client 端再连接了
Spring Cloud 微服务实战(三) - 服务注册与发现_SpringCloud_45



那么问题来了,怎么才能保证 E1宕机后, client 仍能注册在 E2上呢?只要保持每次都同时往两个 E 注册
Spring Cloud 微服务实战(三) - 服务注册与发现_架构_46



同理可得,当有3个 E 时,如此相互注册

Spring Cloud 微服务实战(三) - 服务注册与发现_分布式_47

Spring Cloud 微服务实战(三) - 服务注册与发现_架构_48

Spring Cloud 微服务实战(三) - 服务注册与发现_Java_49

  • 新建 E3
    Spring Cloud 微服务实战(三) - 服务注册与发现_架构_50
    Spring Cloud 微服务实战(三) - 服务注册与发现_架构_51
    Spring Cloud 微服务实战(三) - 服务注册与发现_微服务_52
    对于我们的本地开发环境,部署一个 E 即可,不再集群

5 Eureka总结

◆ @EnableEurekaServer @EnableEurekaClient

◆ 心跳检测、健康检查、负载均衡等功能

◆ Eureka的高可用,生产上建议至少两台以上

◆ ​​分布式系统中 ,服务注册中心是最重要的基础部分​

  • 结构图
    Spring Cloud 微服务实战(三) - 服务注册与发现_Java_53

参考

SpringCloud Finchley三版本微服务实战

互联网Java进阶面试训练营