SpringCloud-consul
一、RestTemplate
实现两个独立微服务之间的调用
提供多种便捷访问远程Http服务的方法,是一种简单便捷的访问restful服务模板类,是Spring提供的用于访问Rest服务的客户端模板工具集
方法:
getForObject 返回对象为响应体中数据转化成的对象,基本可以理解为Json
getForEntity 返回对象为ResponseEntity对象,包含了响应中的一些重要信息,比如响应头,响应状态码,响应体等 在方法后面再加一个getBody()
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
@Configuration
public class RestTemplateConfig {
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
二、consul 服务发现和配置管理系统
1.1为什么不再使用Eureka
-
停更难维护
-
对初学者不友好 ,首次看到自我保护机制
-
注册中心独立且和微服务功能解耦
-
阿里巴巴Nacos的崛起
1.2能干什么
-
服务发现 提供HTTP和DNS两种发现方式
-
健康检测 支持多种方式,HTTP,TCP,Docker,Shell
-
KV存储 Key,Value的存储方式
-
多数据中心 Consul支持多数据中心
-
可视化Web界面
1.3安装
如果出现上述图片,说明版本合适
使用开发者模式启动 consul agent -dev,通过http://localhost:8500可以访问首页
1.4在项目中使用
1.引入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
2.修改yml
spring:
cloud:
consul:
host: localhost
port: 8500
discovery:
service-name: ${spring.application.name} #照这个服务的名字
3.主启动
@EnableDiscoveryClient主启动类
4.修改RestTemplateCOnfig类
consul支持负载均衡,默认有多个集群,只通过微服务名字调用,出错,需加上@LoadBalanced
@Configuration
public class RestTemplateConfig {
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
1.5三个注册中心异同点
consistenct 强一致性 availability 可用性 partition tolerance 分区容错性
组件名 | 语言 | CAP | 服务健康检查 | 对外暴露接口 | Spring Cloud集成 |
---|---|---|---|---|---|
Eureka | Java | AP | 可配支持 | THHP | 已集成 |
Consul | Go | CP | 支持 | HTTP/DNS | 已集成 |
Zookeeper | Java | CP | 支持 | 客户端 | 已集成 |
AP架构:当网络分区出现后,为了保证可用性,系统B可以返回旧值,保证系统的可用性,当系统出现不一致时,虽然a,b上的注册信息不完全相同,但每个Eureka节点依然能够正常的对外提供服务,只会出现查询服务信息时如果请求a查不到,但请求b就能查到,如此保证了可用性但牺牲了一致性结论:违背了一致性c的要求,只需满足可用性和分区容错,即AP
CP架构: 当网络分区出现后,为了保证一致性,就必须拒接请求,否则无法保证一致性,Consul 遵循CAP原理中的CP原则,保证了强一致性和分区容错性,且使用的是Raft算法,比zookeeper使用的Paxos算法更加简单。虽然保证了强一致性,但是可用性就相应下降了,例如服务注册的时间会稍长一些,因为Consul的raft协议要求必须过半数的节点都写入成功才认为注册成功;在leader挂掉了之后,重新选举出leader之前会导致Consul服务不可用。结论:违背了可用性A的要求,只满足一致性和分区容错,即CP
1.6分布式系统面临的-配置服务问题
微服务意味着要将单体应用中的业务拆分成一个个子服务,每个服务的粒度相对较小,因此系统中会出现大量的服务。由于每个服务都需要必要的配置信息才能运行,所以一套集中式的、动态的配置管理设施是必不可少的。比如某些配置文件中的内容大部分都是相同的,只有个别的配置项不同。就拿数据库配置来说吧,如果每个微服务使用的技术栈都是相同的,则每个微服务中关于数据库的配置几乎都是相同的,有时候主机迁移了,我希望一次修改,处处生效。 当下我们每一个微服务自己带着一个application.yml,上百个配置文件的管理......(TOT)0~
1.引入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
2.新增配置文件bootstrap.yml
applicaiton.ym1是用户级的资源配置项 bootstrap.yml是系统级的,优先级更加高 Spring Cloud会创建一个"Bootstrap Context",作为Spring应用的'Application Context的父上下文。初始化的时候,Bootstrap Context负责从外部源加载配置属性并解析配置。这两个上下文共享一个从外部获取的'Environment
'Bootstrap'属性有高优先级,默认情况下,它们不会被本地配置覆盖。'Bootstrap context'和'Application Context'有着不同的约定,所以新增了一个"bootstrap.yml'文件,保证'Bootstrap Context'和'Application Context'配置的分离。 application.yml文件改为bootstrap.yml,这是很关键的或者两者共存 因为bootstrap.yml是比application.yml先加载的。bootstrap.yml优先级高于application.yml
Bootstrap
spring:
application:
name: cloud-pay-service
cloud:
consul:
host: localhost
port: 8500
discovery:
service-names: ${spring.application.name}
config:
profile-separator: '-' #将,改成-
format: YAML
application
Spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/db2024?characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true
username: root
password: 123456
profiles:
active: dev # 环境配置加载内容dev/prod,不写就是默认default配置
3.consul服务器key/value配置填写
-
参考规则:
-
创建config文件夹,以/结尾
- config文件夹下分别创建其他三个文件夹,以/结尾
- 上述三个文件夹下分别创建data内容,data不再是文件夹
#info前面两个空格 :后面一个空格 atguigu: info: welcome to atguigu dev config,version
4.修改controller
@Value("${server.port}") private String port; @GetMapping(value = "/tpay/get/info") public String getInfoByConsul(@Value("${atguigu.info}") String atguiguInfo) { return "atguiguInfo: "+atguiguInfo+"\t"+"port: "+port; }
注意yml中的name要与服务上的名字一致
1.7consul及时动态刷新
服务上修改,但本地无法及时更新
步骤:
-
在主启动类上添加@RefreshScope
-
bootstrap.yml修改下
spring: application: name: cloud-payment-service cloud: consul: host: localhost port: 8500 discovery: service-names: ${spring.application.name} config: profile-separator: '-' format: YAML watch: wait-time: 1