实战springcloud alibaba

发布于:2025-05-11 ⋅ 阅读:(16) ⋅ 点赞:(0)

实战springcloud alibaba

一、版本介绍

springcloud springboot springcloudalibaba 持久层框架 注册中心/配置中心 熔断、限流 数据库 缓存/分布式锁 数据库连接池 远程调用 分布式事务 消息队列 定时任务 大数据存储 文档生成 链路追踪 服务监控
2023.0.3 3.3.5 2023.0.1.2 mybatis-flex1.10.9 nacos2023.0.1.2(nacos服务端使用2.3.2) sentinel2023.0.1.2(dashboard使用1.8.8) mysql8 redis 德鲁伊 druid open-feign seata kafka xxl-job2.5.0 elasticsearch7.9.3 springdoc-openapi-starter-webmvc-ui Sky walking promothus+grafana

二、组件nacos作注册中心、配置中心

2.1 导入包
 <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-nacos-config</artifactId>
        </dependency>

这里的版本与springcloud alibaba一致:2023.0.1.2

2.2 配置yml(bootstrap.yml优先级高,所以配置nacos的连接写在bootstrap.yml)
spring:
  application:
    # 应用名称
    name: mfcx-admin-service
  profiles:
    # 环境配置
    active: dev
  cloud:
    nacos:
      discovery:
        # 服务注册地址
        server-addr: 192.168.174.192:8848
        #        namespace: dev # 命名空间。这里使用 dev 开发环境
        group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP
      config:
        # 配置中心地址
        server-addr: 192.168.174.192:8848
        #        namespace: dev # 命名空间。这里使用 dev 开发环境
        group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP
        # 配置文件格式
        file-extension: yaml
        # 共享配置
        shared-configs:
          - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
        extension-configs:
          - data-id: mfcx-admin-service-bak-info.yaml
            group: DEFAULT_GROUP
            refresh: true

如上: 没有配置那么space,那么使用的是public,分组用的是DEFAULT_GROUP。
配置文件:
1、会读取默认的nacos配置文件名,文件如下:${spring.application.name}-${spring.profile.active}.${spring.cloud.nacos.config.file-extension}
例如,我的配置文件名为: mfcx-admin-service-dev.yaml
2、共享配置,即每个微服务都可以读取到:application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
例如:application-dev.yaml
3、延伸配置,即extension-configs指定的文件名 mfcx-admin-service-bak-info.yaml

2.3 注解

主启动类加上注解 @EnableDiscoveryClient

三、网关gateway

3.1 导入包
 <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
            <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-loadbalancer</artifactId>
        </dependency>
         <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bootstrap</artifactId>
        </dependency>

注:
1.网关引入的是spring-cloud-starter-gateway,而非spring-boot-starter-web
2.在SpringCloud 2020.* 以后版本把 bootstrap 禁用了,导致在读取文件的时候读取不到而报错,所以我们只要把 spring-cloud-starter-bootstrap从新导入进来就会生效了
3.Spring Cloud 2020 版本后移除了 Netflix Ribbon,spring-cloud-starter-loadbalancer 是其官方替代品: 为微服务间的 HTTP/RPC 调用提供 服务实例选择能力,并处理请求的负载均衡逻辑所以网关需引入spring-cloud-loadbalancer
如上使用的版本号分别为:4.1.5、4.1.4、4.1.4

