一、简介
服务消费者需要一个强大的服务发现机制,服务消费者使用这种机制获取服务提供者的网络信息。即使服务提供者的信息发生变化,服务消费者也无须修改配置。
服务提供者、服务消费者、服务发现组件三者之间的关系大致如下:
1.各个微服务在启动时,将自己的网络地址等信息注册到服务发现组件中,服务发现组件会存储这些信息。
2.服务消费者可以从服务发现组件查询服务提供者的网络地址,并使用该地址调用服务提供者的接口。
3.各个微服务与服务发现组件使用一定机制(如:心跳)通信,服务发现组件如长时间无法与某微服务实例通信,就会注销该实例。
4.微服务网络地址发生变更时,会重新注册到服务发现组件。
1.1、服务发现组件
服务发现组件应具备以下功能:服务注册表、服务注册与服务发现、服务检查
1.1.1、服务注册表
是服务发现组件的核心,用来记录各个微服务的信息,如服务名称、IP、端口等。服务注册表提供查询API(用于查询可用的微服务实例)和管理API(用户服务的注册与注销)
1.1.2、服务注册与服务发现
服务注册是指微服务在启动时,将自己的信息注册到服务发现组件上的过程。服务发现是指查询可用微服务列表及其网络地址的机制。
1.1.3、服务检查
服务发现组件使用一定机制定时检测已注册的服务,如发现某实例长时间无法访问,就会从服务注册表中移除实例
Spring Cloud提供了多种服务发现组件的支持,如:Eureka、Zookeeper等。
二、Eureka
Eureka是Netflix开源的服务发现组件,本身是基于REST的服务。它包含Server和Client两部分。Spring Cloud将其集成在子项目Spring Cloud Netflix中,从而实现微服务的注册与发现。
2.1、编写Eureka Server
2.1.1 新建springboot工程
新建一个springboot(1.5.4.RELEASE)工程,再添加如下依赖:
<dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Dalston.SR1</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-config</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka-server</artifactId> </dependency> </dependencies>
2.1.2、编写启动类
package com.example.demo; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; @SpringBootApplication @EnableEurekaServer public class EurekaServerApplication { public static void main(String[] args) { SpringApplication.run(EurekaServerApplication.class, args); } }
2.1.3、配置文件application.properties
server.port=9090 eureka.client.register-with-eureka=false eureka.client.fetch-registry=false eureka.client.service-url.defaultZone=http://localhost:9090/eureka/,http://localhost:9090/eureka1/
说明:
eureka.client.register-with-eureka:表示是否将自己注册到Eureka Server,默认为true.(由于此工程本身就是Eureka Server,所有这里写false)
eureka.client.fetch-registry:表示是否从Eureka Server获取信息,默认为true(由于此工程现在是单节点的,所有这里写false)
eureka.client.service-url.defaultZone:设置与Eureka Server交互的地址,查询服务和注册服务都需要依赖这个地址,多个用逗号分隔
2.1.4、测试
2.2、将微服务注册到Eureka Server上
2.2.1 新建springboot工程
新建一个springboot(1.5.4.RELEASE)工程,再添加如下依赖:
<dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Dalston.SR1</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-config</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> </dependency> </dependencies>
2.2.2、编写启动类
package com.example.demo; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; @EnableEurekaClient @SpringBootApplication public class EurekaClientApplication { public static void main(String[] args) { SpringApplication.run(EurekaClientApplication.class, args); } }
2.2.3、配置文件application.properties
server.port=9091 spring.application.name=demo1 eureka.client.service-url.defaultZone=http://localhost:9090/eureka/ eureka.instance.prefer-ip-address=true
2.2.4、测试
如果在Eureka Server的首页看到以下这段提示,则说明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.
解决:显示指定ip
server.port=9091 spring.application.name=demo1 eureka.client.service-url.defaultZone=http://localhost:9090/eureka/ eureka.instance.prefer-ip-address=true #显示指定IP eureka.instance.instance-id: ${spring.cloud.client.ipAddress}:${server.port}