Spring - Eureka 服务治理
微服务框架中核心基础模块,主要实现各个服务实例的自动注册与发现
搭建的主要配置
服务端:
pom.xml:[版本需要统计,详见最后的错误解决]
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka-server</artifactId> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Brixton.SR5</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
启动类:
@SpringBootApplication @EnableEurekaServer public class SpringBootTestEurekaServerApplication { public static void main(String[] args) { new SpringApplicationBuilder(SpringBootTestEurekaServerApplication.class).web(true).run(args); } }
配置文件:【application.properties】
server.port=1111 eureka.instance.hostname=localhost # 设置不像注册中心注册自己 eureka.client.register-with-eureka=false # 由于注册中心的职责就是维护服务实例,所以并不需要检索服务 eureka.client.fetch-registry=false eureka.client.service-url.defaultZone=http://${eureka.instance.hostname}:${server.port}/eureka/ # 服务续约任务的调用间隔时间 默认为30秒 eureka.instance.lease-renewal-intercal-in-seconds = 30 # 服务失效时间 默认90秒 eureka.instance.lease-expiration-duration-in-seconds = 90 # 备注: 保护机制:15分钟之内心跳失败比例是否低于85%,Eureka Server 将会保护注册实例,使之不会过期。 # 可以以此设置参数来关闭注册中心的自我保护功能,防止关闭的实例无法被服务注册中心剔除的问题 eureka.server.enable-self-preservation=false
客户端-注册服务提供者:
pom.xml:
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--Eureka【注册中心】 客户端--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> </dependency> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Brixton.SR5</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
启动类:
@EnableDiscoveryClient /*就是这个标签*/ @SpringBootApplication public class SpringBootTestApplication { public static void main(String[] args) { SpringApplication.run(SpringBootTestApplication.class, args); } }
配置文件:
# 服务名称 spring.application.name=hello-service # Eureka服务注册地址 eureka.client.service-url.defaultZone=http://localhost:1111/eureka/ # 实例名配置 # 由于默认的实例名称为InstanceInfo中的instanceID参数,其取值为主机名 ${*.hostname}:${*.name}:${*。instance_id}:${server.port} # 所以在本地使用一台本地进行启用多个服务实例时 会有端口冲突 # 解决1 (使用随机端口): sercer.port = ${random.int[10000,19999]} # 解决2 (直接修改实例名参数): # eureka.instance.instanceId = ${spring.application.name}:${random.int}
注册服务的/hello请求接口
@RestController public class HelloController { @Autowired private DiscoveryClient client; /*这个其实没有什么好修改的地方,只是↑DiscoveryClient可以取到服务实例清单*/ @RequestMapping("/hello") String index(){ ServiceInstance instance=client.getLocalServiceInstance(); System.out.println("hello host:"+ instance.getHost()+",service_id:"+instance.getServiceId()); System.out.println("test"); System.out.println(name); return "Hello World"; } }
客户端-服务发现与消费:
pom.xml:
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</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-ribbon</artifactId> </dependency> <!--↑主要内容↑--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot</artifactId> <version>1.2.6.RELEASE</version> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot</artifactId> </dependency> </dependencies> <!--↓主要内容↓--> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Brixton.SR5</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <!--↑主要内容↑-->
启动类:
/*注册为Eureka客户端应用*/ @EnableDiscoveryClient @SpringBootApplication public class SpringBootTestRibbonConsumerApplication { @Bean @LoadBalanced TestRestTemplate restTemplate(){ return new TestRestTemplate(); } public static void main(String[] args) { SpringApplication.run(SpringBootTestRibbonConsumerApplication.class, args); } }
配置文件:
spring.application.name=ribbon-consumer server.port=9000 eureka.client.service-url.defaultZone=http://localhost:1111/eureka/
服务调用使用类实现接口:
@RestController public class UsedHelloController { @Autowired RestTemplate restTemplate; @RequestMapping(value = "ribbon-consumer",method = RequestMethod.GET) public String helloConsumer(){ /*对,就是下面这个进行调用服务的实例接口*/ return restTemplate.getForEntity("http://hello-service/hello",String.class).getBody(); } }
OK 到这里 启动所有的服务就完成了,所有客户端会注册到Eureka中,调用/ribbon-consumer则会远程调用到服务提供的/hello接口。
一些参数等的说明
一些源码的实体类:
EurekaServerConfigBean 为Eureka的服务配置实体类
EurekaClientConfigBean 为Eureka的注册配置实体类
EurekaInstanceConfigBean 为Eureka的服务实例配置类
源码的实例关系:
不要在意箭头和判断(yes/no) (ノ`Д)ノ 太TM难画了
高可用配置:
eureka.client.service-url.defaultZone=http://peer1:1111/eureka/,http://peer2:1112/eureka/
#服务注册中心加入安全校验
http://<username>:<password>@localhost:1111/eureka
遇到的错误:启动错误
java.lang.IllegalStateException: ApplicationEventMulticaster not initialized - call 'refresh' before multicasting events via the context: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@66e417de: startup date [Fri Nov 24 15:18:34 CST 2017]; parent: org.springframework.context.annotation.AnnotationConfigApplicationContext@12d4172e
at org.springframework.context.support.AbstractApplicationContext.getApplicationEventMulticaster(AbstractApplicationContext.java:414) [spring-context-4.3.12.RELEASE.jar:4.3.12.RELEASE]
at org.springframework.context.support.ApplicationListenerDetector.postProcessBeforeDestruction(ApplicationListenerDetector.java:97) ~[spring-context-4.3.12.RELEASE.jar:4.3.12.RELEASE]
at org.springframework.beans.factory.support.DisposableBeanAdapter.destroy(DisposableBeanAdapter.java:253) ~[spring-beans-4.3.12.RELEASE.jar:4.3.12.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroyBean(DefaultSingletonBeanRegistry.java:578) [spring-beans-4.3.12.RELEASE.jar:4.3.12.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroySingleton(DefaultSingletonBeanRegistry.java:554) [spring-beans-4.3.12.RELEASE.jar:4.3.12.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.destroySingleton(DefaultListableBeanFactory.java:961) [spring-beans-4.3.12.RELEASE.jar:4.3.12.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroySingletons(DefaultSingletonBeanRegistry.java:523) [spring-beans-4.3.12.RELEASE.jar:4.3.12.RELEASE]
at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.destroySingletons(FactoryBeanRegistrySupport.java:230) [spring-beans-4.3.12.RELEASE.jar:4.3.12.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.destroySingletons(DefaultListableBeanFactory.java:968) [spring-beans-4.3.12.RELEASE.jar:4.3.12.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.destroyBeans(AbstractApplicationContext.java:1030) [spring-context-4.3.12.RELEASE.jar:4.3.12.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:556) [spring-context-4.3.12.RELEASE.jar:4.3.12.RELEASE]
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:122) [spring-boot-1.5.8.RELEASE.jar:1.5.8.RELEASE]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) [spring-boot-1.5.8.RELEASE.jar:1.5.8.RELEASE]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) [spring-boot-1.5.8.RELEASE.jar:1.5.8.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) [spring-boot-1.5.8.RELEASE.jar:1.5.8.RELEASE]
at org.springframework.boot.builder.SpringApplicationBuilder.run(SpringApplicationBuilder.java:134) [spring-boot-1.5.8.RELEASE.jar:1.5.8.RELEASE]
at com.example.demo.SpringBootTestEurekaServerApplication.main(SpringBootTestEurekaServerApplication.java:12) [classes/:na]
怎么就是启动不起来(ノ`Д)ノ
原因是版本没对上
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.8.RELEASE</version> <!-- 但是spring-cloud-dependencies 使用Brixton.SR5 -->
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Brixton.SR5</version> <!-- spring-boot 使用1.5.8的 -->
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
备注上Spring Cloud版本对应
Component | Angel.SR6 | Brixton.SR5 | Camden.M1 | Camden.BUILD-SNAPSHOT |
---|---|---|---|---|
spring-cloud-aws | 1.0.4.RELEASE | 1.1.1.RELEASE | 1.1.1.RELEASE | 1.1.2.BUILD-SNAPSHOT |
spring-cloud-bus | 1.0.3.RELEASE | 1.1.1.RELEASE | 1.2.0.M1 | 1.2.0.BUILD-SNAPSHOT |
spring-cloud-cli | 1.0.6.RELEASE | 1.1.5.RELEASE | 1.2.0.M1 | 1.2.0.BUILD-SNAPSHOT |
spring-cloud-commons | 1.0.5.RELEASE | 1.1.1.RELEASE | 1.1.1.RELEASE | 1.1.2.BUILD-SNAPSHOT |
spring-cloud-contract | 1.0.0.M2 | 1.0.0.BUILD-SNAPSHOT | ||
spring-cloud-config | 1.0.4.RELEASE | 1.1.3.RELEASE | 1.2.0.M1 | 1.2.0.BUILD-SNAPSHOT |
spring-cloud-netflix | 1.0.7.RELEASE | 1.1.5.RELEASE | 1.2.0.M1 | 1.2.0.BUILD-SNAPSHOT |
spring-cloud-security | 1.0.3.RELEASE | 1.1.2.RELEASE | 1.1.2.RELEASE | 1.1.3.BUILD-SNAPSHOT |
spring-cloud-starters | 1.0.6.RELEASE | |||
spring-cloud-cloudfoundry | 1.0.0.RELEASE | 1.0.0.RELEASE | 1.0.1.BUILD-SNAPSHOT | |
spring-cloud-cluster | 1.0.1.RELEASE | |||
spring-cloud-consul | 1.0.2.RELEASE | 1.1.0.M1 | 1.1.0.BUILD-SNAPSHOT | |
spring-cloud-sleuth | 1.0.6.RELEASE | 1.0.6.RELEASE | 1.0.7.BUILD-SNAPSHOT | |
spring-cloud-stream | 1.0.2.RELEASE | Brooklyn.M1 | Brooklyn.BUILD-SNAPSHOT | |
spring-cloud-zookeeper | 1.0.2.RELEASE | 1.0.2.RELEASE | 1.0.3.BUILD-SNAPSHOT | |
spring-boot | 1.2.8.RELEASE | 1.3.7.RELEASE | 1.4.0.RELEASE | 1.4.0.RELEASE |
spring-cloud-task | 1.0.2.RELEASE | 1.0.2.RELEASE | 1.0.3.BUILD-SNAPSHOT |
meaven 上的各个版本的东东【这个才是最新的】:
https://repo1.maven.org/maven2/org/springframework/cloud/spring-cloud-dependencies/
gethub 版本说明:
https://github.com/spring-projects/spring-cloud/wiki/Spring-Cloud-Edgware-Release-Notes
小杭 2017-12-04 (ノ`Д)ノ