如果直接在服务消费者项目指定服务提供者地址的话,会带来很多问题。比如
服务发现组件提供了解决以上问题的能力。
综上,服务发现组件应该具备以下功能:
服务发现组件的其它叫法:服务注册、服务发现或注册中心。Spring Cloud提供了多种服务发现组件的支持,例如Eureka、Consul和Zookeeper等。
Eureka是Netflix开源的服务发现组件,本身是一个基于REST的服务。它包含Server和Client两部分。
PS:Eureka 2.x已宣布闭源,不过可能是临时的。
Eureka包含两个组件:Eureka Server和Eureka Client,它们的作用如下:
Eureka通过心跳检查、客户端缓存等机制,提供了系统的灵活性、可伸缩性和可用性。
1)新建maven项目microservice-eureka,pom.xml文件引入spring boot、spring cloud和eureka-server的相关依赖。
4.0.0
cn.zhh
microservice-eureka
1.0
org.springframework.boot
spring-boot-starter-parent
2.0.1.RELEASE
org.springframework.cloud
spring-cloud-dependencies
Finchley.M7
pom
import
org.springframework.cloud
spring-cloud-starter-netflix-eureka-server
spring-milestones
Spring Milestones
https://repo.spring.io/libs-milestone
false
org.springframework.boot
spring-boot-maven-plugin
2)在application.yml加上以下配置。
## 服务端口
server:
port: 8080
eureka:
instance:
hostname: localhost
client:
## 因为该应用为注册中心,所以设置为false,代表不向注册中心注册自己
registerWithEureka: false
## 因为该应用为注册中心,职责就是维护服务实例信息,并不需要去检索服务,所以设置为false。
fetchRegistry: false
serviceUrl:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
3)启动类加上EnableEurekaServer注解。
@SpringBootApplication
@EnableEurekaServer
public class MicroserviceEurekaApplication {
public static void main(String[] args) {
SpringApplication.run(MicroserviceEurekaApplication.class, args);
}
}
4)启动项目,浏览器访问http://localhost:8080/,看到以下页面说明Eureka服务端运行成功。
1)新建maven项目microservice-provider,pom.xml文件引入spring boot、spring cloud和eureka-server的相关依赖。
4.0.0
cn.zhh
microservice-provider
1.0
org.springframework.boot
spring-boot-starter-parent
2.0.1.RELEASE
org.springframework.cloud
spring-cloud-dependencies
Finchley.M7
pom
import
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-test
test
org.springframework.cloud
spring-cloud-starter-netflix-eureka-client
spring-milestones
Spring Milestones
https://repo.spring.io/libs-milestone
false
org.springframework.boot
spring-boot-maven-plugin
2)在application.yml加上以下配置。主要是应用名(用于标记服务)、要注册到的Eureke注册中心地址。
server:
port: 8081
spring:
application:
name: provider-pay
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8080/eureka/
3)编写一个支付API的控制器。
@RestController
public class PayController {
@GetMapping("/pay")
public String pay() {
return "支付功能调用成功!";
}
}
4)在项目启动类加上EnableDiscoveryClient注解。
@SpringBootApplication
@EnableDiscoveryClient // 相当于服务发现组件的门面,也可以使用@EnableEurekaClient
public class MicroserviceProviderApplication {
public static void main(String[] args) {
SpringApplication.run(MicroserviceProviderApplication.class, args);
}
}
5)启动应用,可以看到服务已经注册到Eureka Server上了。
Eureka Client会定时连接Eureka Server,获取服务注册表中的信息并缓存在本地。微服务在消费远程API时总是使用本地缓存中的数据。因此一般来说,即使Eureka Server发生宕机,也不会影响到服务之间的调用。但如果Eureka Server宕机时,某些微服务也出现了不可用的情况,Eureka Client中的缓存若不被更新,就可能会影响到微服务的调用,甚至影响到整个应用系统的高可用性。因此,通常会部署一个高可用的Eureka Server集群。
Eureka Server可以通过运行多个实例并相互注册的方式实现高可用部署,Eureka Server实例会彼此增量地同步信息,从而确保所有节点数据一致。事实上,节点之间相互注册时Eureka Server的默认行为。
下面来构造一个双节点Eureka Server集群(3个节点、4个节点...也是类似的,只要将自己的节点都注册到别的节点上就可以了)。
1)配置系统的hosts,Windows系统的hosts文件路径是C:\Windows\System32\drivers\etc\hosts,Linux及Mac OS等系统的文件路径是/etc/hosts。
127.0.0.1 ha1 ha2
2)复制项目microservice-eureka两份,将artifactId分别修改为microservice-eureka-ha1和microservice-eureka-ha2。
3)分别将application.yml修改如下,让两个节点的Eureka Server相互注册。
## 服务端口
server:
port: 9081
eureka:
instance:
hostname: ha1
client:
## 因为该应用为注册中心,所以设置为false,代表不向注册中心注册自己
registerWithEureka: false
## 因为该应用为注册中心,职责就是维护服务实例信息,并不需要去检索服务,所以设置为false。
fetchRegistry: false
serviceUrl:
defaultZone: http://ha2:9082/eureka/
## 服务端口
server:
port: 9082
eureka:
instance:
hostname: ha2
client:
## 因为该应用为注册中心,所以设置为false,代表不向注册中心注册自己
registerWithEureka: false
## 因为该应用为注册中心,职责就是维护服务实例信息,并不需要去检索服务,所以设置为false。
fetchRegistry: false
serviceUrl:
defaultZone: http://ha1:9081/eureka/
4)启动两个项目,分别访问http://localhost:9081/和http://localhost:9082/,都可以看到registered-replicas拥有对方节点。
5)将应用注册到Eureka Server集群上。
以microservice-provider项目为例, 只需修改eureka.client.serviceUrl.defaultZone,配置多个Eureka Server地址,就可以将其注册到Eureka Server集群了。
eureka:
client:
serviceUrl:
defaultZone: http://localhost:9081/eureka/,http://localhost:9082/eureka/
其实,微服务即使只配置Eureka Server集群中的某个节点,也能正常注册到Eureka Server集群,因为多个Eureka Server之间的数据会相互同步。不过,避免某些极端场景,还是建议在客户端配置多个Eureka Server节点。
默认情况下,如果Eureka Server在一定时间内没有接收到某个微服务实例的心跳,Eureka Server将会注销该实例(默认90秒)。但是当网络分区故障发生时,微服务与Eureka Server之间无法正常通信,以上行为可能变得非常危险了——因为微服务本身其实是健康的,此时本不应该注销这个微服务。
Eureka通过“自我保护模式”来解决这个问题——当Eureka Server节点在短时间内丢失过多客户端时(可能发生了网络分区故障),那么这个节点就会进入自我保护模式。一旦进入该模式,Eureka就会保护服务注册表中的信息,不会删除服务注册表中的数据(也就是不会注销任何微服务)。当网络故障恢复后,该Eureka Server节点会自动推出自我保护模式。
可以将eureka.server.enable-self-preservation设置为false禁用自我保护模式(默认为true),一般在开发环境中使用。
Spring Cloud提供了按需选择IP的能力。
1、忽略指定名称的网卡
spring:
cloud:
inetutils:
ignored-interfaces:
- docker0
- vetch.*
这样就可以忽略docker0网卡以及所有以vetch开头的网卡。
2、使用正则表达式,指定使用的网络地址
spring:
cloud:
inetutils:
preferred-networks:
- 192.168
- 10.0
3、只使用站点本地地址
spring:
cloud:
inetutils:
use-only-site-local-interfaces: true
这样就可以强制使用站点本地地址。
4、手动指定IP地址
eureka:
instance:
prefer-ip-address: true
ip-address: 127.0.0.1
在Status一栏有个UP,表示应用程序状态正常。应用状态还有其它取值,例如DOWN、OUT_OF_SERVICE、UNKNOWN等。只有标记为“UP”的微服务会被请求。