Eureka组件
Eureka是Netfilx开源的服务发现组件,本身是一个基于rest的服务,它包含client和server两部分。
Spirng Cloud将它集成在子项目Spirng Cloud Netfilx中,从而实现服务的注册和发现
client注册到Server什么?
client注册后还会在本地做一个缓存,防止Server宕机后服务无法调用,如果提供服务的service宕机,此时调用不就出错了吗?所以要做Server的集群,后文会提到。
1.eureka中的server和client的介绍及特点
- Eureka Server:提供服务发现的能力,各个微服务启动时,会向Eureka Server注册自己的信息例如(IP,端口号,服务名称等),Eureka会存储这些信息。
- Eureka Client:是一个java的客户端用来简化Eureka Server的交互。
- 微服务启动后会周期性的(默认30秒)向Eureka Server发送心跳,如果Eureka在规定的时间没有收到心跳,则会注销该实例(默认90秒)。
- Eureka Client会缓存服务注册表中的信息。这种方式有一定的优势首先可以降低Eureka Server的压力,其次当所有的Eureka Server宕机服务调用方依然可以完成调用。
2.服务注册与服务发现
- 服务注册:当微服务client启动时,向Eureka Server发起注册,并上报该节点的相关信息
- 服务发现:client从Eureka Server获取注册信息,然后发起调用
3.Eureka Server开发
测试环境使用springcloud的Dalston版本。由IDEA快速构建出springboot项目,再引入相关依赖。
1.引入springcloud的相关依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--eureka server-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</artifactId>
</dependency>
</dependencies>
<!--依赖管理,所引入的jar都是没有版本号的,全部都是Dalston版本-->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Dalston.RC1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<!--仓库-->
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
2.入口类的开发
//启用EurekaServer
@EnableEurekaServer
@SpringBootApplication
public class EurekaServer {
public static void main(String[] args) {
SpringApplication.run(EurekaServer.class,args);
}
}
3.配置文件
eureka.client.service-url.defaultZone=http://localhost:8761/eureka
#不能向自身注册
eureka.client.register-with-eureka=false
#关闭自我发现
eureka.client.fetch-registry=false
#本实例名称
spring.application.name=eureka
#使用端口号
server.port=8761
注意:Eureka本身既是Server又是Client,作为Server不能向自身注册,自我发现关闭。
查看Server的状态,Eureka提供了一个web界面查看当前Server上的注册实例以及其他信息
地址:http://127.0.0.1:8761/
这里忘记截图了,假装没有实例注册,将就看下
2.Eureka Client的开发
1.jar包和Server不同
将spring-cloud-starter-eureka-server改为spring-cloud-starter-eureka
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
2.入口类
//该注解可以将client注册到以zookeeper为server的服务中心
@EnableDiscoveryClient
//该注解注册到Eureka @EnableEurekaClient
@SpringBootApplication
public class HiApplication {
public static void main(String[] args) {
SpringApplication.run(HiApplication.class, args);
}
}
3.配置文件
#指定Eureka Server的地址
eureka.client.service-url.default-zone=http://localhost:8761/eureka
server.port=8762
spring.application.name=eureka-client
3.Eureka client之间的相互调用测试
准备两个client,一个作为消费者,一个作为服务者。
服务者
1.导入相关的jar
同上Client
2.入口类同上
3.配置文件
eureka.client.service-url.default-zone=http://localhost:8761/eureka
server.port=8762
spring.application.name=eureka-provider
编写一个作为测试用的Controller
@RestController
@RequestMapping("/test")
public class TestController {
@RequestMapping("/test1")
public String test(String name){
return "xixixi 8763 :"+name;
}
}
消费者
1.jar不变
2.入口类不变
3.配置文件
eureka.client.service-url.default-zone=http://localhost:8761/eureka
server.port=8763
spring.application.name=eureka-client
4.使用java配置RestTemplate
@Configuration
public class RestTemplateConf {
@Bean
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
}
关于RestTemplate的说明:类似于HTTPClient,在程序中发起http请求,RestTemplate是对HTTPClient的封装。
5.写个简单的控制器
@RestController
@RequestMapping("/query")
public class ClientController {
@Autowired
private RestTemplate restTemplate;
@RequestMapping("/test")
public String test(String name){
String template = restTemplate.getForObject("http://EUREKA-PROVIDER/test/test1?name=" + name, String.class);
return template;
}
}
方法说明:getForObject("http://EUREKA-PROVIDER/test/test1?name=" + name, String.class); EUREKA-PROVIDER是注册过的实例名称,可以在Eureka Server的web界面看到的,大小写都可以,是有对应的映射的地址的。
6.测试
启动Eureka Server,两个Client,查看Eureka Server 中注册的实例是否有两个Client,两个则正常;
地址栏发起请求:http://localhost:8763/query/test?name=xixi
查看结果调用成功。
4.Eureka的自我保护机制
Eureka进入自我保护机制的最直接体现,是Eureka首页输出警告如图:
默认情况下,如果Eureka Server在一定时间内没有接受到服务实例的心跳,Eureka将会注销该实例(默认90秒).但是当网络分区发生故障时,微服务和Eureka Server 无法正常通信.以上行为可能变得特别危险了-因为微服务本身是健康的,此时不能注销该服务实例.
Eureka通过自我保护机制来解决这个问题,当Eureka Server在短时间丢失过多的服务实例(可能发生了网络分区的故障,那么这个节点进入自我保护模式,一旦进入此模式,Eureka Server将会保护服务注册表中的信息,不再删除服务注册表中的数据(也就是不再注销任何的服务实例),当网络故障恢复后,Eureka会自动退出自我保护模式。
综上,自我保护模式是一种应对网络故障的安全保护措施,它的架构哲学是宁可同时保留所有的微服务,也不盲目注销任何健康的微服务,使用自我保护模式可以让Eureka,更加健壮,稳定。
在springcloud中可以通过
#关闭自我保护机制 默认开启
eureka.server.enable-self-preservation=false
如果想及时剔除eureka的服务除了关闭自我保护机制外,可以调低eureka的心跳值
eureka-server服务端
配置文件中添加如下配置
#关闭保护机制,以确保注册中心将不可用的实例正确剔除
eureka.server.enable-self-preservation=false
#(代表是5秒,单位是毫秒,清理失效服务的间隔 )
eureka.server.eviction-interval-timer-in-ms=5000
客户端
配置文件中添加如下配置
# 心跳检测检测与续约时间
# 测试时将值设置设置小些,保证服务关闭后注册中心能及时踢出服务
# 配置说明
# lease-renewal-interval-in-seconds 每间隔10s,向服务端发送一次心跳,证明自己依然”存活“
# lease-expiration-duration-in-seconds 告诉服务端,如果我20s之内没有给你发心跳,就代表我“死”了,将我踢出掉。
eureka.instance.lease-renewal-interval-in-seconds=10
eureka.instance.lease-expiration-duration-in-seconds=20
5.client的高可用
搭建Client的集群十份简单,只需要保证实例名称一致,比如都叫做:client-provider,但是端口不能冲突。
保证端口号不一致(测试环境)
保证实例名一致!!!
示例配置
eureka.client.service-url.defaultZone=http://peer:8761/eureka
spring.application.name=eureka-provider
server.port=8764
eureka.client.service-url.defaultZone=http://peer:8761/eureka
spring.application.name=eureka-provider
server.port=8763
最终在Eureka Server的web界面可以看到如下一个集群
6.Eureka Server的高可用
单节点的Eureka Server 不适合线上的生产环境,Eureka Client会定时连接Eureka Server,获取服务注册表中的信息并缓存在本地,微服务消费远程API总是使用本地缓存的数据,因此一般来说既是Eureka Server发生宕机,也不会影响到服务的调用,但是如果Eureka Server宕机时某些微服务也出现了不可用的情况,Eurek Client中的缓存若不被更新,可能会影响到服务的调用,甚至影响到整个系统的高可用性,因此在生产环境会部署一个高可用的Eureka Server集群。
Eureka可以通过运行多个实例并互相注册实现高可用部署,Eureka Server实例会彼此同步信息。
Server1向Server2注册
server.port=8761
eureka.client.service-url.defaultZone=http://peer1:8765/eureka
eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false
eureka.instance.hostname=peer1
server.port=8762
eureka.client.service-url.defaultZone=http://peer:8761/eureka
eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false
spring.application.name=peer
注:peer是hosts映射本地127.0.0.1,http://peer1:8761/eureka,peer1作为Eureka复制集的名称
注意:在client注册到eureka server时 需要填写所有eureka server的地址
eureka.client.service-url.defaultZone=http://peer:8761/eureka,http://peer1:8765/eureka
7.Eureka的健康监测
服务有时候也会出现异常情况,我们也需要知道某个服务的健康状况。我们可以通过添加如下依赖,开启某个服务的健康检查。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
我们来访问一下这个接口http://localhost:port/health,看到了一个很简短的健康报告:
{"description":"Spring Cloud Eureka Discovery Client","status":"UP"}
类似的还有
- info 显示任意的应用信息
- metrics 展示当前应用的指标信息 true
- mappings 显示所有@RequestMapping路径的整理列表
- trace 显示trace信息(默认为最新的一些HTTP请求)
- health 展示应用的健康信息
- beans 显示一个应用中所有Spring Beans的完整列表
这其中有一些是敏感信息,出于安全考虑,一般用户无法访问,如果内网情况下可以
eureka.client.healthcheck.enabled=true
#关掉认证(公网下的生产环境不建议,内网部署可以)
management.security.enabled=false
8.http VS rpc
应用间通信方式主要是HTTP和RPC,在微服务架构中两大配方的主角分别是:
- Dubbo RPC框架
基于dubbo开发的应用还是要依赖周边的平台生态, 相比其它的RPC框架, dubbo在服务治理与服务集成上可谓是非常完善, 不仅提供了服务注册,发现还提供了负载均衡,集群容错等基础能力同时,还提供了面向开发测试节点的Mock和泛化调用等机制。 在spring cloud 出现之前dubbo在国内应用十分广泛,但dubbo定位始终是一个RPC框架。
- SpringCloud 微服务框架(HTTP通信)
Spring Cloud 的目标是微服务架构下的一栈式解决方案,自dubbo复活后dubbo官方表示要积极适配到spring cloud的生态方式,比如作为springcloud的二进制通信方案来发挥dubbo的性能优势,或者通过dubbo的模块化以及对http的支持适配到Spring Cloud,但是到目前为止dubbo与spring cloud 还是不怎么兼容,spring cloud 微服务架构下微服务之间使用http的RestFul方式进行通信,Http RestFul 本身轻量易用适用性强,可以很容易跨语言,跨平台,或者与已有的系统集成。