springCloud Alibaba 看完这篇就够

这篇文章主要讲述了 :
springCloud Alibaba 下的

  • Nacos
  • openFeign
  • sentinel
  • seata
  • springCloud下的Gatetway
  • skyWalking
    等详细搭建和使用过程
版本依赖:
名称版本说明
cloud alibaba2.2.6 RELEASE
spring boot2.3.2.RELEASE
spring cloudHoxton.SR9
nacos1.4.2
openFeign10.10.1跟随cloud主版本
sentinel1.8.1
seata1.3.0跟随cloud主版本
Gatetway2.2.6.RELEASE
skyWalking9.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, GROUPDEFAULT_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时间内,忽略相同的告警消息;
								**微信公众号扫码关注喔**

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值