3.2 配置动态路由
spring:
  cloud:
    gateway:
      discovery:
        locator:
          lowerCaseServiceId: true
          enabled: true
      routes:
        # 认证中心
        - id: mfcx-auth-service
          uri: lb://mfcx-auth-service
          predicates:
            - Path=/auth/**
          filters:
            - RewritePath=/auth/(?<segment>.*),/$\{segment}

        - id: mfcx-admin-service
          uri: lb://mfcx-admin-service
          predicates:
            - Path=/admin/**
          filters:
           #重写路径,例如:localhost:8080/admin/userInfo/queryUserInfoByUserId 在进入/mfcx-admin-service服务后路径为/userInfo/queryUserInfoByUserId
            - RewritePath=/admin/(?<segment>.*),/$\{segment}

四、文档springdoc-openapi-starter-webmvc-ui

4.1 引入包
 <dependency>
            <groupId>org.springdoc</groupId>
            <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
        </dependency>
4.2 yml配置
springdoc:
  api-docs:
    enabled: true
    path: /v3/api-docs
  swagger-ui:
    path: /swagger-ui.html
    enabled: true
4.3 写配置类,可以分模块(每个类一个模块)
@Configuration
public class Swagger3Config {

	/**
	* 这里配置多模块,即每个控制器为一个分类,也可以不配置下面的Bean,那么就是该微服务所有接口都在一起
	**/
    @Bean
    public GroupedOpenApi UserApi() {
        return GroupedOpenApi.builder().group("系统用户模块").pathsToMatch("/userInfo/**").build();
    }

    @Bean
    public GroupedOpenApi RoleApi() {
        return GroupedOpenApi.builder().group("系统角色模块").pathsToMatch("/roleInfo/**", "/others").build();
    }
    /*@Bean
    public GroupedOpenApi CustomerApi()
    {
        return GroupedOpenApi.builder().group("客户微服务模块").pathsToMatch("/customer/**",
        "/customers").build();
    }*/

    @Bean
    public OpenAPI docsOpenApi() {
        return new OpenAPI()
                .info(new Info().title("神雕出行")
                        .description("通用设计rest")
                        .version("v1.0"))
                .externalDocs(new ExternalDocumentation()
                        .description("www.123.com")
                        .url("https://www.baidu.com/"));
    }
}
4.4 注解

在类上面:@Tag(name = "登录接口")
在方法上面:@Operation(summary = "登录")
在字段或属性类上面:@Schema(description = "用户名")

五、远程调用:open-feign的使用

5.1 消费方引入包
  <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
 </dependency>
5.2 标注解

消费方主启动类标注解 @EnableFeignClients(basePackages = “com.mfcx.cloud.feign”)

注意这里的feign接口在其他模块api,这里需要指定包路径

5.3 feign接口的编写
@FeignClient(value = "mfcx-auth-service",
        path = "/remote/auth",
      //  configuration = FeignConfiguration.class,
        fallback = AuthApiFeignClientCallBack.class)
public interface AuthApiFeignClient {

    @PostMapping("/queryGoodsDetail")
    List<GoodsDetailVO> queryGoodsDetail();
}

注:这里的value =
“mfcx-auth-service"与服务方的微服务名称一致,path的路径与feign接口的实现类上的注解@RequestMapping(”/remote/auth")一致

5.4 超时机制
spring:
  cloud:
    openfeign:
      client:
        config:
		#全局超时配置
          default:
            # 连接超时时间 3秒
            connectTimeout: 3000
            # 读取超时时间 3秒
            readTimeout: 3000
            # mfcx-auth-service 服务的超时时间(他会覆盖全局配置)
          mfcx-auth-service:
            connectTimeout: 5000
            readTimeout: 5000
5.5 设置重试机制
@Configuration
public class FeignConfig {
    @Bean
    public Retryer retryer() {
        // 重试间隔时间,重试最大时间,最大重试次数(初始1次,重试2次)
        return new Retryer.Default(1000, 1000, 3);
    }
}

注:这里配置的是feign调用失败,允许再次尝试的参数

5.6 使用http client5 替换http,大幅提升性能

引入包

 <dependency>
        <groupId>org.apache.httpcomponents.client5</groupId>
        <artifactId>httpclient5</artifactId>
    </dependency>
    <dependency>
        <groupId>io.github.openfeign</groupId>
        <artifactId>feign-hc5</artifactId>
    </dependency>

修改配置

spring:
  cloud:
    openfeign:
      #使用HttpClient5  替换http,参考官网:https://docs.spring.io/spring-cloud-openfeign/reference/spring-cloud-openfeign.html
      httpclient:
        hc5:
          enabled: true
      client:
        config:
          # openfeign全局超时时间配置
          default:
            # 连接超时时间 3秒
            connectTimeout: 3000
            # 读取超时时间 3秒
            readTimeout: 3000
            # mfcx-auth-service 服务的超时时间(他会覆盖全局配置)
          mfcx-auth-service:
            connectTimeout: 5000
            readTimeout: 5000
