[超级链接:Spring-Cloud学习序章]
翻译:Eureka [juəˈri:kə]
我发现了==>
服务注册中心,服务提供者
本章主要对服务注册中心Eureka组件进行学习,包括三个层次:
创建主工程spring-cloud-demo
,如何创建参考:Spring-Cloud笔记02:IDEA中构建多模块的Maven项目。
spring-cloud-demo
的pom.xml
内容如下:
<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.0modelVersion>
<groupId>pers.hanchaogroupId>
<artifactId>spring-cloud-demoartifactId>
<version>1.0-SNAPSHOTversion>
<modules>
<module>eureka-servermodule>
<module>eureka-himodule>
modules>
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>1.5.2.RELEASEversion>
<relativePath/>
parent>
<properties>
<project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8project.reporting.outputEncoding>
<java.version>1.8java.version>
<spring-cloud.version>Dalston.SR1spring-cloud.version>
<docker.image.prefix>hanchao5272docker.image.prefix>
properties>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-actuatorartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-eureka-serverartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-dependenciesartifactId>
<version>${spring-cloud.version}version>
<type>pomtype>
<scope>importscope>
dependency>
dependencies>
dependencyManagement>
<repositories>
<repository>
<id>spring-snapshotsid>
<name>Spring Snapshotsname>
<url>https://repo.spring.io/snapshoturl>
<snapshots>
<enabled>trueenabled>
snapshots>
repository>
<repository>
<id>spring-milestonesid>
<name>Spring Milestonesname>
<url>https://repo.spring.io/milestoneurl>
<snapshots>
<enabled>falseenabled>
snapshots>
repository>
repositories>
project>
创建子模块eureka-server
,如何创建参考:[Spring-Cloud笔记02:IDEA中构建多模块的Maven项目]。
编辑pom.xml
,如下:
<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.0modelVersion>
<groupId>pers.hanchao.springclouddemogroupId>
<artifactId>eureka-serverartifactId>
<version>0.0.1-SNAPSHOTversion>
<packaging>jarpackaging>
<name>eureka-servername>
<description>Demo project for Spring Cloud Eureka Serverdescription>
<parent>
<groupId>pers.hanchaogroupId>
<artifactId>spring-cloud-demoartifactId>
<version>1.0-SNAPSHOTversion>
<relativePath/>
parent>
project>
说明:对于服务注册中心来说,必不可少的组件是spring-cloud-starter-eureka-server
,继承自主工程。
在启动类EurekaServerApplication
上添加注解@EnableEurekaServer
,标识这是一个服务注册中心。
@EnableEurekaServer
@SpringBootApplication
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
默认生成的配置文件是application.properties
,我习惯性将其重命名为application.yml
,配置如下:
# 端口号
server:
port: 8761
# 服务注册相关配置
eureka:
# 服务实例主机名
instance:
hostname: localhost
# 服务提供者配置
client:
# 不进行注册(当服务注册中心是单点而非高考用时的配置方式)
registerWithEureka: false
# 不获取注册信息(当服务注册中心是单点而非高考用时的配置方式)
fetchRegistry: false
# 服务注册中心地址
serviceUrl:
defaultZone: http://${security.user.name}:${server.port}/eureka/
注意:
registerWithEureka: false
表示当前服务注册中心不在其他服务注册中心进行注册。fetchRegistry: false
表示当前服务注册中心不获取其他服务注册中心的注册信息。启动服务注册中心,在浏览器访问http://localhost:8761/,如下:
观察Instances currently registered with Eureka
部分,可以发现,目前没有可用的实例,表示还没有服务提供者注册到当前的服务注册中心。
创建子模块eureka-hi
,如何创建参考:[Spring-Cloud笔记02:IDEA中构建多模块的Maven项目]。
编辑pom.xml
,如下:
<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.0modelVersion>
<groupId>pers.hanchao.springclouddemogroupId>
<artifactId>eureka-hiartifactId>
<version>0.0.1-SNAPSHOTversion>
<packaging>jarpackaging>
<name>eureka-hiname>
<description>Demo project for Spring Cloud Eureka Clientdescription>
<parent>
<groupId>pers.hanchaogroupId>
<artifactId>spring-cloud-demoartifactId>
<version>1.0-SNAPSHOTversion>
<relativePath/>
parent>
project>
说明:对于服务提供者来说,必不可少的组件是spring-cloud-starter-eureka-server
,继承自主工程。
在启动类EurekaHiApplication
上添加注解@EnableEurekaClient
,标识这是一个服务提供者。
@RestController
@EnableEurekaClient
@SpringBootApplication
public class EurekaHiApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaHiApplication.class, args);
}
/** 获取端口号 */
@Value("${server.port}")
String port;
/**
* 定义一个简单接口
* @param name
* @return
*/
@GetMapping("/hi/{name}")
public String home(@PathVariable String name){
return "hi " + name + ",I am from port :" + port;
}
}
上述java类
中,还进行了以下编码:
@RestController
,相当于@Controller+@ResponseBody
,标识这个类对外提供Restful
风格的HTTP接口服务。@Value
获取配置文件application.yml
中的配置。@GetMapping("/hi")
对外提供一个GET
类型的接口。@PathVariable
来获取路径上的参数,从而形成RESTful
风格的请求路径。默认生成的配置文件是application.properties
,我习惯性将其重命名为application.yml
,配置如下:
# 服务端口号
server:
port: 8763
# 服务名称,即serviceId
spring:
application:
name: service-hi
# 服务注册与发现相关配置
eureka:
client:
# 服务注册地址
serviceUrl:
defaultZone: http://localhost:8761/eureka/
启动服务eureka-hi
,再次在浏览器访问http://localhost:8761/,如下:
观察Instances currently registered with Eureka
部分,可以发现,目前已经存在一个SERVICE-HI
的服务。
说明Eureka Client
确实注册到了Eureka Server
中心。
在浏览器访问http://localhost:8763/hi/david,得到如下结果:
说明Eureka Client
确实能够提供RESTful
风格的服务。
简单的服务注册中心Eureka Server与服务提供者Eureka Client的网络拓扑图,可以总结如下:
这种配置方式有以下致命缺陷:
所谓高可用,就是将微服务集群化,当其中一个节点挂掉之后,其他的节点还能够提供正常的功能。
高可用配置,可以在前一章节的基础上进行修改。
为了便于区分,本人重新创建了eureka-server-ha
和eureka-hi-ha
服务,其配置过程与前面章节一致。
先上Eureka Server的application.yml配置文件:
---
# 高可用节点1的配置
server:
port: 8771
spring:
# 节点1的标签
profiles: peer1
# 服务名保持一致
application:
name: eureka-ha
eureka:
instance:
hostname: peer1
client:
# 进行注册(高可用配置、默认配置)
# registerWithEureka: true
# 获取注册信息(高可用配置、默认配置)
# fetchRegistry: true
serviceUrl:
# 节点1向节点2/3进行服务注册
defaultZone: http://peer2:8772/eureka/,http://peer3:8773/eureka/
---
# 高可用节点2的配置
server:
port: 8772
spring:
# 节点2的标签
profiles: peer2
# 服务名保持一致
application:
name: eureka-ha
eureka:
instance:
hostname: peer2
client:
# 进行注册(高可用配置、默认配置)
# registerWithEureka: true
# 获取注册信息(高可用配置、默认配置)
# fetchRegistry: true
serviceUrl:
# 节点2向节点1/3进行服务注册
defaultZone: http://peer1:8771/eureka/,http://peer3:8773/eureka/
---
# 高可用节点3的配置
server:
port: 8773
spring:
# 节点3的标签
profiles: peer3
# 服务名保持一致
application:
name: eureka-ha
eureka:
instance:
hostname: peer3
client:
# 进行注册(高可用配置、默认配置)
# registerWithEureka: true
# 获取注册信息(高可用配置、默认配置)
# fetchRegistry: true
serviceUrl:
# 节点3向节点1/2进行服务注册
defaultZone: http://peer1:8771/eureka/,http://peer2:8772/eureka/
说明:
yml
文件中,通过---
来区分多个文件,减少配置文件个数。spring.application.name
相同。registerWithEureka: true
、fetchRegistry: true
。spring.profiles
,通过此标签来区分到底启动哪个配置页。驼峰命名
在Run/Debug Configurations
界面中,配置程序参数为--spring.profiles.active=peer1
。
然后运行,以此来启动节点1的服务,配置如下图所示。
分别配置--spring.profiles.active=peer2
、--spring.profiles.active=peer3
来启动另外两个服务。
在本例中,三个节点的port
分别是8771、8772、8773
,访问http://localhost:8771/,如下:
依次访问http://localhost:8772/、http://localhost:8773/,结果类似。
修改Eureka Client
的配置文件。
# 服务地址
server:
port: 8783
# 服务名称
spring:
application:
name: service-hi-ha
eureka:
client:
serviceUrl:
# 这里只需要执行其中一个服务注册中心节点即可
defaultZone: http://peer1:8771/eureka/
注意:
启动eureka-hi-ha
,然后刷新http://localhost:8771/,发现注册中心多了一个SERVICE-HI-HA
服务。
关闭服务节点peer1
,再次访问http://localhost:8771/,发现服务不可用,表示节点1真的宕机了。
访问http://localhost:8772/或者http://localhost:8773/,发现服务可用如下:
注意:
peer1
节点并没有立即从服务列表中消失,这是因为服务注册中心通过心跳
来检测服务是否存活。peer1
节点挂掉了,但是eureka-hi-ha
的注册信息在其他注册中心节点还是存在的。高可用的服务注册中心Eureka Server与服务提供者Eureka Client的网络拓扑图,可以总结如下:
当前其中任意节点宕机之后,其他节点上还保存着所有的服务注册信息。
无论前面的简单配置,还是高可用配置,都存在一个很低级的安全问题,那就是谁都可以进行服务注册。
为了解决这个问题,可以通过安全认证组件security
来进行配置。
本章节以1.简单配置
章节为基础进行修改。
修改pom.xml
添加security
组件:
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-securityartifactId>
dependency>
dependencies>
修改application.yml
# 端口号
server:
port: 8761
# 安全认证
security:
# 开启基本安全认证
basic:
enabled: true
# 设置用户名密码
user:
name: admin
password: admin
# 服务注册相关配置
eureka:
# 服务实例主机名
instance:
hostname: localhost
# 服务提供者配置
client:
# 不进行注册(当服务注册中心是单点而非高考用时的配置方式)
registerWithEureka: false
# 不获取注册信息(当服务注册中心是单点而非高考用时的配置方式)
fetchRegistry: false
# 服务注册中心地址
serviceUrl:
# 无安全认证的配置
# defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
# 安全认证的配置
defaultZone: http://${security.user.name}:${security.user.password}@${eureka.instance.hostname}:${server.port}/eureka/
无需修改pom.xml
修改application.yml
# 服务端口号
server:
port: 8763
# 服务名称,即serviceId
spring:
application:
name: service-hi
# 服务注册与发现相关配置
eureka:
client:
# 服务注册地址
serviceUrl:
# 无安全认证的配置
# defaultZone: http://localhost:8761/eureka/
# 安全认证配置
defaultZone: http://admin:admin@localhost:8761/eureka/
第一次测试:
依次启动服务eureka-server
和eureka-hi
,在浏览器访问:http://localhost:8761/,会出现以下输入框:
输入用户名admin
和密码admin
之后,进入注册中心。在注册中心,发现了SERVICE-HI
已经注册中心。
第二次测试:
关闭所有服务,关闭浏览器,修改Eureka Client的application.yml
,将defaultZone还原成http://localhost:8761/eureka/
。
依次启动服务eureka-server
和eureka-hi
,在浏览器访问:http://localhost:8761/,重新弹出安全认证输入框。
输入用户名admin
和密码admin
之后,进入注册中心。在注册中心,发现了SERVICE-HI
不在注册中心。
查看eureka-hi
的启动日志,发现报错:
2018-06-03 23:07:22.261 INFO 17504 --- [ main] com.netflix.discovery.DiscoveryClient : Getting all instance registry info from the eureka server
2018-06-03 23:07:22.341 WARN 17504 --- [ main] c.n.d.s.t.d.RetryableEurekaHttpClient : Request execution failure with status code 401; retrying on another server if available
2018-06-03 23:07:22.341 ERROR 17504 --- [ main] com.netflix.discovery.DiscoveryClient : DiscoveryClient_SERVICE-HI/DESKTOP-4J0FACQ:service-hi:8763 - was unable to refresh its cache! status = Cannot execute request on any known server
com.netflix.discovery.shared.transport.TransportException: Cannot execute request on any known server
at com.netflix.discovery.shared.transport.decorator.RetryableEurekaHttpClient.execute(RetryableEurekaHttpClient.java:111) ~[eureka-client-1.6.2.jar:1.6.2]
at com.netflix.discovery.shared.transport.decorator.EurekaHttpClientDecorator.getApplications(EurekaHttpClientDecorator.java:134) ~[eureka-client-1.6.2.jar:1.6.2]
at com.netflix.discovery.shared.transport.decorator.EurekaHttpClientDecorator$6.execute(EurekaHttpClientDecorator.java:137) ~[eureka-client-1.6.2.jar:1.6.2]
...
经测试,简单的安全认证配置成功。