文章目录
参考书:
- https://springcloud.cc/spring-cloud-netflix.html
- zhongwenAPI文档:https://springcloud.cc/sprign-cloud-dalston.html
- SpringCloud中国社区:https://springcloud.cn/
- SpringCloud中文网:https://springclod.cc
springcloud对应的boot版本
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EZNnBhhZ-1643200371334)(D:\CHEN\Typora\image\image-20220118192333435.png)]
mava跳过单元测试
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5gG4BlsX-1643200371335)(D:\CHEN\Typora\image\image-20220120161615101.png)]
一、微服务
-
单体架构:简单方便,高度耦合,扩展性差,适合小型项目。例如:学生管理系统
-
分布式架构:松耦合,扩展性好,但架构复杂,难度大。适合大型互联网项目,例如:京东、淘宝
-
微服务:一种良好的分布式架构方案
①优点:拆分粒度更小、服务更独立、耦合度更低
②缺点:架构非常复杂,运维、监控、部署难度提高
微服务的架构特征:
- 单一职责:微服务拆分粒度更小,每一个服务都对应唯一的业务能力,做到单一职责
- 自治:团队独立、技术独立、数据独立,独立部署和交付
- 面向服务:服务提供统一标准的接口,与语言和技术无关
- 隔离性强:服务调用做好隔离、容错、降级,避免出现级联问题
微服务的上述特性其实是在给分布式架构制定一个标准,进一步降低服务之间的耦合度,提供服务的独立性和灵活性。做到高内聚,低耦合。
因此,可以认为微服务是一种经过良好架构设计的分布式架构方案 。
1.1.服务拆分原则
这里我总结了微服务拆分时的几个原则:
- 不同微服务,不要重复开发相同业务
- 微服务数据独立,不要访问其它微服务的数据库
- 微服务可以将自己的业务暴露为接口,供其它微服务调用
1.2.实现远程调用案例
大概的步骤是这样的:
- 注册一个RestTemplate的实例到Spring容器
- 修改order-service服务中的OrderService类中的queryOrderById方法,根据Order对象中的userId查询User
- 将查询的User填充到Order对象,一起返回
1.2.1.注册RestTemplate
首先,我们在order-service服务中的OrderApplication启动类中,注册RestTemplate实例:
@MapperScan("cn.vector.order.mapper")
@SpringBootApplication
public class OrderApplication {
public static void main(String[] args) {
SpringApplication.run(OrderApplication.class, args);
}
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
1.3 提供者与消费者
在服务调用关系中,会有两个不同的角色:
服务提供者:一次业务中,被其它微服务调用的服务。(提供接口给其它微服务)
服务消费者:一次业务中,调用其它微服务的服务。(调用其它微服务提供的接口)
1.4.Eureka的结构和作用
问题1:order-service如何得知user-service实例地址?
获取地址信息的流程如下:
- user-service服务实例启动后,将自己的信息注册到eureka-server(Eureka服务端)。这个叫服务注册
- eureka-server保存服务名称到服务实例地址列表的映射关系
- order-service根据服务名称,拉取实例地址列表。这个叫服务发现或服务拉取
问题2:order-service如何从多个user-service实例中选择具体的实例?
- order-service从实例列表中利用负载均衡算法选中一个实例地址
- 向该实例地址发起远程调用
问题3:order-service如何得知某个user-service实例是否依然健康,是不是已经宕机?
- user-service会每隔一段时间(默认30秒)向eureka-server发起请求,报告自己状态,称为心跳
- 当超过一定时间没有发送心跳时,eureka-server会认为微服务实例故障,将该实例从服务列表中剔除
- order-service拉取服务时,就能将故障实例排除了
1.5 自动重启项目
-
导入依赖
//在子类中 <!-- 热部署--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> // 在父类中 <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <fork>true</fork> <addResources>true</addResources> </configuration> </plugin> </plugins> </build>
2.设置中打勾
- 配置ctr+shift+Alt+/ 之后点第一个
二、搭建eureka-server
首先大家注册中心服务端:eureka-server,这必须是一个独立的微服务
3.1 引入eureka依赖
引入SpringCloud为eureka提供的starter依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
3.2 编写启动类
给eureka-server服务编写一个启动类,一定要添加一个@EnableEurekaServer注解,开启eureka的注册中心功能:
package cn.itcast.eureka;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@EnableEurekaServer
public class EurekaApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaApplication.class, args);
}
}
3.3 编写配置文件
编写一个application.yml文件,内容如下:
server:
port: 7001
# 单机版
eureka:
instance:
hostname: localhost #eureka服务端的实例名字
client:
register-with-eureka: false #表识不向注册中心注册自己
fetch-registry: false #表示自己就是注册中心,职责是维护服务实例,并不需要去检索服务
service-url:
#设置与eureka server交互的地址查询服务和注册服务都需要依赖这个地址
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
#集群版
#eureka:
# instance:
# hostname: eureka7001.com #eureka服务端的实例名字
# client:
# register-with-eureka: false #表识不向注册中心注册自己
# fetch-registry: false #表示自己就是注册中心,职责是维护服务实例,并不需要去检索服务
# service-url:
# #设置与eureka server交互的地址查询服务和注册服务都需要依赖这个地址
# defaultZone: http://eureka7001.com:7001/eureka/
# server:
## 关闭自我保护机制,保证不可用服务被及时踢除
# enable-self-preservation: false
# eviction-interval-timer-in-ms: 2000
3.4 启动服务
启动微服务,然后在浏览器访问:http://localhost:7001/
三、服务注册
将user-service注册到eureka-server中去。
1)引入依赖
在provider的pom文件中,引入下面的eureka-client依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
2)配置文件
在provider-payment中,修改application.yml文件,添加服务名称、eureka地址:
server:
port: 8001
spring:
application:
name: cloud-payment-service
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/cloud2022?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8
username: root
password: chen123456
eureka:
client:
#表示是否将自己注册进EurekaServer
register-with-eureka: true
#是否从EurekaServer抓取已有的注册信息
fetch-registry: true
service-url:
defaultZone: http://localhost:7001/eureka
mybatis:
mapper-locations: classpath:mapper/*.xml
type-aliases-package: com.vector.springcloud.entities
3)启动多个provider-payment实例
四、注册集群服务
-
首先要找到C:\Windows\System32\drivers\etc下的hosts,添加服务地址
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Y12P8vEQ-1643200371338)(D:\CHEN\Typora\image\image-20220124160414778.png)]
-
集群注册yml配置
server: port: 7001 #集群版 eureka: instance: hostname: eureka7001.com #eureka服务端的实例名字 client: register-with-eureka: false #表识不向注册中心注册自己 fetch-registry: false #表示自己就是注册中心,职责是维护服务实例,并不需要去检索服务 service-url: #设置与eureka server交互的地址查询服务和注册服务都需要依赖这个地址 defaultZone: http://eureka7002.com:7002/eureka/ ############另一个配置文件的配置################### server: port:7002 #集群版 eureka: instance: hostname: eureka7002.com #eureka服务端的实例名字 client: register-with-eureka: false #表识不向注册中心注册自己 fetch-registry: false #表示自己就是注册中心,职责是维护服务实例,并不需要去检索服务 service-url: #设置与eureka server交互的地址查询服务和注册服务都需要依赖这个地址 defaultZone: http://eureka7001.com:7001/eureka/
五、解决zookeper版本冲突问题
//导入依赖包
<!-- 先排除自带的zookeeper版本-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
<exclusions>
<exclusion>
<groupId>com.weicoder</groupId>
<artifactId>zookeeper</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.weicoder</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.6</version>
</dependency>
六、Consul介绍
- Consu是一套开源的分布式发现和配置管理系统,用Go语言开发
- 提供了微服务系统中心的服务管理,配置中心,控制总线等功能。
- 优点是:基于raft协议,比较简洁;支持健康检查
七、Ribbon介绍
- Spring Cloud Ribbon是基于Netflix Ribbon实现的一套客户端 负载均衡的工具
- 搭配restTemplate实现负载均衡
7.1 自定义负载均衡规则
在com.vector.myrule下创建:
@Configuration
public class MySelfRule {
@Bean
public IRule myRule() {
// 此处将ribbon默认使用的轮询策略改为随机策略
return new RandomRule();
}
}
// 之后在主类中添加
@RibbonClient(name = "CLOUD-PAYMENT-SERVICE", configuration = MySelfRule.class)
八、服务网关
8.1 Geteway概述
- Geteway是在spring生态系统之上和构建的API网关服务,基于spring5、springboot2和Project Reactor等技术。
- Geteway旨在提供一种简单而有效的方式对API进行路由,并提供一些强大的过滤器功能,例如:熔断、限流、重试等。
- SpringCloud Gateway 使用的Webflux中的reactor-netty响应式编程组件,底层使用了Netty通讯框架。
8.2 引入依赖:
<!--gateway-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
8.3 yml配置:
spring:
application:
name: cloud-gateway
cloud:
gateway:
discovery:
locator:
enabled: true #开启从注册中心动态创建路由的功能,利用微服务名进行路由
routes:
- id: payment_routh #payment_route #路由的ID,没有固定规则但要求唯一,建议配合服务名
uri: http://localhost:8001 #匹配后提供服务的路由地址
#uri: lb://cloud-payment-service #匹配后提供服务的路由地址
predicates:
- Path=/payment/get/** # 断言,路径相匹配的进行路由
- id: payment_routh2 #payment_route #路由的ID,没有固定规则但要求唯一,建议配合服务名
uri: http://localhost:8001 #匹配后提供服务的路由地址
#uri: lb://cloud-payment-service #匹配后提供服务的路由地址
predicates:
- Path=/payment/lb/** # 断言,路径相匹配的进行路由
- After=2020-03-08T10:59:34.102+08:00[Asia/Shanghai]
# - Before=2020-03-08T10:59:34.102+08:00[Asia/Shanghai]
# - Between=2020-03-08T10:59:34.102+08:00[Asia/Shanghai] , 2020-03-08T10:59:34.102+08:00[Asia/Shanghai]
# curl http://localhost:9527/payment/lb --cookie "username=zzyy"
# - Cookie=username,zzyy #Cookie=cookieName,正则表达式
# 请求头要有X-Request-Id属性并且值为整数的正则表达式 curl http://localhost:9527/payment/lb --cookie "username=zzyy" -H "X-Request-Id:11"
# - Header=X-Request-Id, \d+
# - Host=**.atguigu.com # curl http://localhost:9527/payment/lb -H "Host:afae.atguigu.com"
8.4 Gateway三大核心概念
- Route 路由: 它有ID,目标URL,一系列的断言和过滤器组成
- Predicate 断言:
- Filter 过滤器:指的是Spring框架中GatewayFilter的实例,使用过滤器,可以在请求被路由前或者对请求之间,对路由进行使用。
九、SpringCloud Sleuth
SpringCloud Sleuth是路由的请求链路跟踪
使用:在github下载jar包,运行访问:http://localhost:9411/zipkin/
zipkin: 可视化监听
9.1 引入依赖:
<!--包含了sleuth+zipkin-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>
9.2 yml的配置:
spring:
application:
name: cloud-payment-service
zipkin:
base-url: http://localhost:9411
sleuth:
sampler:
#采样率值介于0到1之间,1则表示全部采集
probability: 1
十、Nacos的安装及启动
服务注册和配置中心
10.1 安装
访问:在浏览器地址输入 nacos.io 访问,并前往github下载即可
10.2 启动
启动非常简单,进入bin目录,结构如下:
然后执行命令即可:
-
windows命令:
startup.cmd -m standalone
10.3 访问
在浏览器输入地址:http://192.168.160.1:8848/nacos/index.html即可:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-t71thgzs-1643200371339)(D:\CHEN\Typora\image\image-20220120151449855.png)]
默认的账号和密码都是nacos。
10.4 导入依赖父类:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.2.5.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
// 子类引入依赖
<!--SpringCloud ailibaba nacos -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
10.5 yml配置:
spring:
application:
name: nacos-payment-provider
cloud:
nacos:
discovery:
server-addr: localhost:8848 #配置Nacos地址
#端口暴漏
management:
endpoints:
web:
exposure:
include: '*'
10.6 nacos替代config作为配置中心
10.6.1导入依赖
<!--nacos-config 配置中心-自带动态刷新-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!--nacos-discovery 注册中心-服务发现与注册-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
10.6.2 yml的配置:
bootstrap.yml的优先级高于application.yml
################# bootstrao.yml配置 ################
server:
port: 3377
spring:
application:
name: nacos-config-client
cloud:
nacos:
discovery:
server-addr: localhost:8848 #服务注册中心地址
config:
server-addr: localhost:8848 #配置中心地址
file-extension: yaml #指定yaml格式的配置
#group: DEV_GROUP #修改的分组
#namespace: 912eccb8-4d1d-43a0-80c5-0dc6ca5805f6 #新建命名空间流水号
# ${spring.application.name}-${spring.profile.active}.${spring.cloud.nacos.config.file-extension}
# nacos-config-client-dev.yaml
# nacos-config-client-test.yaml ----> config.info
###################application.yml配置####################
spring:
profiles:
active: dev
#active: test # 表示测试环境
#active: info
10.6.3 主启动类的引用:
// 引入以下注解
@EnableDiscoveryClient
@SpringBootApplication
// controller中的调用
@RestController
@RefreshScope
public class ConfigClientController {
@Value("${config.info}")
private String configInfo;
@GetMapping("/config/info")
public String getConfigInfo() {
return configInfo;
}
}
10.6.4 根据yml配置推出
nacos可视化页面中的配置服务名:nacos-config-client-dev.yaml
文件中的配置为:
config:
info: .....
10.7 nacos集群和持久化
10.7.1 持久化
- 要把nacos自带的数据库修改为mysql数据库
找到windows安装的nacos配置目录…\nacos-2.03\conf下的nacos-mysql.sql文件,粘贴复制到mysql下执行即可。
/******************************************/
/* 数据库全名 = nacos_config */
/* 表名称 = config_info */
/******************************************/
CREATE TABLE `config_info` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
`data_id` varchar(255) NOT NULL COMMENT 'data_id',
`group_id` varchar(255) DEFAULT NULL,
`content` longtext NOT NULL COMMENT 'content',
`md5` varchar(32) DEFAULT NULL COMMENT 'md5',
`gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
`src_user` text COMMENT 'source user',
`src_ip` varchar(50) DEFAULT NULL COMMENT 'source ip',
`app_name` varchar(128) DEFAULT NULL,
`tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段',
`c_desc` varchar(256) DEFAULT NULL,
`c_use` varchar(64) DEFAULT NULL,
`effect` varchar(64) DEFAULT NULL,
`type` varchar(64) DEFAULT NULL,
`c_schema` text,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_configinfo_datagrouptenant` (`data_id`,`group_id`,`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_info';
/******************************************/
/* 数据库全名 = nacos_config */
/* 表名称 = config_info_aggr */
/******************************************/
.
.
.
.
10.7.2 linux下的配置:
// 进入到nacos/conf/application.propertirs下修改配置
// 复制出 cp application.properties application.properties.init
// 修改的是 application.properties
spring.datasource.platform=mysql
db.num=1
db.url.0=jdbc:mysql://服务器IP:3306/nacos_config?serverTimezone=UTC&characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true
db.user=root
db.password=123456
配置 cluster.conf.example
// 复制 cp cluster.conf.example cluster.conf
// 修改 cluster.conf的配置
hostname -i 得出ip地址
// 配置cluster.conf,添加
172.16.143.144:3333
172.16.143.144:4444
172.16.143.144:5555
// 几个端口号
安装nginx的linux
启动端口
./startup.sh -p 3333
.......
// 启动linux版本的nginx
./nginx -c /user/local/nginx/conf/nginx.conf
// 验证启动
ps -ef|grep nginx
十一、Sentinel
Sentinel:分布式系统的流量防卫兵。
具有的特征:
- 应用场景丰富:例如秒杀(把流量控制在系统可承受范围内),集群流量控制等
- 实时监控。
- 广泛的开源生态
- 完善的SPI扩展点
服务中的使用:
- 服务雪崩
- 服务降级
- 服务熔断
- 服务限流
访问:下载jar包运行: http://localhost:8080/#/login
用户名和密码都是: sentinel
11.1 导入的依赖
<!--SpringCloud ailibaba sentinel -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
11.2 yml的配置
spring:
application:
name: cloudalibaba-sentinel-service
cloud:
nacos:
discovery:
server-addr: localhost:8848 #Nacos服务注册中心地址
sentinel:
transport:
dashboard: localhost:8080 #配置Sentinel dashboard地址
port: 8719
###################################
datasource:
ds1:
nacos:
server-addr: localhost:8848
dataId: ${spring.application.name}
groupId: DEFAULT_GROUP
data-type: json
rule-type: flow
十二、seata
官网:http://seata.io/zh-cn/
seate典型的分布式事务过程:1+3模式:
分布式事务处理过程的-ID+三组件模式:
- Transaction ID XID 全局唯一的事务ID。
- Transaction Coordinator(TC) :事务协调器,维护全局事务的运行状态。
- Transaction Manager™ :控制全局事务的边界。
- Resource Manager(RM) :控制分支事务、负责分支注册、状态汇报。
下载地址:https://github.com/seata/seata/releases
修改file.conf配置:
修改store下的东西:先进入到。。。\seata\seata-server-1.4.2\conf下
- mode = “改为db”
- 修改db{里面的 url 、user、 password}
创建seata数据库
修改registry.conf配置
修改它的 type = “nacos” 和 serverAddr = “localhost:8848”
datasource:
ds1:
nacos:
server-addr: localhost:8848
dataId: ${spring.application.name}
groupId: DEFAULT_GROUP
data-type: json
rule-type: flow
## 十二、seata
官网:http://seata.io/zh-cn/
seate典型的分布式事务过程:1+3模式:
分布式事务处理过程的-ID+三组件模式:
- Transaction ID XID 全局唯一的事务ID。
- Transaction Coordinator(TC) :事务协调器,维护全局事务的运行状态。
- Transaction Manager(TM) :控制全局事务的边界。
- Resource Manager(RM) :控制分支事务、负责分支注册、状态汇报。
下载地址:https://github.com/seata/seata/releases
### 修改file.conf配置:
修改store下的东西:先进入到。。。\seata\seata-server-1.4.2\conf下
- mode = "改为db"
- 修改db{里面的 url 、user、 password}
**创建seata数据库**
### 修改registry.conf配置
修改它的 type = "nacos" 和 serverAddr = "localhost:8848"