5.7 对请求和响应进行GZIP压缩

对请求和响应进行GZIP压缩
Spring Cloud OpenFeign支持对请求和响应进行GZIP压缩,以减少通信过程中的性能损耗。
通过下面的两个参数设置,就能开启请求与相应的压缩功能:
开启请求压缩: spring.cloud.openfeign.compression.request.enabled=true
压缩的数据类型: spring.cloud.openfeign.compression.request.mime-types=text/xml,application/xml,application/json
触发压缩的大小: spring.cloud.openfeign.compression.request.min-request-size=2048
开启返回压缩 : spring.cloud.openfeign.compression.response.enabled=true

5.8 打印feign日志

配置类加一个Bean

@Configuration
public class FeignConfig {
    @Bean
    public Retryer retryer() {
        // 重试间隔时间,重试最大时间,最大重试次数(初始1次,重试2次)
        return new Retryer.Default(1000, 1000, 3);
    }
    //feign 提供了日志打印功能,我们可以通过配置来调整日志级别,
    //从而了解 Feign 中 Http 请求的细节,
    //说白了就是对Feign接口的调用情况进行监控和输出
    @Bean
    public Logger.Level logLevel() {
        return Logger.Level.FULL;
    }
}

yml配置

logging:
  level:
    com:
      mfcx:
        cloud:
          feign:
            AuthApiFeignClient: debug

注: 其中com.mfcx.cloud.feign.AuthApiFeignClient是接口(标记@FeignClient的接口),配置了日志,能清楚的看到远程调用的重试次数及失败原因

六、服务降级 sentinel

6.1 导包
     <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
   </dependency>
6.2 yml配置

服务端连接sentinel大盘

spring:
    sentinel:
      transport:
        dashboard: localhost:8080 #配置Sentinel dashboard控制台服务地址
        port: 8719 #默认8719端口,假如被占用会自动从8719开始依次+1扫描,直至找到未被占用的端口

消费端激活Sentinel对Feign的支持

feign:
  sentinel:
    enabled: true
6.3 feign接口配置回退类,AuthApiFeignClientCallBack
@FeignClient(value = "mfcx-auth-service",
        path = "/remote/auth",
        fallbackFactory = AuthApiFeignClientCallback.class)
public interface AuthApiFeignClient {

    @PostMapping("/queryUserInfo")
    List<UserInfoResDTO> queryUserInfo(@RequestBody UserInfoReqDTO userInfo);

    @PostMapping("/queryUser")
    UserInfoResDTO queryUser();

    @PostMapping("/queryUserByname")
    CommonResult<List<UserInfoResDTO>> queryUserByName(@RequestBody UserInfoReqDTO userInfo);
}
6.4 编写回退类AuthApiFeignClientCallBack
@Component
@Slf4j
public class AuthApiFeignClientCallback implements FallbackFactory<AuthApiFeignClient> {

    @Override
    public AuthApiFeignClient create(Throwable cause) {

        return new AuthApiFeignClient() {
            @Override
            public List<UserInfoResDTO> queryUserInfo(UserInfoReqDTO userInfo) {

                log.error("[Fallback] 调用 mfcx-auth-service queryUserInfo失败,原因:{}", cause.getMessage());
                return List.of();
            }

            @Override
            public UserInfoResDTO queryUser() {
                log.error("[Fallback] 调用 mfcx-auth-service queryUser失败,原因:{}", cause.getMessage());
                return new UserInfoResDTO();
            }

            @Override
            public CommonResult queryUserByName(UserInfoReqDTO userInfo) {
                log.error("[Fallback] 调用 mfcx-auth-service queryUser失败,原因:{}", cause.getMessage());
                CommonResult result = CommonResult.error(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR);
                return result;
            }
        };
    }
}
6.5 显示声明回退类

因为AuthApiFeignClientCallBack 位于 mfcx-auth-api 模块,在消费方需要显示声明此对象

