这篇文章主要讲述了 :
springCloud Alibaba 下的
- Nacos
- openFeign
- sentinel
- seata
- springCloud下的Gatetway
- skyWalking
等详细搭建和使用过程
版本依赖:
名称 | 版本 | 说明 |
---|---|---|
cloud alibaba | 2.2.6 RELEASE | – |
spring boot | 2.3.2.RELEASE | – |
spring cloud | Hoxton.SR9 | – |
nacos | 1.4.2 | – |
openFeign | 10.10.1 | 跟随cloud主版本 |
sentinel | 1.8.1 | – |
seata | 1.3.0 | 跟随cloud主版本 |
Gatetway | 2.2.6.RELEASE | – |
skyWalking | 9.0.0 | – |
项目已放置gitee
https://gitee.com/zwenbobo_admin/cloudalibaba
创建父子工程项目 首先整合nacos 和 feign
父工程:cloud-test
子工程:cloud-test-consumer (客户层)
子工程:cloud-test-provider (服务层,远程调研层)
1.父工程pom.xml
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.cloud</groupId>
<artifactId>cloud-test</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>cloud-test</name>
<description>Demo project for Spring Boot</description>
<packaging>pom</packaging>
<modules>
<module>cloud-test-consumer</module>
<module>cloud-test-provider</module>
<!-- <module>cloud-test-feign</module>-->
</modules>
<properties>
<!--spring cloud版本-->
<spring.cloud-version>Hoxton.SR9</spring.cloud-version>
<spring.cloud.alibaba-version>2.2.6.RELEASE</spring.cloud.alibaba-version>
<java.version>8</java.version>
<skipTests>true</skipTests>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<!--spring cloud-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring.cloud-version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--spring cloud alibaba-->
<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>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
2.子工程cloud-test-consumer pom.xml
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.cloud</groupId>
<artifactId>cloud-test</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<artifactId>cloud-test-consumer</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>cloud-test-consumer</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>8</java.version>
</properties>
<dependencies>
<!--配置feign-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!--web起步依赖-->
<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>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>3.0.0</version>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
2.1 yml
server:
port: 8080
spring:
application:
name: consumer-server
cloud:
nacos:
server-addr: 127.0.0.1:8848
discovery:
username: nacos
password: nacos
namespace: public
ephemeral: false
2.2 启动类中添加注解
//注解式 feign 客户端
@EnableFeignClients
2.3 添加 feign远程接口 下单和获取订单两个方法
@FeignClient(name="provider-server",path = "/item",configuration = FeignConfig.class)
public interface ItemFeignService {
@GetMapping("/doOrder")
String doOrder();
/**
* 根据用户ID 获取订单
* @param id
* @return
*/
@GetMapping("/item/{id}")
String getItemInfo(@PathVariable(name = "id") String s);
}
2.4 controller
@RestController
@RequestMapping("/order")
public class OrderController {
@Resource
private ItemFeignService itemFeignService;
@GetMapping("/doOrder")
public String doOrder() {
//1.下单
String info = itemFeignService.doOrder();
System.out.println("下单成功,订单信息为:"+info);
//3.模拟返回成功信息
return info;
}
@GetMapping("/getOrder")
public String getOrder() {
//1.模拟远程调用获取到到商品信息
String info = itemFeignService.getItemInfo("1");
System.out.println("获取订单信息为:"+info);
//3.模拟返回成功信息
return info;
}
}
3.子工程:cloud-test-providerr pom.xml
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.cloud</groupId>
<artifactId>cloud-test</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<artifactId>cloud-test-provider</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>cloud-test-provider</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>8</java.version>
</properties>
<dependencies>
<!--配置feign-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!--web起步依赖-->
<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>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
3.1 yml
server:
port: 8081
spring:
application:
name: provider-server
cloud:
nacos:
server-addr: 127.0.0.1:8848
discovery:
username: nacos
password: nacos
namespace: public
ephemeral: false
3.2 实现feign 接口的远程服务 controller
@RestController
@RequestMapping("/item")
public class ItemController {
@Value("${server.port}")
private String port;
/**
* 获取商品的信息
*
* @param id
* @return
*/
@GetMapping("/doOrder")
public String doOrder() {
String itemInfo = "订单生成:"+port;
return itemInfo;
}
/**
* 获取商品的信息
*
* @param id
* @return
*/
@GetMapping("/item/{id}")
public String getInfo(@PathVariable(name = "id") String id) {
String itemInfo = "订单信息:"+port;
return itemInfo;
}
Feign 配置
1.feign 日志配置 在consumer工程编写配置类
package com.cloud.config;
/**
* @Author wenbo
* @Date 2022/12/14 10:35
*
* 全局配置: 当使用@Configuration 会将配置作用所有的服务提供方
* 局部配置: 1.通过配置类:如果只想针对某一个服务进行配置,就不要加 @Configuration
* 2.通过配置文件yml
*
**/
@Configuration
public class FeignConfig {
@Bean
public Logger.Level feignLoggerLevel(){
return Logger.Level.FULL;
}
}
1.2 consumer yml 追加 feign 日志配置
server:
port: 8080
spring:
application:
name: consumer-server
cloud:
nacos:
server-addr: 127.0.0.1:8848
discovery:
username: nacos
password: nacos
namespace: public
ephemeral: false
#全局
logging:
level:
com.cloud.feign: debug
#单个服务 也可以在服务层
#@FeignClient(name="provider-server",path = "/item",configuration = FeignConfig.class)
feign:
client:
config:
provider-server:
loggerLevel: BASIC
1.3 负载均衡
分别启动服务访问地址 可以用idea启动多个服务测试feign负载均衡
//下单
http://localhost:8080/order/doOrder
//获取订单
http://localhost:8080/order/getOrder
//nacos 控制台查看服务
http://192.168.10.88:8848/nacos/index.html
1.4 feign 契约配置 contract: feign.Contract.Default
feign:
client:
config:
provider-server:
loggerLevel: BASIC
contract: feign.Contract.Default
注意:
该配置需要改变feign 接口中的spring注解未原生注解
1.5 feign 超时配置
@Bean
public Request.Options options(){
return new Request.Options(5000, TimeUnit.MILLISECONDS, 10000,TimeUnit.MILLISECONDS,false);
}
yml 方式
feign:
client:
config:
provider-server:
loggerLevel: BASIC
connectTimeout: 5000
readTimeout: 3000
1.6 feign拦截器
public class CustomFeignInterceptor implements RequestInterceptor {
private Logger logger = LoggerFactory.getLogger(this.getClass());
@Override
public void apply(RequestTemplate template) {
//记录日志
logger.info("feign拦截器");
//修改请求头
template.header("headName","请求头");
//template.query("id","23");
template.uri("/item/9");
}
}
代码方式
@Bean
public RequestInterceptor basicAuthRequestInterceptor(){
return new CustomFeignInterceptor();
}
yml
feign:
client:
config:
provider-server:
loggerLevel: BASIC
connectTimeout: 5000
readTimeout: 3000
requestInterceptors[0]:
com.cloud.interceptor.feign.CustomFeignInterceptor
nacos 配置中心实现
1.子工程中都添加依赖
<!--配置中心-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
2.创建 bootstrap.yml
# DataId 默认使用 `spring.application.name` 配置跟文件扩展名结合(配置格式默认使用 properties), GROUP 不配置默认使用 DEFAULT_GROUP。因此该配置文件对应的 Nacos Config 配置的 DataId 为 nacos-config.properties, GROUP 为 DEFAULT_GROUP
spring:
application:
name: com.cloud.order
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848
file-extension: yaml
#refresh-enabled: false nacos 将无法感知配置文件改变
namespace: f668dd3a-88a6-43fa-bd7f-360bc6e84cc8
注意:
(1).命名空间不写默认读取的是public ,自定义空间要写空间ID值,要不不生效,public没有ID 就写public 或者不写
(2).服务注册发现中也有命名空间,这里指的是服务要注册到那个环境中
(3).nacos 2.0以后的版本可以没有bootstrap文件,直接写application.yml 文件就可以
详细配置官方文档地址:
https://github.com/alibaba/spring-cloud-alibaba/blob/2021.x/spring-cloud-alibaba-docs/src/main/asciidoc-zh/nacos-config.adoc
3.nacos 其他配置
3.1 通过 spring.cloud.nacos.config.shared-configs来支持多个共享 Data Id 的配置
3.2 通过 spring.cloud.nacos.config.extension-configs来支持多个共享 Data Id 的配置
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848
file-extension: yaml
#refresh-enabled: false nacos 将无法感知配置文件改变
namespace: f668dd3a-88a6-43fa-bd7f-360bc6e84cc8
shared-configs:
- data-id: com.cloud.order-shared.yaml
refresh: true
extension-configs:
- data-id: com.cloud.order-extension.yaml
refresh: true
下标越大优先级越高 extension > shared
注意:
使用 @Value(“${user.name}”) 获取配置文件的值事不会自动刷新需要加上注解
@RefreshScope
Sentinel
官方文档
https://sentinelguard.io/zh-cn/docs/flow-control.html
https://github.com/alibaba/spring-cloud-alibaba/wiki/Sentinel
1.下载控制台
(1)jar 包方式 下载对应的版本jar
https://github.com/alibaba/Sentinel/releases
启动命令
java -Dserver.port=8080 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard.jar
可以配置 win脚本快速启动 start.bat
@echo off
java -Dserver.port=8858 -Dsentinel.dashboard.auth.username=wenbo -Dsentinel.dashboard.auth.password=123456 -Dserver.servlet.session.timeout=120m -jar sentinel-dashboard-1.8.1.jar
pause over
(2)源码方式
https://github.com/alibaba/Sentinel/tree/master/sentinel-dashboard
其他命令参数行
1.-Dsentinel.dashboard.auth.username=sentinel 用于指定控制台的登录用户名为 sentinel
2.-Dsentinel.dashboard.auth.password=123456 用于指定控制台的登录密码为 123456
3.-Dserver.servlet.session.timeout=7200 用于指定 Spring Boot 服务端 session 的过期时间
2.引入依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
注解方式依赖
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-core</artifactId>
<version>1.8.1</version>
</dependency>
3.配置控制台信息
spring:
cloud:
sentinel:
transport:
port: 8719
dashboard: localhost:8080
4.访问控制台
127.0.0.0:8080 输入用户密码初次访问就会出现监控的接口,然后进行服务的监控,流控,降级设置
5.sentinem对feign的支持 ,需要配置文件中配置
feign.sentinel.enabled=true
5.1在 @FeignClient 注解中添加EchoServiceFallback
@FeignClient(name = "service-provider", fallback = EchoServiceFallback.class, configuration = FeignConfiguration.class)
public interface EchoService {
@RequestMapping(value = "/echo/{str}", method = RequestMethod.GET)
String echo(@PathVariable("str") String str);
}
class FeignConfiguration {
@Bean
public EchoServiceFallback echoServiceFallback() {
return new EchoServiceFallback();
}
}
class EchoServiceFallback implements EchoService {
@Override
public String echo(@PathVariable("str") String str) {
return "echo fallback";
}
}
6.sentinel持久化配置 使用nacos
6.1.依赖
<!--sentinel持久 nacos数据源数据源-->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
6.2 yml配置
spring:
sentinel:
transport:
dashboard: 127.0.0.1:8858
web-context-unify: false #支持链路限流
datasource:
sentinel-flow:
nacos:
server-addr: 127.0.0.1:8848
data-id: sentinel
data-type: json
rule-type: flow
Seata 整合
https://github.com/seata/seata
https://seata.io/zh-cn/docs/overview/what-is-seata.html
1.下载相关版本的saata软件包
1.2使用nacos做配置中心(registry.conf)
registry {
# file 、nacos 、eureka、redis、zk、consul、etcd3、sofa
type = "nacos"
nacos {
application = "seata-server"
serverAddr = "127.0.0.1:8848"
group = "SEATA_GROUP"
namespace = ""
cluster = "default"
username = "nacos"
password = "nacos"
}
}
config {
type = "nacos"
nacos {
serverAddr = "127.0.0.1:8848"
group = "SEATA_GROUP"
namespace = ""
username = "nacos"
password = "nacos"
}
}
++小case:++
事务分组: 异地机房停电容错
service.vgroupMapping.my_test_tx_group=default
#my_test_tx_group 需要与客户端保持一致 default 要跟客户端和 registry.conf 中的cluster 保持一致
(客户端properties配置:spring.cloud.alibabab.seata.tx-service-group=my_test_tx_group)
my_test_tx_group可自定义为(gunagzhou.shanghai)对应的client 也要设置
seata.service.vgroup-mapping.projectA=guangzhou
1.2.1 快速将seata配置同步到nacos
1.将seata源码目录script\config-center config.txt 文件
store.mode=db
并修改数据库连接信息
2.执行script\config-center\nacos nacos-config.sh 脚本即可
1.3 使用db做事务支持(file.config)
store {
## store mode: file、db、redis
mode = "db"
## database store property
db {
## the implement of javax.sql.DataSource, such as DruidDataSource(druid)/BasicDataSource(dbcp)/HikariDataSource(hikari) etc.
datasource = "druid"
## mysql/oracle/postgresql/h2/oceanbase etc.
dbType = "mysql"
driverClassName = "com.mysql.jdbc.Driver"
url = "jdbc:mysql://127.0.0.1:3306/seata_cloud"
user = "root"
password = "123456"
minConn = 5
maxConn = 30
globalTable = "global_table"
branchTable = "branch_table"
lockTable = "lock_table"
queryLimit = 100
maxWait = 5000
}
}
1.3.1 数据库脚本
https://github.com/seata/seata/tree/master/script/server/db
2.项目配置
2.1引入依赖
注意:如果引入的是springBoot seata 事务不会指定传递要手动配置
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-seata</artifactId>
</dependency>
2.2 yml 配置 为了保留配置没有放在nacos中 ,在yml直接配置
seata:
registry:
#配置seata的注册中心 ,告诉seata client怎么取访问seata serve(TC)
type: nacos
nacos:
server-addr: 127.0.0.1:8848
application: seata-server
username: nacos
password: nacos
group: SEATA_GROUP
#配置seata 的配置中心
config:
type: nacos
nacos:
server-addr: 127.0.0.1:8848
username: nacos
password: nacos
group: SEATA_GROUP
enable-auto-data-source-proxy: false
注意:因为使用的是mybatis-plus 它支持seata 的整合这里设置代理为false,要不事务会被代理两次 默认为true
enable-auto-data-source-proxy: false
如果你使用mybatis-plus 还需要设置 这里使用 at模式
seata: true
seata-mode: at
3.生产端代码 controller
@GetMapping("/addOrder2")
public String addOrder2() throws TransactionException {
String str = iOrderService.createOrder(2L,2L);
return str;
}
3.1 订单service 通过feign 远程调用库存服务
@Resource
private ItemFeignService itemFeignService;
@Override
@GlobalTransactional(rollbackFor = Exception.class)
public String createOrder(Long productId, Long productSpecs) throws TransactionException {
Order order = new Order();
order.setOrderNumber("HX123456789");
baseMapper.insert(order);
String s = itemFeignService.decStock2();
//int a = 1/0;
System.out.println();
return s;
}
3.2 库存服务代码 int a = 1/0;不管在订单服务端还是库存服务端异常都可以回滚
@GetMapping("/decStock2")
public String decStock2(){
String xid = RootContext.getXID();
System.err.println(xid);
Stock stock = iStockService.getById(12L);
stock.setProductNum(stock.getProductNum() - 1);
iStockService.updateById(stock);
int a = 1/0;
System.out.println();
return "成功";
}
特别注意:
如果使用feign 配置了 fallback 会导致不能回滚
@FeignClient(name="provider-server",configuration = FeignConfig.class,fallback = ItemFeignServiceFallback.class)
处理办法:
(1)在ItemFeignServiceFallback 中手动回滚
@Override
public String decStock2() throws TransactionException {
//手动回滚代码段
GlobalTransactionContext.reload(RootContext.getXID()).rollback();
return "feign限流";
}
(2)在全局异常中统一回滚.比如 GloubalExceptionHandler中
Gatetway
关注稳定与安全
- 全局性流控
- 日志统计
- 防止sql 注入
- 防止web攻击
- 屏蔽工具扫描
- 黑白ip名单
- 证书/加解密处理
提供更好的服务
- 服务级别流控
- 服务降级流控
- 路由与负载均衡
- 服务过滤 聚合与发现
- 权限验证与用户等级策略
- 业务规则与参数校验
- 多级缓存策略
中文文档
https://cloud.tencent.com/developer/article/1403887?from=15425
1.项目搭建
1.1 创建子项目 cloud-test-gateway
1.2添加一依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
1.3配置yml
server:
port: 8082
spring:
application:
name: cloud-gateway
cloud:
gateway:
#路由规则
routes:
- id: order_route #路由的唯一标识
uri: http://127.0.0.1:8080 #需要转发的地址
#断言规则 路由规则匹配
predicates:
- Path=/order-service/**
#http://127.0.0.1:8081/order-service/order/add
filters:
- StripPrefix=1 #转发 前去掉第一层路径
#http://127.0.0.1:8081/order/add
1.4启动gateway 访问原先的接口
http://192.168.10.88:8082/order-service/order/addOrder2
2.getaway的内置断言配置
- AfterRoutePredicateFactory //在该日期时间之后发生的请求都将被匹配
- After=2017-01-20T17:42:47.789-07:00[America/Denver]
- BoforeRoutePredicateFactory //在该日期时间之前发生的请求都将被匹配。
- Before=2017-01-20T17:42:47.789-07:00[America/Denver]
- BetweenRoutePredicateFactory //在datetime1和datetime2之间的请求将被匹配。
- Between=2017-01-20T17:42:47.789-07:00[America/Denver], 2017-01-21T17:42:47.789-07:00[America/Denver]
- Cookie 路由断言 Factory
- Cookie=chocolate, ch.p
- Header 路由断言 Factory
- Header=X-Request-Id, \d+
- Host 路由断言 Factory
- Host=**.somehost.org,**.anotherhost.org
- Method 路由断言 Factory
- Method=GET
- Path 路由断言 Factory
- Path=/foo/{segment},/bar/{segment}
- Query 路由断言 Factory
- Query=baz,and
- RemoteAddr 路由断言 Factory
- RemoteAddr=192.168.1.1/24
- 权重
gateway:
#discovery:
#locator:
#enabled: true
#路由规则
routes:
- id: order_route
uri: lb://com.cloud.order
predicates:
- Weight=group1,8
- id: order_route2
uri: lb://com.cloud.order2
predicates:
- Weight=group1,2
3.自定义路由断言工厂
(1)必须是spring 主键bean
(2)类必须加上RoutePredicateFactory
(3)必须继承AbstractRoutePredicateFactory
(4)必须声明静态的内部类 声明属性来接收配置文件中的断言信息
(5)需要结合shortcutFieldOrder进行绑定
(6)通过apply进行逻辑排断 true 成功
3.1 自定义代码示例
package com.cloud.gateway.predicates;
import lombok.Data;
import org.springframework.cloud.gateway.handler.predicate.AbstractRoutePredicateFactory;
import org.springframework.cloud.gateway.handler.predicate.GatewayPredicate;
import org.springframework.stereotype.Component;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.server.ServerWebExchange;
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
/**
* @Author wenbo
* @Date 2023/1/5 16:55
**/
@Component
public class CheckAuthRoutePredicateFactory extends AbstractRoutePredicateFactory<CheckAuthRoutePredicateFactory.Config> {
public CheckAuthRoutePredicateFactory() {
super(CheckAuthRoutePredicateFactory.Config.class);
}
@Override
public List<String> shortcutFieldOrder() {
return Arrays.asList("name");
}
@Override
public Predicate<ServerWebExchange> apply(Config config) {
return new GatewayPredicate() {
@Override
public boolean test(ServerWebExchange exchange) {
if (config.getName().equals("wenbo")){
return true;
}
return false;
}
};
}
/**
* 接受断言中的配置信息
*/
@Validated
@Data
public static class Config {
private String name;
}
}
4.gateway 拦截器
- 对于所有匹配的请求,这将向下游请求的头中添加 - x-request-foo:bar header
-AddRequestHeader=X-Request-Foo, Bar
- 对于所有匹配的请求,这将向下游请求添加foo=bar查询字符串
-AddRequestParameter=foo, bar
- 于所有匹配的请求,这会将x-response-foo:bar头添加到下游响应的header中
- AddResponseHeader=X-Response-Foo, Bar
- 这将给所有匹配请求的路径加前缀/mypath
- PrefixPath=/mypath
还有很多具体可参考官网查看
4.1自定义getaway路由拦截器代码示例
package com.cloud.gateway.filters;
import lombok.Data;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.List;
/**
* @Author wenbo
* @Date 2023/1/5 17:44
**/
@Component
public class CheckAuthGatewayFilterFactory extends AbstractGatewayFilterFactory<CheckAuthGatewayFilterFactory.Config> {
public CheckAuthGatewayFilterFactory() {
super(Config.class);
}
@Override
public List<String> shortcutFieldOrder() {
return Arrays.asList("value");
}
@Override
public GatewayFilter apply(Config config) {
return (exchange, chain) -> {
String name = exchange.getRequest().getQueryParams().getFirst("name");
if (config.getValue().equals(name)){
return chain.filter(exchange);
}else{
exchange.getResponse().setStatusCode(HttpStatus.NOT_FOUND);
return exchange.getResponse().setComplete();
}
};
}
@Data
public static class Config {
private String value;
}
}
4.2 全局拦截器代码示例
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
/**
* @Author wenbo
* @Date 2023/1/5 18:10
**/
@Component
public class LogFilter implements GlobalFilter {
Logger log = LoggerFactory.getLogger(LogFilter.class);
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
log.info(exchange.getRequest().getPath().value());
return chain.filter(exchange);
}
}
yml 配置实现 其中还配置了 gateway下的跨域
spring:
application:
name: cloud-gateway
cloud:
gateway:
#discovery:
#locator:
#enabled: true #是否启动自动识别nacos 服务
#路由规则
routes:
- id: order_route #路由的唯一标识
uri: lb://com.cloud.order #需要转发的地址 lb: 使用nacos中的本地负载均衡
#断言规则 路由规则匹配
predicates:
- Path=/order-server/**
#- After=2023-01-04T17:42:47.789-07:00[Asia/Shanghai]
#- Header=X-Request-Id,\d+
#- Method=Get
#- Query=name,wenbo|wenbo2
#http://127.0.0.1:8081/order-service/order/add
- CheckAuth=wenbo
filters:
- StripPrefix=1 #转发 前去掉第一层路径
- AddRequestHeader=X-Request-color,red #添加请求头
#- RedirectTo=302,https://www.baidu.com
- CheckAuth=wenbo
#http://127.0.0.1:8081/order/add
globalcors:
corsConfigurations:
'[/**]': #允许跨域访问的资源
allowedOrigins: "http://docs.spring.io" #跨域允许来源
allowedMethods:
- GET
- POST
nacos:
discovery:
server-addr: 127.0.0.1:8848
username: nacos
password: nacos
logging:
config: classpath:logback-spring.xml
filePath: /home/local/program/logs/cloudSpring
5.getaway 和 sentinel的配合使用
5.1 pom加入依赖
<!--sentinel 整合getaway-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
</dependency>
<!--sentinel 依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
5.2 yml配置 sentinel dashboard
sentinel:
transport:
dashboard: 127.0.0.1:8858
#统一的异常返回
scg:
fallback:
mode: response
response-body: "{code:200,msg:降级了}"
5.2.1 异常也可以通过配置类配置
import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.BlockRequestHandler;
import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.GatewayCallbackManager;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.server.ServerResponse;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import javax.annotation.PostConstruct;
/**
* @Author wenbo
* @Date 2023/1/6 13:54
**/
@Configuration
public class GatewayConfig {
@PostConstruct
public void init(){
BlockRequestHandler blockRequestHandler = new BlockRequestHandler() {
//自定义异常
@Override
public Mono<ServerResponse> handleRequest(ServerWebExchange serverWebExchange, Throwable throwable) {
return ServerResponse.status(HttpStatus.OK)
.contentType(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromValue("降级了!"));
}
};
GatewayCallbackManager.setBlockHandler(blockRequestHandler);
}
}
sentinel 整合gateway后的 控制台有些许变化,总的规则还是不变,多了gateway的功能,实际功能更多,更好
skyWalking 链路追踪
Skywalking是一个优秀的国产的开源框架,支持Java、.Net、NodeJs等探针,数据存储支持Mysql、Elasticsearch等,跟Pinpoint一样采用字节码注入的方式实现代码的无侵入,探针采集数据粒度粗,但性能表现优秀,且对云原生支持,目前增长势头强劲,社区活跃。
是分布式系统的应用程序性能监视工具,专为微服务,云原生架构和基于容器(Docker,K8S,Mesos)架构而设计,它是一款优秀的APM(Application Performance Management)工具,包括了分布式追踪,性能指标分析和服务依赖分析等。
网站:
官网:http://skywalking.apache.org
下载:http://skywalking.apache.org/downloads
Github:https://github.com/apache/skyWalking
文档:https://skywalking.apache.org/docs/skywalking-showcase/next/readme/
中文文档:https://skyapm.github.io/document-cn-translation-of-skywalking/
1.搭建 skyWalking
1.1 先去官网下载 启动包 ,目前已经升级到9.xx 的包,以前8.xx的包自带 agent 目录文件 现在要单独下载
apache-skywalking-apm-9.0.0.tar.gz
apache-skywalking-java-agent-8.13.0.tgz
1.1.1 自定义客户端端口
webapp\webapp.yml
1.1.2 skyWalking 存储方式 ,注册方式配置
\config\application.yml #mysql创建好数据库表会在服务启动时创建 注意可能会报数据库连接异常 在\oap-libs\ 目录下添加mysql 连接jar 即可
1.13 windows 环境idea VM 配置服务接入
-javaagent:D:\tools\apache-skywalking-apm-9.0.0\apache-skywalking-apm-bin\agent\skywalking-agent.jar
-DSW_AGENT_NAME=consumer-service
-DSW_AGENT_COLLECTOR_BACKEND_SERVICES=127.0.0.1:11800
注意:
如果在gateway 接入是不成功的 需要做以下步骤:
将\agent\optional-plugins\apm-spring-cloud-gateway-2.1.x-plugin-8.13.0.jar 复制到\agent\plugins下
linux 下可编写脚本
# !/bin/sh
# Skywalking Agent配置
export SW_AGENT_MANE=springboot-skywalking-deno ngont 名字,一般使用`spring.application.nameexport
export SW_AGENT_COLLECTOR_BACKEND_SERVICES=127.0.0.1:11800#配置collector地址。
export SW_AGENT_SPAN_LIMIT=2000 #配置链路的最大Span数量,默认为300。
export JAVA_AGENT=-javaagent:/usr/local/soft/apache-skywalking/agent/skywalking-agent.jar
java $JAVA_AGENT -jar springboot-skywalking-demo-0.0.1-SNAPSHOT.jar #jar启动
2.skyWalking 链路参数 和返回值支持
2.1 添加依赖
<!-- Skywalking工具类-->
<dependency>
<groupId>org.apache.skywalking</groupId>
<artifactId>apm-toolkit-trace</artifactId>
<version>8.4.0</version>
</dependency>
2.2 业务方法上添加注解
@Trace
@Tag(key = "addOrder2",value = "returnedObj")
public String createOrder(Long productId, Long productSpecs) throws TransactionException {}
2.2.1 既有返回值又有参数
@Trace
@Tags({
@Tag( key = "createOrder",value = "returnedObj"),
@Tag(key = "createOrder",value = "arg[0]")})
public String createOrder(Long productId, Long productSpecs) throws TransactionException {}
或者
@Override
@GlobalTransactional(rollbackFor = Exception.class)
@Trace
@Tag(key = "addOrder2",value = "returnedObj")
@Tag(key = "addOrder2",value = "arg[0]")
@Tag(key = "addOrder2",value = "arg[1]")
public String createOrder(Long productId, Long productSpecs) throws TransactionException {}
3.skyWalking 日志配置 这里配置logback
3.1 添加依赖
<dependency>
<groupId>org.apache.skywalking</groupId>
<artifactId>apm-toolkit-logback-1.x</artifactId>
<version>8.10.0</version>
</dependency>
3.2 在logback.xml的Pattern部分中设置%tid
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
<layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout">
<Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%tid] [%thread] %-5level %logger{36} -%msg%n</Pattern>
</layout>
</encoder>
</appender>
3.3 将日志上传到 skyWalking
在logback-spring.xml 中追加
<appender name="grpc-log" class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.log.GRPCLogClientAppender">
<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
<layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.mdc.TraceIdMDCPatternLogbackLayout">
<Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%X{tid}] [%thread] %-5level %logger{36} -%msg%n</Pattern>
</layout>
</encoder>
</appender>
3.4输出
<root level="${log.lever}">
<appender-ref ref="consoleAppender"/>
<appender-ref ref="grpc-log"/>
</root>
注意 : 如果不是本地服务需要配置 \agent\config\agent.config
plugin.toolkit.log.grpc.reporter.server_host=${SW_GRPC_LOG_SERVER_HOST:127.0.0.1}
plugin.toolkit.log.grpc.reporter.server_port=${SW_GRPC_LOG_SERVER_PORT:11800}
plugin.toolkit.log.grpc.reporter.max_message_size=${SW_GRPC_LOG_MAX_MESSAGE_SIZE:10485760}
plugin.toolkit.log.grpc.reporter.upstream_timeout=${SW_GRPC_LOG_GRPC_UPSTREAM_TIMEOUT:30}
4.skyWalking 告警配置
在apache-skywalking-apm-bin\config\alarm-settings.yml 中配置规则 和回调接口来触发报警功能
4.1 参数介绍
include names: 本规则告警生效的实体名称,如服务名,终端名;
exclude-names:将此规则作用于不匹配的实体名称上,如服务名,终端名;
threshold: 阈值,可以是一个数组,即可以配置多个值;
op: 操作符, 可以设定 >, <, =;
period: 多久检查一次当前的指标数据是否符合告警规则;以分钟为单位
count: 超过阈值条件,达到count次数,触发告警;
silence period:在同一个周期,指定的silence period时间内,忽略相同的告警消息;
**微信公众号扫码关注喔**