- Java工程师的进阶之路
- 1 - SpringCloud简介与工程构建
- 2 - 服务注册中心:Eureka、Zookeeper、Consul
- 3 - 服务负载均衡:Ribbon
- 4 - 服务接口调用:OpenFeign
- 5 - 服务的断路器:Hystrix
- 6 - 服务的路由器:GateWay
- 7 - 服务配置中心:SpringCloud Config
- 8 - 服务消息驱动:SpringCloud Stream
- 9 - 服务链路跟踪:SpringCloud Sleuth
四、Eureka
4.1、简介
- 什么是服务治理
Spring Cloud封装了Netflix 公司开发的Eureka模块来实现服务治理
在传统的RPC远程调用框架中,管理每个服务与服务之间依赖关系比较复杂,管理比较复杂,所以需要使用服务治理,管理服务于服务之间依赖关系,可以实现服务调用、负载均衡、容错等,实现服务发现与注册。
- 什么是服务注册与发现
Eureka采用了CS的设计架构,Eureka Sever作为服务注册功能的服务器,它是服务注册中心。而系统中的其他微服务,使用Eureka的客户端连接到 Eureka Server并维持心跳连接。这样系统的维护人员就可以通过Eureka Server来监控系统中各个微服务是否正常运行。
在服务注册与发现中,有一个注册中心。当服务器启动的时候,会把当前自己服务器的信息比如服务地址通讯地址等以别名方式注册到注册中心上。另一方(消费者服务提供者),以该别名的方式去注册中心上获取到实际的服务通讯地址,然后再实现本地RPC调用RPC远程调用框架核心设计思想:在于注册中心,因为使用注册中心管理每个服务与服务之间的一个依赖关系(服务治理概念)。在任何RPC远程框架中,都会有一个注册中心存放服务地址相关信息(接口地址)
Eureka包含两个组件:Eureka Server和Eureka Client
Eureka Server
提供服务注册服务
各个微服务节点通过配置启动后,会在EurekaServer中进行注册,这样EurekaServer中的服务注册表中将会存储所有可用服务节点的信息,服务节点的信息可以在界面中直观看到。
EurekaClient
通过注册中心进行访问
它是一个Java客户端,用于简化Eureka Server的交互,客户端同时也具备一个内置的、使用轮询(round-robin)负载算法的负载均衡器。在应用启动后,将会向Eureka Server发送心跳(默认周期为30秒)。如果Eureka Server在多个心跳周期内没有接收到某个节点的心跳,EurekaServer将会从服务注册表中把这个服务节点移除(默认90秒)
4.2、搭建单机Eureka服务
4.2.1、搭建服务注册中心模块
最终效果
1、创建名为cloud-eureka-server7001
的Maven工程
2、改POM
这个是适配cloud最新版本的服务注册中心
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<dependencies>
<!--eureka-server-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</art
</dependency>
<!-- 引入自己定义的api通用包,可以使用Payment支付Entity -->
<dependency>
<groupId>com.laptoy.springcloud</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!--boot web actuator-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--一般通用配置-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
</dependencies>
3、写YML
server:
port: 7001
eureka:
instance:
hostname: locathost #eureka服务端的实例名称
client:
# false表示不向注册中心注册自己。
register-with-eureka: false
# false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
fetch-registry: false
service-url:
# 设置与Eureka server交互的地址查询服务和注册服务都需要依赖这个地址。
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
4、主程序类
@EnableEurekaServer
:开启服务注册功能
@SpringBootApplication
@EnableEurekaServer
public class EurekaMain7001 {
public static void main(String[] args) {
SpringApplication.run(EurekaMain7001.class, args);
}
}
5、测试:访问http://localhost:7001
4.2.2、注册提供者微服务8001
1.修改cloud-provider-payment8001
2.添加依赖(服务客户端依赖)
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
3、添加YML(服务客户端配置)
eureka:
client:
# 表示是否将自己注册进Eureka server默认为true。
register-with-eureka: true
# 是否从EurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡
fetchRegistry: true
service-url:
defaultZone: http://localhost:7001/eureka
4、主启动类
添加@EnableEurekaClient
:开启服务客户端功能
@SpringBootApplication
@EnableEurekaClient
public class PaymentMain001 {
public static void main(String[] args) {
SpringApplication.run(PaymentMain001.class, args);
}
}
5、测试
1、启动
cloud-provider-payment8001、cloud-eureka-server7001
2、访问localhost:7001
4.2.3、注册消费者微服务80
1.修改cloud-consumer-order80
2.添加依赖(服务客户端依赖)
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
3.添加YML(服务客户端配置)
eureka:
client:
# 表示是否将自己注册进Eurekaserver默认为true。
register-with-eureka: true
# 是否从EurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡
fetchRegistry: true
service-url:
defaultZone: http://localhost:7001/eureka
4、主启动
添加@EnableEurekaClient
:开启服务客户端功能
@SpringBootApplication
@EnableEurekaClient
public class OrderMain80
{
public static void main( String[] args ){
SpringApplication.run(OrderMain80.class, args);
}
}
5、测试
1、启动
cloud-provider-payment8001、cloud-eureka-server7001和cloud-consumer-order80
这三工程。
2、访问http://localhost:7001
4.3、搭建集群Eureka服务
4.3.1、集群简介
微服务RPC远程服务调用核心:高可用,试想你的注册中心只有一个,万一它出故障了,会导致整个为服务环境不可用。
解决方法:搭建Eureka注册中心集群,实现负载均衡+故障容错
互相注册,互相守望
4.3.2、集群构建步骤
1、构建第二台服务注册中心cloud-eureka-server7002
,模仿上文7001的配置,这里不在赘述
2、找到C:\Windows\System32\drivers\etc
路径下的hosts文件,修改映射配置添加进hosts文件
127.0.0.1 eureka7001.com
127.0.0.1 eureka7002.com
3、修改cloud-eureka-server7001
配置文件
server:
port: 7001
eureka:
instance:
hostname: eureka7001.com #eureka服务端的实例名称
client:
register-with-eureka: false #false表示不向注册中心注册自己。
fetch-registry: false #false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
service-url:
#集群指向其它eureka
defaultZone: http://eureka7002.com:7002/eureka/
#单机就是7001自己
#defaultZone: http://eureka7001.com:7001/eureka/
4、修改cloud-eureka-server7002
配置文件
server:
port: 7002
eureka:
instance:
hostname: eureka7002.com #eureka服务端的实例名称
client:
register-with-eureka: false #false表示不向注册中心注册自己。
fetch-registry: false #false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
service-url:
#集群指向其它eureka
defaultZone: http://eureka7001.com:7001/eureka/
#单机就是7002自己
#defaultZone: http://eureka7002.com:7002/eureka/
5、测试
4.3.3、注册客户端服务
将支付服务8001微服务,订单服务80微服务发布到上面2台Eureka集群配置中,修改这些服务的eureka配置
eureka:
client:
#表示是否将自己注册进Eurekaserver默认为true。
register-with-eureka: true
#是否从EurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡
fetchRegistry: true
service-url:
# 执行所有注册中心
defaultZone: http://eureka7001.com:7001/eureka, http://eureka7002.com:7002/eureka
7001注册中心
7002注册中心
访问消费者服务成功
4.4、搭建服务提供者集群
1、支付服务提供者8001、8002集群环境构建
参考cloud-provider-payment8001
1、新建
cloud-provider-payment8002
2、改POM
3、写YML - 端口8002
4、主启动
5、业务类
2、使用Ribbon实现负载均衡
1、cloud-consumer-order80
服务调用地址不能写死,面向服务名调用
@Slf4j
@RestController
public class OrderController {
//public static final String PAYMENT_URL = "http://localhost:8001";
public static final String PAYMENT_URL = "http://CLOUD-PAYMENT-SERVICE";
...
}
2、使用@LoadBalanced
注解赋予RestTemplate负载均衡的能力
@Configuration
public class ApplicationContextConfig {
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
3、访问http://localhost/consumer/payment/get/1
,负载均衡效果达到,8001、8002端口交替出现
4.5、actuator微服务信息完善
1、主机名称:服务名称修改(也就是将IP地址,换成可读性高的名字)
修改cloud-provider-payment8001,cloud-provider-payment8002
eureka:
instance:
instance-id: payment800x
2、访问信息增加IP信息提示
修改cloud-provider-payment8001,cloud-provider-payment8002
eureka:
instance:
prefer-ip-address: true
4.6、服务发现Discovery
对于注册进eureka里面的微服务,可以通过服务发现来获得该服务的信息
1、修改cloud-provider-payment8001
的Controller
import org.springframework.cloud.client.discovery.DiscoveryClient;
@RestController
@Slf4j
public class PaymentController{
...
@Resource
private DiscoveryClient discoveryClient;
...
@GetMapping(value = "/payment/discovery")
public Object discovery()
{
List<String> services = discoveryClient.getServices();
for (String element : services) {
log.info("*****element: "+element);
}
List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");
for (ServiceInstance instance : instances) {
log.info(instance.getServiceId()+"\t"+instance.getHost()+"\t"+instance.getPort()+"\t"+instance.getUri());
}
return this.discoveryClient;
}
}
2、主启动类
@EnableDiscoveryClient
:开启服务发现
@SpringBootApplication
@EnableEurekaClient
@EnableDiscoveryClient
public class PaymentMain001 {
public static void main(String[] args) {
SpringApplication.run(PaymentMain001.class, args);
}
}
访问
http://localhost:8001/payment/discovery
测试结果
4.7、Eureka自我保护理论知识
1、概述
-
保护模式主要用于一组客户端和Eureka Server之间存在网络分区场景下的保护。一旦进入保护模式,Eureka Server将会尝试保护其服务注册表中的信息,不再删除服务注册表中的数据,也就是不会注销任何微服务。
-
EMERGENCY! EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ARE UP WHEN THEY’RE NOT. RENEWALS ARE LESSER THANTHRESHOLD AND HENCE THE INSTANCES ARE NOT BEING EXPIRED JUSTTO BE SAFE
-
即某时刻某一个微服务不可用了,Eureka不会立刻清理,依旧会对该微服务的信息进行保存。
2、导致原因
- 一句话:某时刻某一个微服务不可用了,Eureka不会立刻清理,依旧会对该微服务的信息进行保存
- 属于CAP里面的AP分支
3、为什么会产生Eureka自我保护机制?
- 为了EurekaClient可以正常运行,防止与EurekaServer网络不通情况下,EurekaServer不会立刻将EurekaClient服务剔除
4、什么是自我保护模式?
- 默认情况下,如果EurekaServer在一定时间内没有接收到某个微服务实例的心跳,EurekaServer将会注销该实例(默认90秒)。但是当网络分区故障发生(延时、卡顿、拥挤)时,微服务与EurekaServer之间无法正常通信,以上行为可能变得非常危险了——因为微服务本身其实是健康的,此时本不应该注销这个微服务。Eureka通过“自我保护模式”来解决这个问题——当EurekaServer节点在短时间内丢失过多客户端时(可能发生了网络分区故障),那么这个节点就会进入自我保护模式。
5、自我保护机制∶默认情况下EurekaClient定时向EurekaServer端发送心跳包
- 如果Eureka在server端在一定时间内(默认90秒)没有收到EurekaClient发送心跳包,便会直接从服务注册列表中剔除该服务,但是在短时间( 90秒中)内丢失了大量的服务实例心跳,这时候Eurekaserver会开启自我保护机制,不会剔除该服务(该现象可能出现在如果网络不通但是EurekaClient为出现宕机,此时如果换做别的注册中心如果一定时间内没有收到心跳会将剔除该服务,这样就出现了严重失误,因为客户端还能正常发送心跳,只是网络延迟问题,而保护机制是为了解决此问题而产生的)。
6、在自我保护模式中,Eureka Server会保护服务注册表中的信息,不再注销任何服务实例。
-
它的设计哲学就是宁可保留错误的服务注册信息,也不盲目注销任何可能健康的服务实例。一句话讲解:好死不如赖活着。
-
综上,自我保护模式是一种应对网络异常的安全保护措施。它的架构哲学是宁可同时保留所有微服务(健康的微服务和不健康的微服务都会保留)也不盲目注销任何健康的微服务。使用自我保护模式,可以让Eureka集群更加的健壮、稳定。
4.8、关闭自我保护模式
1、使用eureka.server.enable-self-preservation = false
可以禁用自我保护模式
eureka:
...
server:
#关闭自我保护机制,保证不可用服务被及时踢除
enable-self-preservation: false
eviction-interval-timer-in-ms: 2000
关闭后主页会显示:
THE SELF PRESERVATION MODE IS TURNED OFF. THIS MAY NOT PROTECT INSTANCE EXPIRY IN CASE OF NETWORK/OTHER PROBLEMS.
2、生产者客户端eureakeClient端8001配置eureka配置
eureka:
...
instance:
instance-id: payment8001
prefer-ip-address: true
#心跳检测与续约时间
#开发时没置小些,保证服务关闭后注册中心能即使剔除服务
#Eureka客户端向服务端发送心跳的时间间隔,单位为秒(默认是30秒)
lease-renewal-interval-in-seconds: 1
#Eureka服务端在收到最后一次心跳后等待时间上限,单位为秒(默认是90秒),超时将剔除服务
lease-expiration-duration-in-seconds: 2
3、测试
- 7001和8001都配置完成
- 先启动7001再启动8001
4、结果:先关闭8001,马上被删除了
五、Zookeeper
5.1、简介与安装
zookeeper是一个分布式协调工具,可以实现注册中心功能
zookeeper服务器取代Eureka服务器,zk作为服务注册中心
5.2、搭建服务提供者8004
1、新建名为cloud-provider-payment8004
的Maven工程
2、改POM
<dependencies>
<!-- SpringBoot整合Web组件 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency><!-- 引入自己定义的api通用包,可以使用Payment支付Entity -->
<groupId>com.laptoy.springcloud</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>${project.version}</version>
</dependency>
<!-- SpringBoot整合zookeeper客户端 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
<!--先排除自带的zookeeper3.5.3 防止与3.4.9起冲突-->
<exclusions>
<exclusion>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--添加zookeeper3.4.9版本-->
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.9</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
3、改YML
#8004表示注册到zookeeper服务器的支付服务提供者端口号
server:
port: 8004
#服务别名----注册zookeeper到注册中心名称
spring:
application:
name: cloud-provider-payment
cloud:
zookeeper:
connect-string: 120.76.55.55:2181
4、主启动类
@SpringBootApplication
@EnableDiscoveryClient
public class PaymentMain8004 {
public static void main(String[] args) {
SpringApplication.run(PaymentMain8004.class, args);
}
}
5、控制层
import org.springframework.beans.factory.annotation.Value;
import java.util.UUID;
@RestController
@Slf4j
public class PaymentController {
@Value("${server.port}")
private String serverPort;
@RequestMapping(value = "/payment/zk")
public String paymentzk() {
return "springcloud with zookeeper: " + serverPort + "\t" + UUID.randomUUID().toString();
}
}
6、启动8004注册进zookeeper(要先启动zookeeper的server)
1、关闭防火墙
2、进入zookeepper bin目录
3、开启服务./zkServer.sh start
4、开启客户端连接./zkCli.sh
7、测试
浏览器 -
http://localhost:8004/payment/zk
接着用zookeeper客户端操作
5.3、节点情况
ZooKeeper的服务节点是临时节点,没有Eureka那含情脉脉。
5.4、搭建服务消费者80
1、新建cloud-consumerzk-order80
2、改POM
<dependencies>
<!-- SpringBoot整合Web组件 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- SpringBoot整合zookeeper客户端 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
<!--先排除自带的zookeeper-->
<exclusions>
<exclusion>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--添加zookeeper3.4.9版本-->
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.9</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
3、改YML
server:
port: 80
#服务别名----注册zookeeper到注册中心名称
spring:
application:
name: cloud-consumer-order
cloud:
zookeeper:
connect-string: 120.76.55.55:2181
4、主启动
@SpringBootApplication
@EnableDiscoveryClient
public class OrderZKMain80 {
public static void main(String[] args) {
SpringApplication.run(OrderZKMain80.class, args);
}
}
5、业务类
@Configuration
public class ApplicationContextConfig {
@Bean
@LoadBalanced
public RestTemplate getRestTemplate() {
return new RestTemplate();
}
}
@RestController
@Slf4j
public class OrderZKController {
public static final String INVOKE_URL = "http://cloud-provider-payment";
@Resource
private RestTemplate restTemplate;
@GetMapping(value = "/consumer/payment/zk")
public String paymentInfo()
{
String result = restTemplate.getForObject(INVOKE_URL+"/payment/zk",String.class);
return result;
}
}
6、测试
1、运行
ZooKeeper服务端
、cloud-consumerzk-order80
、cloud-provider-payment8004
2、打开ZooKeeper客户端:
7、访问测试
http://localhost/consumer/payment/zk
六、Consul
6.1、简介
Consul是一个服务网格解决方案,它提供了一个功能齐全的控制平面,具有服务发现、配置和分段功能。这些特性中的每一个都可以根据需要单独使用,也可以一起用于构建全服务网格。Consul需要一个数据平面,并支持代理和本机集成模型。Consul船与一个简单的内置代理,使一切工作的开箱即用,但也支持第三方代理集成,如Envoy。
Consul是一套开源的分布式服务发现和配置管理系统,由HashiCorp 公司用Go语言开发。
提供了微服务系统中的服务治理、配置中心、控制总线等功能。这些功能中的每一个都可以根据需要单独使用,也可以一起使用以构建全方位的服务网格,总之Consul提供了一种完整的服务网格解决方案。
它具有很多优点。包括:基于raft协议,比较简洁;支持健康检查,同时支持HTTP和DNS协议支持跨数据中心的WAN集群提供图形界面跨平台,支持Linux、Mac、Windows。
功能:
- 服务发现 - 提供HTTP和DNS两种发现方式。
- 健康监测 - 支持多种方式,HTTP、TCP、Docker、Shell脚本定制化
- KV存储 - Key、Value的存储方式
- 多数据中心 - Consul支持多数据中心
- 可视化Web界面
6.2、安装
1、Window版本官网下载:下载Amd64位压缩包
2、解压到自己的文件夹,这里演示放D:\environment\consul
文件夹中解压,解压完得到consul.exe
3、cmd后进入该文件夹执行consul agent -dev
启动(-dev表示开发模式运行,另外还有-server表示服务模式运行)
4、启动后访问:localhost:8500
6.3、搭建服务提供者8006
1、新建cloud-provider-payment8006
工程
2、改POM
<dependencies>
<!-- 引入自己定义的api通用包,可以使用Payment支付Entity -->
<dependency>
<groupId>com.laptoy.springcloud</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>${project.version}</version>
</dependency>
<!--SpringCloud consul-server -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
<!-- SpringBoot整合Web组件 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--日常通用jar包配置-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>RELEASE</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>RELEASE</version>
<scope>test</scope>
</dependency>
</dependencies>
3、改YML
server:
port: 8006
spring:
application:
name: consul-provider-payment
# consul注册中心地址
cloud:
consul:
host: localhost
port: 8500
discovery:
#hostname: 127.0.0.1
service-name: ${spring.application.name}
4、主启动类
@SpringBootApplication
@EnableDiscoveryClient
public class PaymentMain8006 {
public static void main(String[] args) {
SpringApplication.run(PaymentMain8006.class, args);
}
}
5、业务类
@RestController
@Slf4j
public class PaymentController {
@Value("${server.port}")
private String serverPort;
@RequestMapping(value = "/payment/consul")
public String paymentConsul() {
return "springcloud with consul: "+serverPort+"\t "+ UUID.randomUUID().toString();
}
}
6、测试
访问:
http://localhost:8006/payment/consul
访问:
http://localhost:8500
会显示cloud-provider-payment8006
6.4、搭建服务提供者80
1、新建cloud-consumerconsul-order80
工程
2、POM
<dependencies>
<!--SpringCloud consul-server -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
<!-- SpringBoot整合Web组件 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--日常通用jar包配置-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
3、YML
server:
port: 80
spring:
application:
name: cloud-consumer-order
# consul注册中心地址
cloud:
consul:
host: localhost
port: 8500
discovery:
# hostname: 127.0.0.1
service-name: ${spring.application.name}
4、主启动类
@SpringBootApplication
@EnableDiscoveryClient
public class OrderConsulMain80 {
public static void main(String[] args) {
SpringApplication.run(OrderConsulMain80.class, args);
}
}
5、业务类
配置类
@Configuration
public class ApplicationContextConfig {
@Bean
@LoadBalanced
public RestTemplate getRestTemplate() {
return new RestTemplate();
}
}
控制类
@RestController
@Slf4j
public class OrderConsulController {
public static final String INVOKE_URL = "http://consul-provider-payment";
@Resource
private RestTemplate restTemplate;
@GetMapping(value = "/consumer/payment/consul")
public String paymentInfo() {
String result = restTemplate.getForObject(INVOKE_URL+"/payment/consul",String.class);
return result;
}
}
6、测试
1、运行
consul,cloud-providerconsul-payment8006,cloud-consumerconsul-order80
2、访问
http://localhost:8500/
主页会显示出consul,cloud-providerconsul-payment8006,cloud-consumerconsul-order80服务
3、访问测试地址 - http://localhost/consumer/payment/consul
七、三个注册中心异同点
7.1、CAP概念
CAP理论的核心是:一个分布式系统不可能同时很好的满足一致性,可用性和分区容错性这三个需求,最多只能同时较好的满足两个。
- C:Consistency (强一致性)
- A:Availability (可用性)
- P:Partition tolerance (分区容错性)
因此,根据CAP原理将NoSQL数据库分成了满足CA原则、满足CP原则和满足AP原则三大类:
- CA - 单点集群,满足—致性,可用性的系统,通常在可扩展性上不太强大。
- CP - 满足一致性,分区容忍必的系统,通常性能不是特别高。
- AP - 满足可用性,分区容忍性的系统,通常可能对一致性要求低一些。
7.2、AP架构(Eureka)
当网络分区出现后,为了保证可用性,系统B可以返回旧值,保证系统的可用性。
结论:违背了一致性C的要求,只满足可用性和分区容错,即AP
7.3、CP架构(ZooKeeper/Consul)
当网络分区出现后,为了保证一致性,就必须拒接请求,否则无法保证一致性。
结论:违背了可用性A的要求,只满足一致性和分区容错,即CP。