@Configuration
public class FeignConfig {
    @Bean
    public Retryer retryer() {
        // 重试间隔时间,重试最大时间,最大重试次数(初始1次,重试2次)
        return new Retryer.Default(1000, 1000, 3);
    }
    //feign 提供了日志打印功能,我们可以通过配置来调整日志级别,
    //从而了解 Feign 中 Http 请求的细节,
    //说白了就是对Feign接口的调用情况进行监控和输出
    @Bean
    public Logger.Level logLevel() {
        return Logger.Level.FULL;
    }

    /**
     * 显式声明回退工厂 Bean
     * @return
     */
    @Bean
    public AuthApiFeignClientCallBack authApiFeignClientCallBack() {
        return new AuthApiFeignClientCallBack();
    }
}

七、sentinel实现网关限流

这里采用gateway+nacos+sentinel实现网关动态限流

7.1 引包
   <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>

        <!-- SpringCloud Alibaba Sentinel Gateway -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
        </dependency>

        <!-- Sentinel Datasource Nacos -->
        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-datasource-nacos</artifactId>
        </dependency>
7.2 主启动类加一行代码,添加此代码,在Sentinel控制台中做判断使用
System.setProperty("csp.sentinel.app.type", "1");
7.3 添加yml配置
spring:
  cloud:
    sentinel:
      transport:
        dashboard: 192.168.10.181:8858
        port: 8719
      eager: true
      datasource:
        ds1:
          nacos:
          # nacos地址
            server-addr: 192.168.10.181:8848
            # 配置文件名
            data-id: gateway-flow-rule-sentinel
            # 分组
            group-id: DEFAULT_GROUP
            # 类型
            data-type: json
            # 固定,网关流控
            rule-type: gw-flow
            #命名空间
            namespace: 0b911c8b-a723-4af0-a4d0-9fa7c0a579bb
        ds2:
          nacos:
            server-addr: 192.168.10.181:8848
            data-id: gateway-flow-rule-api-sentinel
            group-id: DEFAULT_GROUP
            data-type: json
            # 固定,分组流控
            rule-type: gw-api-group
7.4 写两个配置类

加载nacos中的限流数据配置类

@Slf4j
@Configuration
public class GatewayConfiguration {
   @Value("${spring.cloud.nacos.config.server-addr}")
    private String nacosAddr;
    @Value("${spring.cloud.nacos.config.group}")
    private String group;
    private final List<ViewResolver> viewResolvers;
    private final ServerCodecConfigurer serverCodecConfigurer;

    public GatewayConfiguration(ObjectProvider<List<ViewResolver>> viewResolversProvider,
                                ServerCodecConfigurer serverCodecConfigurer) {
        this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList);
        this.serverCodecConfigurer = serverCodecConfigurer;
    }

    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() {
        // Register the block exception handler for Spring Cloud Gateway.
        return new SentinelGatewayBlockExceptionHandler(viewResolvers, serverCodecConfigurer);
    }
   @PostConstruct
    public void doInit() {
        // 注册 API 分组规则
        ReadableDataSource<String, Set<ApiDefinition>> apiDefinitionSource =
                new NacosDataSource<>(nacosAddr,
                        group,
                        "gateway-flow-rule-api-sentinel",
                        source -> JSON.parseObject(source, new TypeReference<>() {
                        }));

        GatewayApiDefinitionManager.register2Property(apiDefinitionSource.getProperty());

        // 注册网关限流规则
        ReadableDataSource<String, Set<GatewayFlowRule>> flowRuleSource =
                new NacosDataSource<>(nacosAddr,
                        group,
                        "gateway-flow-rule-sentinel",
                        source -> JSON.parseObject(source, new TypeReference<>() {
                        }));

        GatewayRuleManager.register2Property(flowRuleSource.getProperty());

        // 打印当前规则信息
        Set<GatewayFlowRule> rules = GatewayRuleManager.getRules();
        System.out.println("限流规则数量:" + rules.size());
        rules.forEach(rule -> System.out.println("Rule: " + rule));
    }
//    @Bean
//    @Order(Ordered.HIGHEST_PRECEDENCE)
//    public GlobalFilter sentinelGatewayFilter() {
//        return new SentinelGatewayFilter();
//    }

}

限流返回数据格式配置类

@Configuration
public class SentinelGatewayConfig {

