版本选择
Spring Boot、Spring Cloud、Spring Coud Alibaba版本选择官网: 版本说明
项目搭建
- 创建父POM项目
File -> new Project -> maven -> Next
删除不需要的文件(因为是父POM、只要剩下POM文件就行了、MD文件后续再补)
- 统一版本管理
<!--统一管理Jar的版本-->
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<spring.cloud.alibaba-version>2021.1</spring.cloud.alibaba-version>
<spring.cloud-version>2020.0.1</spring.cloud-version>
<spring.boot.version>2.4.2</spring.boot.version>
<lombok.version>1.18.16</lombok.version>
<hutool.version>5.7.19</hutool.version>
<fastjson.version>1.2.75</fastjson.version>
<druid.version>1.1.22</druid.version>
<mysql.version>8.0.23</mysql.version>
<mybatis.plus.version>3.4.2</mybatis.plus.version>
</properties>
- 锁定子模块版本
<!--在dependencyManagement元素中声明所依赖的jar包的版本号等信息,那么所有子项目再次引入此依赖jar包时则无需显式的列出版本号。
Maven会沿着父子层级向上寻找拥有dependencyManagement 元素的项目,然后使用它指定的版本号。-->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring.boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring.cloud.alibaba-version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring.cloud-version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
- 通用依赖引入
<dependencies>
<!--mybatis plus-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis.plus.version}</version>
</dependency>
<!-- MySql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
<scope>runtime</scope>
</dependency>
<!-- 实现对数据库连接池的自动化配置 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!--mybatis plus-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis.plus.version}</version>
</dependency>
<!-- 连接池 阿里巴巴数据源 全世界最牛逼的data source 没有之一 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>${druid.version}</version>
</dependency>
<!--Lombok项目是一个Java库,它会自动插入编辑器和构建工具中,Lombok提供了一组有用的注释,用来消除Java类中的大量样板代码-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
<!--Hutool是一个小而全的Java工具类库,通过静态方法封装,降低相关API的学习成本,提高工作效率,使Java拥有函数式语言般的优雅,让Java语言也可以“甜甜的”。-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>${hutool.version}</version>
</dependency>
<!-- fastjson json转换 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
</dependencies>
子模块创建(服务提供者)
- 创建子模块
- 修改POM
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--服务注册-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<exclusions>
<exclusion>
<groupId>com.netflix.ribbon</groupId>
<artifactId>ribbon</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-loadbalancer</artifactId>
</dependency>
<!--配置中心-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!--2021以上版本需要引入该jar才能使bootstrap配置文件生效-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
<!--RPC框架-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!--spring监控-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>
- 编写主启动类 src/main/java
com.cloud.pay.PayMain8001
package com.cloud.pay;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 功能描述:支付模块主启动类
*
* @Author: zhuheguo
* @Date: 2022/4/11 10:30
*/
@SpringBootApplication
@EnableDiscoveryClient
@RestController
@RefreshScope
@EnableFeignClients
public class PayMain8001 {
public static void main(String[] args) {
SpringApplication.run(PayMain8001.class, args);
}
@Value("${test}")
private String test;
@GetMapping("test")
public String test() {
return test + "\thello world!";
}
}
- 编写配置文件 src/main/resource
bootstrap.yml
(使用properties也可以ToYaml)
management:
endpoints:
web:
exposure:
include: '*'
spring:
application:
name: cloud-pay
cloud:
nacos:
config:
file-extension: yaml
group: DEFAULT_GROUP
namespace: cloud-demo
server-addr: tx.ovozz.com:8848
profiles:
active: dev
- 配置Nacos(配置中心和服务注册中心)
Nacos官方文档:https://github.com/alibaba/Nacos
1.创建命名空间
2.编写配置文件
server:
port: 8001
test: 'test nacos config!'
spring:
cloud:
nacos:
discovery:
namespace: cloud-demo
server-addr: tx.ovozz.com:8848
# datasource 数据源配置内容,对应 DataSourceProperties 配置属性类
datasource:
#druid监控地址http://localhost:${server.port}/druid/login.html
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://tx.ovozz.com:3306/cloud_demo?autoReconnect=true&useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=UTC
username: cloud_demo
password: cloud_demo
# 初始化配置
initial-size: 3
# 最小连接数
min-idle: 3
# 最大连接数
max-active: 15
# 获取连接超时时间
max-wait: 5000
# 连接有效性检测时间
time-between-eviction-runs-millis: 90000
# 最大空闲时间
min-evictable-idle-time-millis: 1800000
test-while-idle: true
test-on-borrow: false
test-on-return: false
validation-query: select 1
# 配置监控统计拦截的filters
filters: stat,wall,log4j,config
stat-view-servlet:
url-pattern: /druid/*
reset-enable: false
- 启动与测试
PS: 启动前创建数据库操作就不演示了
-
启动支付服务模块
-
测试接口访问和获取Nacos Config 配置 http://localhost:8001/test
官方文档:https://github.com/alibaba/spring-cloud-alibaba/wiki/Nacos-config
修改Nacos 中的配置文件
cloud-pay-dev.yaml
发布并且刷新页面http://localhost:8001/test
- 服务注册
在Nacos管理 -> 服务管理 -> 服务列表中看到 cloud-pay 则代表服务注册成功
子模块创建(服务消费者)
创建流程同上
项目右键 -> New -> Module -> Maven -> Next -> cloud-pay-consumer-9001 -> Finish
copy pom
copy bootstrap.yml
并修改项目名称(服务名称),其它的都一样
spring:
application:
name: cloud-pay-consumer
- Nacos 中添加配置文件
cloud-pay-consumer-dev.yaml
其实就是copy了之前的修改了端口
server:
port: 9001
#省略了其它相同的文件
- 编写主启动类
com.cloud.pay.PayConsumerMain9001
package com.cloud.pay;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
/**
* 功能描述:支付模块消费者主启动类
*
* @Author: zhuheguo
* @Date: 2022/4/11 10:30
*/
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class PayConsumerMain9001 {
public static void main(String[] args) {
SpringApplication.run(PayConsumerMain9001.class, args);
}
}
- 编写接口 com.cloud.pay.service.PayService
package com.cloud.pay.service;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
/**
* 功能描述:
*
* @Author: zhuheguo
* @Date: 2022/4/11 15:13
*/
@FeignClient("cloud-pay")
public interface PayService {
/**
* 测试支付消费接口
* @return
*/
@GetMapping("test")
String pay();
}
- 启动与测试
- 测试负载均衡
修改PayMain8001
@Value("${test}")
private String test;
@Value("${server.port}")
private String port;
@GetMapping("test")
public String test() {
return test + ":" + port + "\thello world!";
}
利用8001修改端口启动8002 (不会可以参考 Idea中一个服务按多个端口同时启动)
把8001启动配置也加上-Dserver.port=8001
把Nacos 中配置中心的cloud-pay-dev.yaml
文件删除端口配置
server:
port: 8001
启动idea中的8001和8002
反复刷新http://localhost:9001/pay
测试 sentinel
- 项目配置
官方文档:https://github.com/alibaba/Sentinel/wiki/%E4%BB%8B%E7%BB%8D
在```cloud-pay-8001``项目的pom中添加
<!--Sentinel-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<!--sentinel 持久化-->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
在Nacos管理页 -> 配置管理 -> 配置列表 -> cloud-demo -> cloud-pay-dev.yaml 添加
spring:
cloud:
sentinel:
transport:
dashboard: localhost:8080
port: 8719
- 测试监控
启动8001和Sentinel控制台(https://github.com/alibaba/Sentinel/releases 下载然后jar运行默认8080端口)
访问http://localhost:8080并登录
登录进去默认什么都没有,然后我们疯狂刷新http://localhost:8001/test然后所在次刷新http://localhost:8080
- 测试流控(服务熔断)
QPS:每秒查询率(QPS,Queries-per-second)是对一个特定的查询服务器在规定时间内所处理流量多少的衡量标准。
新增后尝试每隔一秒访问一次和疯狂访问http://localhost:8001/test可以看出这个规则限定每秒只能访问一次,规则范围为的被Sentinel限流了
- 测试降级(服务熔断)
在PayMain8001添加接口并重启
@GetMapping("/testA")
public String testA(@RequestParam int num) {
return "testA---:" + (1 / num);
}
为了演示,选择最简单的异常数来测试熔断机制
访问http://localhost:8001/testA?num=1进行测试,发现无论如何不会触发熔断
访问http://localhost:8001/testA?num=0进行测试,发现每秒请求数超过5次并且异常数达到两次则熔断20秒
其它控制台配置请自行查阅资料了解
@SentinelResource 请参考https://blog.csdn.net/weixin_41213402/article/details/105511219
分布式事务
配置太多了,单独的文章有介绍//www.greatytc.com/p/d08ee4567749
服务网关
打包发布
需要打包的项目POM中添加打包插件即可,可以参考//www.greatytc.com/p/edf18c93236b
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
开源地址
https://gitee.com/zhuheguo/cloud-demo.git
踩坑记录
- 基于SpringBoot bootstrap.yml配置未生效的解决
作者一开始使用Spring Boot项目升级到Spring Cloud项目使用Nacos Config一直不生效,困扰了我整整一天,一直排查Nacos的问题,最后发现是因为 bootstrap.yml不生效(怀疑人生)
解决方案:引入spring-cloud-starter-bootstrap
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
- 控制台抛出异常
nested exception is java.lang.IllegalStateException: No Feign Client for loadBalancing defined. Did you forget to include spring-cloud-starter-loadbalancer
解决方案:Spring Cloud [Feign]在Hoxton.M2 RELEASED版本之后不再使用Ribbon而是使用spring-cloud-loadbalancer
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<exclusions>
<exclusion>
<groupId>com.netflix.ribbon</groupId>
<artifactId>ribbon</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-loadbalancer</artifactId>
</dependency>