遗留问题:前面提到即使通过配置来使消费者指向提供者的服务,当提供者位置改变。消费者就要修改并重新部署,非常不方便。这就需要一个强大的服务发现机制,消费者可通过该机制获取服务提供者的网络信息——服务发现组件就提供了这种服务!
1、提供者、消费者和服务发现组件三者的关系
- 各微服务启动时,将自己的网络信息注册到服务发现组件中
- 服务消费者可以从发现组件中获取提供者的网络地址,并调用服务
- 各微服务与发现组件使用一定的机制(如心跳机制)通信。若发现组件长时间无法与微服务通信,则注销该实例
- 微服务地址发生变更会重新注册到发现组件。。所以就无需人工修改消费者的配置了。
1.1、服务发现组件具备的功能
- 服务注册表——核心,记录各微服务信息:名称、IP、端口等。查询API,管理API(用于服务注册和注销)
- 服务注册与发现——微服务启动时将自己的信息注册到发现组件;查询可用微服务列表及其网络地址
- 服务检查——如心跳机制长时间检查不到,注销该实例
1.2、常用服务发现组件
SpringCloud提供了多种服务发现组件的支持,如Eureka,Consul和Zookeeper等。该教程以Eureka为例,来讲解服务的注册与发现。
2、Eureka简介
Eureka集成在SpringCloud的子项目SpringCloudNetflix中,基于REST服务,包含server和client两部分。
2.1、Eureka原理
2.1.1、前提知识
AWS的Region和Availability Zone(亚马逊的概念,AWS——Amazon Web Service)
- Region表示AWS中的地理位置,下有多个Availability Zone;各个Region间相互隔离,相当于好多机房组成的一个集群
- Availability Zone就可理解为机房
2.1.2、Eureka架构
- Application Server 相当于服务提供者
- Application Client 相当于服务消费者
- Make Remote Call 相当于调用RESTful API的行为
- us-east-1c,us-east-1d,us-east-1e 都是Zone,都属于us-east-1这个Region
Eureka 包含两个组件Eureka Server 和Eureka Client
- Eureka Server 各个微服务启动时都会想Eureka Server注册自己的信息,存储
- Eureka Client 是Java客户端,简化与Eureka Server的交互
- 微服务启动后,会周期性(默认30s)向Eureka Server发送心跳,以续约“租期”
- 如果Eureka Server在一定时间内(默认90s)没有接收到某微服务的心跳,Eureka Server就会注销该实例
- 多个Eureka Server实例,互相通过复制的方式,实现注册表数据的同步
- Eureka Client会缓存服务注册表中的信息,缓解Server的压力;同时即使Server都挂掉了,client中的缓存依然能保证消费者可以调用到服务
2.2、编写Eureka Server
2.2.1、pom文件
<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.gome</groupId>
<artifactId>discovery-eureka</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</artifactId>
</dependency>
</dependencies>
<!-- 引入Spring Cloud依赖 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Camden.SR4</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>
2.2.2、编写启动类
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);
}
}
2.2.3、编写配置文件
server:
port: 8761
eureka:
client:
register-with-eureka: false
#表示是否将自己注册到Eureka Server,默认为true。由于当前应用就是Eureka Server,故而设为false
fetch-registry: false
#表示是否从Eureka Server获取注册信息,默认为true。因为这是一个单点的Eureka Server,不需要同步其他节点数据,故而false
service-url:
defaultZone: http://localhost:8761/eureka/
#设置Eureka Server交互的地址,查询服务和注册服务都需要依赖这个地址。
2.3、将微服务注册到Eureka Server上
在原来的服务提供项目provider-user项目基础上修改
2.3.1、pom文件
<!-- 添加Eureka服务发现组件 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
2.3.2、yml配置文件修改
spring:
application:
name: provider-user
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
instance:
prefer-ip-address: true #表示将自己的IP注册到Eureka Server,否则表示将所在服务器操作系统的hostname注册到Eureka Server
2.3.3、修改启动类
在启动类上添加@EnableDiscoveryClient注解,声明这是一个Eureka Client
@EnableDiscoveryClient
@SpringBootApplication
public class ProviderUserApplication {
也可以使用@EnableEurekaClient注解替代,但是@EnableDiscoveryClient更好一点,因为Spring Cloud中服务发现组件有很多种,如Zookeeper、Consul等,@EnableDiscoveryClient为各种服务组件都提供了支持。
同理,也可以把其他服务都这样注册到Eureka Server上。
2.4、Eureka Server的高可用
Eureka Server集群可以保证单个Eureka Server宕机造成的各类问题。构建多节点Eureka Server集群。(略)
2.5、Eureka Server添加用户认证
Eureka Server对应的项目中
2.5.1、pom文件中添加spring-boot-starter-security的依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
2.5.2、yml配置文件中添加以下配置
security:
basic:
enabled: true #开启基于HTTP basic的认证
user:
name: user #配置登录账号是user
password: password123 #配置登录密码时password123
2.5.3、供给方注册时认证
只需将yml配置中eureka.client.server-url.defaultZone配置为 http://user:password@Eureka_host:Eureka_port/eureka/
2.6、Eureka的元数据
Eureka的元数据有两种,分别是标准元数据和自定义元数据。
- 标准元数据指的是主机名、IP地址、端口号、状态页和健康检查等信息,都会注册在服务注册表中
- 自定义元数据可以使用eureka.instance.metadata-map配置,这些元数据可以在客户端中访问到,一般不改变客户端行为
2.7、Eureka Server的REST端点
就相当于Eureka Server暴露的一些接口,通过接口操作,可以操作Eureka
(一般不会这么用吧。。)
2.8、Eureka的自我保护模式
自我保护模式出现的场景——当由于网络原因造成,Eureka Server不能正常接口到服务提供方的心跳,默认超过90秒以后就会注销掉该实例。当Eureka Server节点在短时间内丢失过多客户端时,会自动进入该模式。一旦进入该模式,注册表中的信息不再被删除。故障恢复后会自动退出该模式。
(这个功能貌似没有太大意义,丢过得也丢了,只是把丢失服务数量尽可能最小化)
2.9、多网卡环境下的IP选择
可以通过配置,将指定网卡信息忽略,将用的到的网卡信息注册到Eureka Server中(具体过程略)
2.10、Eureka的健康检查
直接通过Eureka Server项目中配置的eureka.client.service-url中的地址,就可以从网页端查看当前注册的服务的状态,Status状态栏有UP\DOWN、OUT_OF_SERVICE、UNKNOWN,只有当Status是UP时,微服务才能被正常访问到。
也可以通过/health接口来获取对应信息。