创建SpringCloud Alibaba项目
下载并安装Nacos
Nacos 依赖 Java 环境来运行安装之前选装JDK1.8
官方文档:https://nacos.io/
下载地址:https://github.com/alibaba/nacos/releases
启动命令:
startup.cmd -m standalone #standalone表示单机启动,默认为集群模式启动
启动成功效果图:
默认地址http://localhost:8848/nacos/index.html
默认账号密码为:nacos/nacos
备注: 如无法启动可尝试降低版本
创建SpringCloud Alibaba父级项目
创建一个maven项目:
这里可以直接将src文件夹删除只留下pom文件即可
在pom中添加:
<groupId>org.example</groupId>
<artifactId>springcloud-alibaba-demo</artifactId>
<version>1.0-SNAPSHOT</version>
<name>root</name>
<packaging>pom</packaging>
<build>
<plugins>
<!--参考文章:https://blog.csdn.net/liupeifeng3514/article/details/80236077-->
<plugin>
<!-- 指定maven编译的jdk版本,如果不指定,maven3默认用jdk 1.5 maven2默认用jdk1.3 -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<!-- 源代码使用的JDK版本 -->
<source>1.8</source>
<!-- 需要生成的目标class文件的编译版本 -->
<target>1.8</target>
<!-- 字符集编码 -->
<encoding>UTF-8</encoding>
<!-- 跳过测试 -->
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</build>
创建common项目
添加依赖:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<!-- 指定版本 -->
<properties>
<java.version>1.8</java.version>
<spring-cloud-alibaba.version>2.1.0.RELEASE</spring-cloud-alibaba.version>
<spring-cloud.version>Greenwich.RELEASE</spring-cloud.version>
<spring-boot.version>2.1.7.RELEASE</spring-boot.version>
<spring-platform.version>Cairo-SR8</spring-platform.version>
</properties>
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>common</artifactId>
<version>1.0-SNAPSHOT</version>
<name>common</name>
<packaging>pom</packaging>
<dependencyManagement>
<dependencies>
<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>
<!--支持Spring Boot 2.1.X-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--Greenwich.RELEASE-->
<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>
</project>
创建服务提供者
添加依赖:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.example</groupId>
<artifactId>common</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>service-producer</artifactId>
<groupId>org.example</groupId>
<version>1.0-SNAPSHOT</version>
<name>service-producer</name>
<dependencies>
<!-- nacos -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- web启动 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- feign -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
</dependencies>
</project>
添加配置文件:
server:
port: 8300
spring:
application:
name: producer
cloud:
nacos:
discovery:
server-addr: localhost:8848
loadbalancer:
retry:
enabled: false
创建启动类,启动类需添加
- @EnableDiscoveryClient 用于服务注册
- @EnableFeignClients 同于服务调用
@EnableDiscoveryClient
@SpringBootApplication
@EnableFeignClients
public class OrderApplication {
public static void main(String[] args) {
SpringApplication.run(OrderApplication.class, args);
}
}
创建Controller
@RestController
@RequestMapping("/test")
public class TestServiceController {
@RequestMapping("/producer")
public String test(String name) {
return "I am " + name;
}
}
启动发现nacos中已经有服务注册:
调用测试:
http://localhost:8300/test/producer?name=张三
创建服务消费者
创建过程可以参照服务提供者(pom依赖和配置文件大体一致)
需修改配置文件中
- spring.application.name
- server.port
创建启动类,启动类需添加
@EnableDiscoveryClient 用于服务注册
@EnableFeignClients 同于服务调用
@EnableDiscoveryClient
@SpringBootApplication
@EnableFeignClients
public class ConsumerApplication{
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class, args);
}
}
创建Apis接口
/**
* FeignClient name为要调用的服务名
*/
@FeignClient(name = "producer")
public interface TestServicesApis {
/**
* 接口中的参数必须使用@RequestParam注解指定名称
* RequestMapping注解需和被调用一致
* RequestMapping中的参数为该服调用的地址
*
* @param name
* @return
*/
@RequestMapping("/test/producer")
String test(@RequestParam("name") String name);
}
创建Controller
@RestController
@RequestMapping("/test")
public class TestServiceController {
@Autowired
private TestServicesApis testServicesApis;
@RequestMapping("/get")
public String get(String name) {
return testServicesApis.test(name);
}
}
启动项目发现成功注册到nacos中
调用测试:
http://localhost:8400/test/get?name=李四
创建config服务
创建过程一致
pom文件:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>com.tianyu.springcloudalibaba</groupId>
<artifactId>common</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>servicer-config</artifactId>
<groupId>com.tianyu.springcloudalibaba</groupId>
<version>1.0-SNAPSHOT</version>
<name>service-config</name>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- nacos 配置中心 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
</dependencies>
</project>
创建bootstarp.yaml配置文件 , 必须是bootstarp
配置文件名称命名规范:
${prefix}-${spring.profile.active}.${file-extension}
prefix 默认为 spring.application.name 的值,
也可以通过配置项 spring.cloud.nacos.config.prefix来配置。
spring.profile.active 即为当前环境对应的 profile,详情可以参考 Spring Boot文档。
注意:当 spring.profile.active 为空时,对应的连接符 - 也将不存在,dataId 的拼接格式变成 ${prefix}.${file-extension}
file-exetension 为配置内容的数据格式,可以通过配置项 spring.cloud.nacos.config.file-extension 来配置。目前只支持 properties 和 yaml 类型
# 配置文件的名称构成
# ${prefix}-${spring.profile.active}.${file-extension}
# 如${spring.profile.active}部分为空 , 则名称构成为${prefix}.${file-extension}
# ${prefix}默认是#{spring.application.name}也可以指定${spring.cloud.nacos.cofig.prefix}
server:
port: 8500
spring:
application:
name: config
cloud:
nacos:
config:
# 配置中心的地址
server-addr: localhost:8848
# 配置文件的格式 ${file-extension} 部分
file-extension: yaml
# 配置文件的第一部分 ${prefix} 部分
prefix: config
discovery:
server-addr: localhost:8848
loadbalancer:
retry:
enabled: false
创建启动类
@SpringBootApplication
@EnableDiscoveryClient
public class ConfigApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigApplication.class, args);
}
}
创建Controller
nacos配置中心是支持热加载的
需在有@Value的类上添加@RefreshScope实现热加载
@RefreshScope
@RestController
@RequestMapping("/test")
public class TestController {
@Value("${name}")
private String name;
@RequestMapping("/get_value")
public String getValue() {
return "name : " + name;
}
}
在nacos中创建配置
添加好后启动config项目
调用测试:
http://localhost:8500/test/get_value
我们修改配置文件中的配置
再次测试:
http://localhost:8500/test/get_value
热加载成功
Sentinel 的使用
下载地址:
https://github.com/alibaba/Sentinel/releases
启动命令:
java -jar * (* 表示下载的jar包名称)
默认端口
我们在consumer服务中进行修改使其使用Sentinel
在pom文件中添加依赖:
<!-- sentinel -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
在配置文件中添加配置:
spring:
cloud:
sentinel:
transport:
port: 8719 # 用作与sentinel进行交互的端口
dashboard: localhost:8080 # sentinel的地址
在我们的Controller中添加SentinelResource注解
@RestController
@RequestMapping("/test")
public class TestServiceController {
@Autowired
private TestServicesApis testServicesApis;
@RequestMapping("/get")
@SentinelResource(value = "SentinelTest") //value为资源名 , 必填
public String get(String name) {
return testServicesApis.test(name);
}
}
重启服务并调用consumer的接口 , 效果如下
我们点击簇点链路找到我们的SentinelTest点击流控添加流控规则
我们将单机阈值设置为2 (连续点击三次时服务被快速失败)
我们在浏览器测试快速连续刷新3次
- Sentinel 控制台可以很方便的控制各种规则,包括流控规则、降级规则等,但是这种方式将规则存储在内存中,一旦服务宕机或者重启会导致规则消失,生产中不建议使用
- pull模式:即拉模式,客户端主动向某个规则管理中心定期轮询拉取规则,这个规则中心可以是 RDBMS、文件 等;实时性不保证,拉取过于频繁也可能会有性能问题
- push模式:**即推模式,规则中心统一推送,客户端通过注册监听器的方式时刻监听变化,比如使用 Nacos、Zookeeper 等配置中心。这种方式有更好的实时性和一致性保证。生产环境下一般采用 push 模式的数据源。
我们继续改造consumer服务将Sentinel 的配置持久化
在配置文件中添加配置修改后效果:
server:
port: 8400
spring:
application:
name: consumer
cloud:
nacos:
discovery:
server-addr: localhost:8848
loadbalancer:
retry:
enabled: false
sentinel:
transport:
port: 8719 # 用作与sentinel进行交互的端口
dashboard: localhost:8080 # sentinel的地址
eager: true # 设置心跳检测
datasource:
ds: #名字随意起
nacos:
server-addr: localhost:8848 # nacos的地址
data-id: ${spring.application.name}-flow-rules # 与在nacos创建的配置文件的data-id对应
group-id: DEFAULT_GROUP # 与nacos中配置文件的组对应
#rule-type参数是spring cloud alibaba升级到0.2.2之后增加的配置,
#用来定义存储的规则类型。所有的规则类型可查看枚举类:
#org.springframework.cloud.alibaba.sentinel.datasource.RuleType,
#每种规则的定义格式可以通过各枚举值中定义的规则对象来查看,比如限流规则可查看:
#com.alibaba.csp.sentinel.slots.block.flow.FlowRule。
rule-type: flow
data-type: json # 格式
namespace: public # 命名空间 如果没有创建则是public
# Nacos 注册中心客户端心跳日志禁用 防止刷屏
logging:
level:
com.alibaba.nacos.client.config.impl: WARN
设置好后在nacos中创建配置文件
[
{
"resource": "/test",
"limitApp": "default",
"grade": 1,
"count": 10,
"strategy": 0,
"controlBehavior": 0,
"clusterMode": false
}
]
- resource:资源名,即限流规则的作用对象
- limitApp:流控针对的调用来源,**若为 default 则不区分调用来源
- grade:限流阈值类型(QPS 或并发线程数);0代表根据并发数量来限流,1代表根据QPS来进行流量控制
- count:限流阈值
- strategy:调用关系限流策略
- controlBehavior:流量控制效果(直接拒绝、Warm Up、匀速排队)
- clusterMode:是否为集群模式
我们重启服务在Sentinel中的流控中可以看到添加了一条规则
*备注可以改造Sentinel将Sentinel中的配置持久化到Nacos中可参考
https://blog.csdn.net/EnjoyEDU/article/details/109587953
SpringCloudGateway使用
- Predicate:断言,内置了很多这种Predict,满足断言的才会进入路由 , 包括了:时间、path、query、Header等等
例如:Header=X-Request-Id, \d+ - filter:过滤器,内置了很多filter,并且可以自定义,只在配置的路由起作用
例如:AddRequestHeader=X-Request-Foo, Bar,表示经过此过滤器会加上指定参数 - global filter:全局过滤器,内置了很多filter,并且可以自定义,作用范围为所有的路由 , 例如:AddRequestHeader=X-Request-Foo, Bar,表示经过此过滤器会加上指定参数
我们新建项目
pom:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>com.tianyu.springcloudalibaba</groupId>
<artifactId>common</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>servicer-gateway</artifactId>
<groupId>com.tianyu.springcloudalibaba</groupId>
<version>1.0-SNAPSHOT</version>
<name>service-gateway</name>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
</dependencies>
</project>
配置文件
server:
port: 8600
spring:
application:
name: gateway
profiles:
# 指定配置
# route_simple:简单转发
# route_stripPrefix:截取请求
# route_uri:转发指定地址并传入参数,自定义过滤器
# route_ld:服务发现
# 下面会有多个配置 active为选择使用哪个配置 值为spring.profiles中对应的值
active: route_ld
--- # 单纯转发
spring:
profiles: route_simple
cloud:
gateway:
routes:
# id自定义 不能重复
- id: url-proxy-1
# uri为满足条件之后需要跳转到哪里
uri: https://blog.csdn.net
# 断言 , 满足条件 , 此条件为路径为csdn localhost:port/csdn
predicates:
- Path=/csdn
- id: url-fsfy-2
uri: http://www.sunlands.com/
# 此条件为参数名为green并且值是个数 localhost:port?green=1
predicates:
- Query=green,\d+
nacos:
discovery:
enabled: false
--- # 过滤器截取
spring:
profiles: route_stripPrefix
cloud:
gateway:
routes:
- id: url-proxy-1
uri: https://blog.csdn.net
predicates:
- Path=/str/rank/list #localhost:port/str/rank/list
# 过滤器 断言满足后做的操作
filters:
# 截取路径位数 会将第一个截取掉 变为 localhost:port/rank/list
- StripPrefix=1
nacos:
discovery:
enabled: false
--- ## 转发指定地址截取并传入参数
spring:
profiles: route_uri
cloud:
gateway:
routes:
# 路由标识(id:标识,具有唯一性)
- id: route_uri2-fs
# 目标服务地址(uri:地址,请求转发后的地址)
uri: http://localhost:8300
predicates:
## 匹配 GET 请求
- Method=GET
- Path=/aaa/test/producer
# 过滤器
filters:
# 会将/aaa 截取掉
- StripPrefix=1
## 添加指定参数
- AddRequestParameter=name, aaaaaaaw
nacos:
discovery:
enabled: false
--- # 服务发现
spring:
# 配置文件名称,用来标识不同环境的配置。由 spring.profiles.active 的值来决定使用哪组配置。
profiles: route_ld
cloud:
gateway:
# 路由(routes:路由,它由唯一标识(ID)、目标服务地址(uri)、一组断言(predicates)和一组过滤器组成(filters)。filters 不是必需参数。)
routes:
# 路由标识(id:标识,具有唯一性) 转发指定地址并传入参数
- id: route_uri2-fs
# 目标服务地址(uri:地址,请求转发后的地址)
uri: lb://producer
# 路由条件(predicates:断言,匹配 HTTP 请求内容)
predicates:
# 匹配规则
- Path=/demo/**
# 过滤器(filters:过滤器,过滤规则)
filters:
# 会将/demo截取掉
- StripPrefix=1
## 添加指定参数
- AddRequestParameter=name, bbbbb
discovery:
locator:
enabled: true #注册中心发现
lower-case-service-id: true #小写
nacos:
discovery:
server-addr: 127.0.0.1:8848
sentinel:
transport:
port: 8719
dashboard: localhost:8080
eager: true #关闭懒加载
启动类:
@SpringBootApplication
@EnableDiscoveryClient
public class GatewayApplicetion {
public static void main(String[] args) {
SpringApplication.run(GatewayApplicetion.class, args);
}
}
配置文件中的配置为多个配置可以指定spring.profiles.active的值进行选取配置 , 一下我以4中情况进行测试
修改spring.profiles.active的值为route_simple
, 启动项目访问:
http://localhost:8600/csdn
gateway会帮我们自动跳转到https://blog.csdn.net这个网址效果如下
我们再次尝试访问
http://localhost:8600/?green=1
gateway会帮我们自动跳转到http://www.sunlands.com/
效果如下:
我们将spring.profiles.active修改为route_stripPrefix重启项目
我们访问:
http://localhost:8600/str/rank/list
效果如下:
我们启动service-producer项目
修改spring.profiles.active的值为route_uri重启service-gateway项目
我们访问:
http://localhost:8600/aaa/test/producer
效果如下
我们修改spring.profiles.active的值为route_ld重启项目
我们访问:
http://localhost:8600/demo/test/producer
效果如下
至此我们SpringCloud Alibaba项目简单的搭建完成
本人第一次写博客 , 也是在学习的过程中做一下记录 , 有不对的地方希望各位大神多多指点
代码地址:
https://github.com/Tianyu-java/springcloud-alibaba.git