SpringCloudAlibaba + Nacos + Sentinel + seata + MyBatis
文档:
https://github.com/alibaba/spring-cloud-alibaba/blob/master/README-zh.md
https://nacos.io/zh-cn/docs/what-is-nacos.html
https://github.com/alibaba/Sentinel/wiki/%E4%BB%8B%E7%BB%8D
https://seata.io/zh-cn/docs/user/quickstart.html
参考
https://blog.csdn.net/qq_37495786/article/details/103488402
新建maven工程,工程结构如图
工程使用generator生成代码,使用相对简单
sql
CREATE DATABASE IF NOT EXISTS `sca_order` DEFAULT CHARACTER SET utf8;
USE `sca_order`;
DROP TABLE IF EXISTS `order_record`;
CREATE TABLE `order_record` (
`id` varchar(32) NOT NULL COMMENT 'ID',
`business_no` varchar(50) NOT NULL COMMENT '编码',
`commodity_id` varchar(32) NOT NULL COMMENT '商品ID',
`user_id` varchar(32) NOT NULL COMMENT '用户ID',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='订单表';
CREATE DATABASE IF NOT EXISTS `sca_common` DEFAULT CHARACTER SET utf8;
USE `sca_common`;
DROP TABLE IF EXISTS `common_user`;
CREATE TABLE `common_user` (
`id` varchar(32) NOT NULL COMMENT 'ID',
`name` varchar(50) NOT NULL COMMENT '名称',
`phone` varchar(20) NOT NULL COMMENT '电话',
`age` int(3) NOT NULL COMMENT '年龄',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户表';
CREATE DATABASE IF NOT EXISTS `sca_inventory` DEFAULT CHARACTER SET utf8 ;
USE `sca_inventory`;
DROP TABLE IF EXISTS `phone_inventory`;
CREATE TABLE `phone_inventory` (
`id` varchar(32) NOT NULL COMMENT 'ID',
`name` varchar(50) NOT NULL COMMENT '名称',
`price` decimal(8,2) NOT NULL DEFAULT '0.00' COMMENT '价格',
`total` int(6) NOT NULL DEFAULT '0' COMMENT '库存',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='库存表';
pom中添加如下配置
<packaging>pompackaging>
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.1.11.RELEASEversion>
parent>
<properties>
<project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
<maven.compiler.source>1.8maven.compiler.source>
<maven.compiler.target>1.8maven.compiler.target>
<java.version>1.8java.version>
<spring-cloud-alibaba.version>2.1.0.RELEASEspring-cloud-alibaba.version>
<spring-cloud.version>Greenwich.RELEASEspring-cloud.version>
<spring-boot.version>2.1.7.RELEASEspring-boot.version>
<spring-platform.version>Cairo-SR8spring-platform.version>
properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-alibaba-dependenciesartifactId>
<version>${spring-cloud-alibaba.version}version>
<type>pomtype>
<scope>importscope>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-dependenciesartifactId>
<version>${spring-boot.version}version>
<type>pomtype>
<scope>importscope>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-dependenciesartifactId>
<version>${spring-cloud.version}version>
<type>pomtype>
<scope>importscope>
dependency>
<dependency>
<groupId>io.spring.platformgroupId>
<artifactId>platform-bomartifactId>
<version>${spring-platform.version}version>
<type>pomtype>
<scope>importscope>
dependency>
dependencies>
dependencyManagement>
本地虚拟机上运行nacos,首先保证虚拟机上有64位jdk1.8或以上版本
下载的是linux版本nacos-server-1.4.0.tar.gz上传到虚拟机
解压后进入bin目录,执行命令sh startup.sh -m standalone
正常来说这个启动不会有问题。查看日志看启动是否成功日志在nacos/logs/start.out
访问页面查看
http://192.168.1.223:8848/nacos/index.html 用户名密码都是nacos。
代码配置:
pom文件中加入nacos依赖
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
dependency>
application.yml文件中加入
spring:
application:
name: sca-common
cloud:
nacos:
discovery:
server-addr: 192.168.1.223:8848
pom文件中加入依赖
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-openfeignartifactId>
dependency>
再需要调用其他服务的工程中加入依赖,不需要调用其他服务的可以不加。
写法很简单
@FeignClient(value = "sca-common") //sca-common就是对应服务的注册到nacos的名称
public interface CommonClients {
@RequestMapping(value = "/CommonUser/getUserInfoByUserId.do") //value中的url路径就是正常的调用路径
public String getUserInfoByUserId(@RequestParam("userId") String userId);
}
下面是sca-common中的接口
@RestController
@RequestMapping(value = "/CommonUser")
public class CommonUserController {
@RequestMapping(value = "/getUserInfoByUserId.do")
public String getUserInfoByUserId(@RequestParam("userId") String userId){
return "success";
}
}
如果,调用的服务不是很重要,对于业务来说即使报错也不能影响正常业务使用,那么FeignClient需要加上fallback
@FeignClient(value = "sca-common",fallback = CommonClientsFallback.class)
public interface CommonClients {
@RequestMapping(value = "/CommonUser/getUserInfoByUserId.do")
public String getUserInfoByUserId(@RequestParam("userId") String userId);
}
CommonClientsFallback就是写CommonClients这个接口的实现类,如下:
@Component(value = "commonClientsFallback")
public class CommonClientsFallback implements CommonClients {
private Logger logger = LoggerFactory.getLogger(this.getClass());
@Override
public String getUserInfoByUserId(String userId) {
logger.error("查用户异常了");
return "error";
}
}
在实现类里面需要对异常做出相应的处理。比如,订单中的积分系统出问题,那么订单不能受到影响,所以就需要将积分的一些信息存在未处理的表中或者其他位置,使用定时任务或者其他手段将积分加上就可以了。
当然,加上fallback后发现其实并没有生效,在application.yml中加入配置
feign:
hystrix:
enabled: true #feign调用时如果配置了fallback就会生效
Sentinel的整体搭建和初步使用比较简单
下载地址:https://github.com/alibaba/Sentinel/releases/tag/1.8.1
下载jar包,所以使用Java -jar就可以运行,我在本地演示
其实也是一个spring boot项目。
浏览器输入:http://localhost:8080/#/login
用户名密码都是sentinel
项目的application中加入sentinel的相关配置
spring:
application:
name: sca-order
cloud:
nacos:
discovery:
server-addr: 192.168.1.223:8848
sentinel:
enabled: true
transport:
dashboard: 127.0.0.1:8080 #这个时自己启动sentinel时给的端口号,默认时8080
port: 8719 #固定
启动项目,调用任意接口
每个请求可以做流控和降级,根据自己需要进行配置,具体配置方法可以参照文档或者百度他人做法。
这个部分是我搭建耗时最长的部分,我先说明我使用的seata服务版本是0.9.0,目前最小的是1.4.1
下载地址https://github.com/seata/seata
我最先使用的是1.4.1,各种问题,后来用1.2的也是,退回到0.9.0
windows上没有成功过,直接开始Linux搭建过程
cd seata/conf 可以看到两个db开头的sql文件,在数据库新建一个seata的schema,将db_store.sql中的表建立到seata中,建好后如图
重点编辑三个位置
我的项目有三个服务,sca-common,sca-order,sca-inventory,我这里将vgroup_mapping和vgroupMapping都配置了一次,是因为我之前在使用1.4和1.2的时候需要,0.9的版本应该只需要vgroup_mapping
store.mode配置db,可以根据自己的需要配置file
数据库链接
出现please start seata-server后打开浏览器查看nacos
如图表示配置成功。
registry {
# file 、nacos 、eureka、redis、zk、consul、etcd3、sofa
type = "nacos"
nacos {
serverAddr = "localhost"
application = "seata-server"
namespace = ""
cluster = "default"
}
}
config {
# file、nacos 、apollo、zk、consul、etcd3
type = "nacos"
nacos {
serverAddr = "localhost"
namespace = ""
group = "SEATA_GROUP"
}
}
我都是用的nacos,如果需要使用其他方式可以根据自己的需要修改。
进入bin目录,执行如下命令
-p 端口号
-h 发布地址,默认本机locahost,但是我在使用中出现过使用localhost和127.0.0.1时代码启动报找不到服务的错误,所以我启动时直接使用的IP
-m 方式
出现Server started后打开浏览器nacos
启动成功
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-starter-alibaba-seataartifactId>
dependency>
我注释的部分就是之前使用的,后来发现用默认的就行,我的boot版本2.1.11.RELEASE
spring:
application:
name: sca-order
cloud:
nacos:
discovery:
server-addr: 192.168.1.223:8848
sentinel:
enabled: true
transport:
dashboard: 127.0.0.1:8080 #这个时自己启动sentinel时给的端口号,默认时8080
port: 8719 #固定
alibaba:
seata:
tx-service-group: sca-order-group
注意 tx-service-group: sca-order-group 中的sca-order-group是与nacos-config.txt中对应的
registry {
# file 、nacos 、eureka、redis、zk、consul、etcd3、sofa
type = "nacos"
loadBalance = "RandomLoadBalance"
loadBalanceVirtualNodes = 10
nacos {
#application = "seata-local-server"
serverAddr = "192.168.1.223:8848"
group = "SEATA_GROUP"
namespace = "public"
cluster = "default"
#username = ""
#password = ""
}
}
config {
# file、nacos 、apollo、zk、consul、etcd3
type = "nacos"
nacos {
serverAddr = "192.168.1.223:8848"
namespace = "public"
group = "SEATA_GROUP"
username = ""
password = ""
}
file {
name = "file.conf"
}
}
@Configuration
public class DataSourceProxyConfig {
@Bean
@ConfigurationProperties(prefix = "spring.datasource")
public DruidDataSource druidDataSource() {
return new DruidDataSource();
}
/**
* 必须配置数据源代理
*/
@Primary
@Bean
public DataSourceProxy dataSource(DruidDataSource druidDataSource) {
return new DataSourceProxy(druidDataSource);
}
}
如此配置后需要在boot启动class中加上@EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class}),否则启动会报错
库存减正常。异常可以自己测试,不过需要将fallback去掉,并在调用服务里面模拟一个错误。我代码中注释的部分有,已经测试过。
代码地址