本博目录:
如何使用Spring Cloud搭建服务注册与发现模块。
这里我们会用到Spring Cloud Netflix,该项目是Spring Cloud的子项目之一,Eureka是Spring Cloud Netflix的一个子模块,也是核心模块之一。用于云端服务发现,一个基于REST的服务,用于定位服务,以实现云端中间层服务发现和故障转移。通过一些简单的注解,开发者就可以快速的在应用中使用Eureka。
Eureka 原理,如图所示:
由图可知,Eureka包括两个组件:Eureka Server 和Eureka Client
Eureka Server:提供服务发现的能力,客户端微服务启动时,会向Eureka Server注册自己的信息,EurekaServer 会存储这些信息。
Eureka Client:是一个Java客户端,和Eureka Server 进行交互。
注:微服务启动后,会周期性(30秒)向Eureka Server 发送心跳以续约自己的“租期”,如果Eureka Server在一定时间之内没有接收到某个服务的心跳,EurekaServer会注销该实例(90秒之内),综上,Eureka通过心跳检测。客户端缓存等机制,提高了系统的灵活性、可伸缩性。
创建一个基础的Spring Boot工程,并在pom.xml中引入需要的依赖:
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-eureka-serverartifactId>
dependency>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-dependenciesartifactId>
<version>Camden.SR6version>
<type>pomtype>
<scope>importscope>
dependency>
dependencies>
dependencyManagement>
通过@EnableEurekaServer注解启动一个服务注册中心,在Spring Boot应用启动类中添加这个注解就能开启此功能,如下:
@EnableEurekaServer
@SpringBootApplication
public class EurekaServerDemoApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerDemoApplication.class, args);
}
}
在默认设置下,该服务注册中心也会将自己作为客户端来尝试注册它自己,所以我们需要禁用它的客户端注册行为,只需要在application.properties中增加如下配置:
server.port=8671
## 是否将自己注册到Eureka Server 默认为true
eureka.client.register-with-eureka=false
## 是否从Eureka Server 获取注册信息,默认为true
eureka.client.fetch-registry=false
## 与Eureka server 交互的地址,查询服务和注册服务都需要这个地址,多个地址使用“,”分割
eureka.client.service-url.defaultZone=http://localhost:8671/eureka/
启动工程后,访问:http://localhost:8671/
首先,创建一个基本的Spring Boot应用,在pom.xml中,加入如下配置:
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-eurekaartifactId>
dependency>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-dependenciesartifactId>
<version>Camden.SR6version>
<type>pomtype>
<scope>importscope>
dependency>
dependencies>
dependencyManagement>
在主类中通过加上@EnableDiscoveryClient注解,该注解能激活Eureka中的DiscoveryClient实现,才能实现Controller中对服务信息的输出。
@EnableDiscoveryClient
@SpringBootApplication
public class EurekaClientDemoApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaClientDemoApplication.class, args);
}
}
application.properties项目配置:
##指定注册到Eureka Server上的应用名称
spring.application.name=compute-service
server.port=8672
eureka.client.serviceUrl.defaultZone=http://localhost:8671/eureka/
启动该工程后,再次访问:http://localhost:8671
结果如图所示:
在之前的例子中,Eureka Server 是允许匿名登录的。添加spring-boot-starter-security的依赖,使得Eureka Server需要登录才能访问
在pom文件中添加如下配置:
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-securityartifactId>
dependency>
配置文件中添加:
//开启基于HTTP basic的认证
security.basic.enabled=true
//登录账号和密码
security.user.name=chaole
security.user.password=chao1111
启动eureka Server ,如图输入账号和密码即可登录
默认情况下,如果Eureka Server在一定时间内没有接收到某个微服务实例的心跳,Eureka Server将会注销该实例(默认90秒)。但是当网络分区故障发生时,微服务与Eureka Server之间无法正常通信,这就可能变得非常危险了—-因为微服务本身是健康的,此时本不应该注销这个微服务。
Eureka Server通过“自我保护模式”来解决这个问题—-当Eureka Server节点在短时间内丢失过多客户端时(可能发生了网络分区故障),那么这个节点就会进入自我保护模式。一旦进入该模式,Eureka Server就会保护服务注册表中的信息,不再删除服务注册表中的数据(也就是不会注销任何微服务)。当网络故障恢复后,该Eureka Server节点会自动退出自我保护模式。
自我保护模式是一种对网络异常的安全保护措施。使用自我保护模式,而已让Eureka集群更加的健壮、稳定。
在Spring Cloud中,可以使用eureka.server.enable-self-preservation=false来禁用自我保护模式
—- — —— —— —- —– —–可参考《Spring cloud 与 docker 微服务架构实战》
在编写Eureka Server 时,出现了以下错误
org.springframework.beans.factory.BeanDefinitionStoreException: Failed to process import candidates for configuration class [com.swc.EurekaServerDemoApplication]; nested exception is java.lang.IllegalStateException: Failed to introspect annotated methods on class org.springframework.cloud.netflix.eureka.server.EurekaServerConfiguration
at org.springframework.context.annotation.ConfigurationClassParser.processImports(ConfigurationClassParser.java:616) ~[spring-context-4.3.11.RELEASE.jar:4.3.11.RELEASE]
at org.springframework.context.annotation.ConfigurationClassParser.doProcessConfigurationClass(ConfigurationClassParser.java:299) ~[spring-context-4.3.11.RELEASE.jar:4.3.11.RELEASE]
at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:245) ~[spring-context-4.3.11.RELEASE.jar:4.3.11.RELEASE]
at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:198) ~[spring-context-4.3.11.RELEASE.jar:4.3.11.RELEASE]
at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:167) ~[spring-context-4.3.11.RELEASE.jar:4.3.11.RELEASE]
at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:308) ~[spring-context-4.3.11.RELEASE.jar:4.3.11.RELEASE]
at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:228) ~[spring-context-4.3.11.RELEASE.jar:4.3.11.RELEASE]
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:270) ~[spring-context-4.3.11.RELEASE.jar:4.3.11.RELEASE]
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:93) ~[spring-context-4.3.11.RELEASE.jar:4.3.11.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:687) ~[spring-context-4.3.11.RELEASE.jar:4.3.11.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:525) ~[spring-context-4.3.11.RELEASE.jar:4.3.11.RELEASE]
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:122) ~[spring-boot-1.5.7.RELEASE.jar:1.5.7.RELEASE]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) [spring-boot-1.5.7.RELEASE.jar:1.5.7.RELEASE]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) [spring-boot-1.5.7.RELEASE.jar:1.5.7.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) [spring-boot-1.5.7.RELEASE.jar:1.5.7.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1118) [spring-boot-1.5.7.RELEASE.jar:1.5.7.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1107) [spring-boot-1.5.7.RELEASE.jar:1.5.7.RELEASE]
at com.swc.EurekaServerDemoApplication.main(EurekaServerDemoApplication.java:12) [classes/:na]
Caused by: java.lang.IllegalStateException: Failed to introspect annotated methods on class org.springframework.cloud.netflix.eureka.server.EurekaServerConfiguration
at org.springframework.core.type.StandardAnnotationMetadata.getAnnotatedMethods(StandardAnnotationMetadata.java:163) ~[spring-core-4.3.11.RELEASE.jar:4.3.11.RELEASE]
at org.springframework.context.annotation.ConfigurationClassParser.retrieveBeanMethodMetadata(ConfigurationClassParser.java:380) ~[spring-context-4.3.11.RELEASE.jar:4.3.11.RELEASE]
at org.springframework.context.annotation.ConfigurationClassParser.doProcessConfigurationClass(ConfigurationClassParser.java:314) ~[spring-context-4.3.11.RELEASE.jar:4.3.11.RELEASE]
at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:245) ~[spring-context-4.3.11.RELEASE.jar:4.3.11.RELEASE]
at org.springframework.context.annotation.ConfigurationClassParser.processImports(ConfigurationClassParser.java:606) ~[spring-context-4.3.11.RELEASE.jar:4.3.11.RELEASE]
... 17 common frames omitted
Caused by: java.lang.NoClassDefFoundError: org/springframework/boot/context/embedded/FilterRegistrationBean
at java.lang.Class.getDeclaredMethods0(Native Method) ~[na:1.8.0_131]
at java.lang.Class.privateGetDeclaredMethods(Class.java:2701) ~[na:1.8.0_131]
at java.lang.Class.getDeclaredMethods(Class.java:1975) ~[na:1.8.0_131]
at org.springframework.core.type.StandardAnnotationMetadata.getAnnotatedMethods(StandardAnnotationMetadata.java:152) ~[spring-core-4.3.11.RELEASE.jar:4.3.11.RELEASE]
... 21 common frames omitted
Caused by: java.lang.ClassNotFoundException: org.springframework.boot.context.embedded.FilterRegistrationBean
at java.net.URLClassLoader.findClass(URLClassLoader.java:381) ~[na:1.8.0_131]
at java.lang.ClassLoader.loadClass(ClassLoader.java:424) ~[na:1.8.0_131]
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:335) ~[na:1.8.0_131]
at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ~[na:1.8.0_131]
... 25 common frames omitted
最终才发现,是在pom文件中,spring cloud 的版本有误,我引入的版本是
这个版本对应的spring boot 版本 是 1.3.5.RELEASE 但我的spring boot 版本是1.5.7.RELEASE,最后修改springcloud版本到 Camden.SR6 即可。