    public SentinelGatewayConfig() {
        GatewayCallbackManager.setBlockHandler(new BlockRequestHandler() {
            @Override
            public Mono<ServerResponse> handleRequest(ServerWebExchange exchange, Throwable t) {
               // R error = R.error(500, "限流啦 别在试啦");
                Map<Object,Object> map = new HashMap<>();
                map.put(500, "限流啦 别在试啦");
                String errorStr = JSON.toJSONString(map);
                Mono<ServerResponse> just = ServerResponse.ok().body(Mono.just(errorStr), String.class);
                return just;
            }
        });
    }
}
7.5 nacos中的配置

文件 gateway-flow-rule-sentinel,格式 json

[
    {
    "resource": "mfcx-auth-service",
    "resourceMode": 0,
    "count": 15,
    "intervalSec": 60
  },
  {
    "resource": "mfcx-auth-service-api",
    "resourceMode": 1,
    "count": 4,
    "intervalSec": 60
   },
   {
    "resource": "mfcx-admin-service-api",
    "resourceMode": 1,
    "count": 5,
    "intervalSec": 60
   }
]

文件 gateway-flow-rule-api-sentinel ,格式:json

[{
 "apiName": "mfcx-admin-service-api",
    "predicateItems": [
      {
        "pattern": "/admin/feign/user/queryUserInfo"
      },
      {
        "pattern":"/admin/feign/user/queryUser",
         "matchStrategy": 0
      }
    ]
}]

含义解释:

resource:表示限流的资源名称,这里是针对认证服务整体进行限流
resourceMode: 0=服务, 1=API, 2=自定义 流控粒度
count: 在统计时间窗口内允许的最大请求数量
intervalSec:统计时间窗口长度(秒)
apiName:定义这组路由规则的名称标识,与resourceMode为1 的resource对应
predicateItems: 路由断言规则数组,定义匹配请求路径的规则集合,决定哪些请求路径会被路由到目标分组
pattern:路径匹配
matchStrategy: 0=精确 1=前缀 2=正则 3=包含,默认为0

八、引入mybatis-flex

8.1 导包
  <!--数据库相关-->
    <dependency>
        <groupId>com.mybatis-flex</groupId>
        <artifactId>mybatis-flex-spring-boot3-starter</artifactId>
    </dependency>

    <dependency>
        <groupId>com.mybatis-flex</groupId>
        <artifactId>mybatis-flex-processor</artifactId>
    </dependency>
    <dependency>
        <groupId>com.mysql</groupId>
        <artifactId>mysql-connector-j</artifactId>
    </dependency>

    <!--其中包含mybatis-spring-boot-starter-->
    <dependency>
        <groupId>com.github.pagehelper</groupId>
        <artifactId>pagehelper-spring-boot-starter</artifactId>
        <exclusions>
            <!-- 保留 mybatis-spring-boot-starter 但排除特定传递依赖 -->
            <exclusion>
                <groupId>org.mybatis</groupId>
                <artifactId>mybatis</artifactId>
            </exclusion>
            <exclusion>
                <groupId>org.mybatis</groupId>
                <artifactId>mybatis-spring</artifactId>
            </exclusion>
        </exclusions>
    </dependency>

其中的版本号一次是:1.10.9、1.10.9、8.3.0、2.1.0

8.2 引入数据库相关配置
spring:
  datasource:
    username: root
    password: 123456
    url: jdbc:mysql://192.168.174.192:3307/tfx_user?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&serverTimezone=Asia/Shanghai
    driver-class-name: com.mysql.cj.jdbc.Driver
  mybatis-flex:
    mapper-locations: classpath*:/mapper/**/*.xml
    configuration:
      map-underscore-to-camel-case: true

至此,mybatis-flex就引入了项目。
Mapper层的写法,

@Mapper
public interface UserInfoMapper extends BaseMapper<UserInfo> {
}

实体类的写法

@Data
@Table("user_info")
public class UserInfo {
    //雪花算法自动生成主键
    @Id(keyType = KeyType.Generator,value = KeyGenerators.snowFlakeId)
    private Long id;
    private String name;
    private String addr;
    private Long roleId;
}

九、分布式事务seata

seata的详细引入过程


网站公告

今日签到

点亮在社区的每一天
去签到