SpringCloud Alibaba完整使用

简介: SpringCloud Alibaba 微服务全栈实战教程,从零带你搭建 Nacos 注册配置中心、Gateway 网关、Sentinel 限流熔断、Seata 分布式事务、OpenFeign 远程调用等完整微服务组件。配套全套视频教程 + 保姆级搭建文档,手把手教你跑通微服务项目,适合在校生、转行及 1-3 年后端开发者学习练手、简历加分,文末可领学习资料与技术交流群。

@TOC

资料领取

可以学到微服务里面的各种组件搭建使用教程、6666

1、视频学习

我的视频搭建教程

《小白必看!SpringCloudAlibaba微服务全栈开发实战》

2、学习搭建网站

小白简历包装,简历优化

3、技术交流QQ群

加入开发社区

4、源码地址

https://gitee.com/yswyn_admin/cloud_api

一、AlibabaCloud微服务初级篇依赖认知

1、版本依赖关系讲解

1)官方网站

gitHup地址

2)采取毕业版本依赖关系

由于 Spring Boot 2.4+ 和以下版本之间变化较大,目前企业级客户老项目相关 Spring Boot 版本仍停留在
 Spring Boot 2.4 以下,为了同时满足存量用户和新用户不同需求,社区以 Spring Boot 2.4 为分界线,
 同时维护 2.2.x 和 2021.x 两个分支迭代。

2、Cloud Alibaba Maven坐标

Spring Cloud Alibaba Version 2021.0.1.0
Spring Cloud Version Spring Cloud 2021.0.1
Spring Boot Version 2.6.3
Sentinel Version 1.8.3
Nacos Version 1.4.2
RocketMQ Version 4.9.2
Seata Version 1.4.2

3、2021.0.1.0升级指南

1)升级指针

升级版本 (注意版本对应关系)

<dependencyManagement>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-dependencies</artifactId>
        <version>2.6.3</version>
        <type>pom</type>
        <scope>import</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-dependencies</artifactId>
        <version>2021.0.1</version>
        <type>pom</type>
        <scope>import</scope>
    </dependency>
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-alibaba-dependencies</artifactId>
        <version>2021.0.1.0</version>
        <type>pom</type>
        <scope>import</scope>
    </dependency>
</dependencyManagement>

2)官网

githup官网

4、官网地址收集

1)Cloud Alibaba官网组件大全

Cloud Alibaba官网组件大全

2)Cloud Alibaba依赖关系

Cloud Alibaba依赖关系

3)Cloud Alibaba 2021.0.1.0 升级定制指南

升级定制指南

4)Cloud Alibaba Nacos 版本大全

Cloud Alibaba Nacos 版本大全

5)Cloud Alibaba Sentinel 版本大全

Cloud Alibaba Sentinel 版本大全

5、虚拟机搭建

虚拟机搭建教程地址

二、AlibabaCloud微服务运维篇环境搭建

1、虚拟机搭建

1)搭建学习地址

搭建学习教程地址

2)百度到哔哩哔哩

在这里插入图片描述

3)下载VMware16

下载VMware16官网文档

4)安装

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

3、Docker-compose搭建Maven私服

在这里插入图片描述

4、Docker-compose搭建Nacos搭建

在这里插入图片描述

5、Docker-compose搭建mysql数据库

在这里插入图片描述

6、Docker-compose搭建Sentinel限流服务

在这里插入图片描述

7、Docker-compose搭建Zipkin链路追踪

在这里插入图片描述

8、Docker-compose搭建Elasticsearch

在这里插入图片描述

9、Docker-compose搭建Redis

在这里插入图片描述

10、Docker-compose搭建RebaitMQ

在这里插入图片描述

11、Docker-compose搭建 Nginx

在这里插入图片描述

12、kafka集群搭建

在这里插入图片描述

13、DNS解析

在这里插入图片描述

14、Docker-compose搭建MogoDB

在这里插入图片描述

15、Docker-compose搭建RocketMQ

在这里插入图片描述

16、docker-compose安装

在这里插入图片描述

三、AlibabaCloud微服务组件与搭建模型

1、模块划分

cloud_api             聚合服务
    cloud_commont     工具服务
    cloud_party          图片服务
    cloud_login       登录服务
    cloud_gateway     网关服务
    cloud_admin       数据监控服务
    cloud_production  数据生产服务
    cloud_data        数据清洗服务
    cloud_ouath       接口认证服务
    cloud_log         日志服务

2、搭建模块

**IDEA 2021 工具搭建**

搭建前提先看我视频搭建下要的环境
视频地址 点我进行观看

1)聚合工程搭建

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

(1) 给聚合父POM增加依赖

<distributionManagement>
    <repository>
        <!--此名称要和.m2/settings.xml中设置的ID一致 -->
        <id>nexus</id>
        <name>Nexus Releases Repository</name>
        <url>http://192.168.2.110:8081/repository/maven-releases/</url>
    </repository>
    <snapshotRepository>
        <!--此名称要和.m2/settings.xml中设置的ID一致 -->
        <id>nexus</id>
        <name>Nexus Snapshots Repository</name>
        <url>http://192.168.2.110:8081/repository/maven-snapshots/</url>
    </snapshotRepository>
</distributionManagement>

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.6.3</version>
    <relativePath/>
</parent>

<dependencies>
    <!--由于2021版本去除了-bootstrap.yml支持、所以我们要加上去-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-bootstrap</artifactId>
    </dependency>
</dependencies>

<!--2021毕业版本依赖-->
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>2.6.3</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>2021.0.1</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-dependencies</artifactId>
            <version>2021.0.1.0</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

<!--maven插件-->
<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>
                <mainClass>none</mainClass>     <!-- 取消查找本项目下的Main方法:为了解决Unable to find main class的问题 -->
                <classifier>execute</classifier>    <!-- 为了解决依赖模块找不到此模块中的类或属性 -->
            </configuration>
            <executions>
                <execution>
                    <goals>
                        <goal>repackage</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

(2) 全局动态切换环境

配置到父pom里面

<!--统一环境-->
<profiles>
    <profile>
        <id>prod</id>
        <properties>
            <profiles.active>prod</profiles.active>
        </properties>
        <activation>
            <activeByDefault>true</activeByDefault>
        </activation>
    </profile>
    <profile>
        <id>dev</id>
        <properties>
            <profiles.active>dev</profiles.active>
        </properties>
    </profile>
</profiles>

在这里插入图片描述

2)创建工具服务

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3)图片服务

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

4)登陆服务

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

5)网关服务

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

6)数据监控服务

在这里插入图片描述

7)数据生产服务

在这里插入图片描述

8)数据清洗服务

在这里插入图片描述

9)接口认证服务

在这里插入图片描述

3、全部服务统一配置环境

1)创建三个yml

application.yml
application-dev.yml
application-prod.yml

在这里插入图片描述

2)整体端口和服务名称配置

给 application.yml 配置文件添加如下

server:
  port: 8087
spring:
  profiles:
    active: dev
  application:
    name: 自己的服务名称比如/cloud-log

3)全部服务统一包名的昵称

创建每个服务的包名

com.cloud.api

在这里插入图片描述

4)全部服务增加启动类配置

@SpringBootApplication
public class APP {
   
    public static void main(String[] args) {
   
    //APP 每个服务的名称开头比如 APILogSpringApplication
        SpringApplication.run(APP.class, args);
    }
}

4、配置IDEA的Run DashBoard模式

在这里插入图片描述

(1) 给Workspace.xml 新增如下配置

  <component name="RunDashboard">
    <option name="configurationTypes">
      <set>
        <option value="SpringBootApplicationConfigurationType" />
      </set>
    </option>
    <option name="ruleStates">
      <list>
        <RuleState>
          <option name="name" value="ConfigurationTypeDashboardGroupingRule" />
        </RuleState>
        <RuleState>
          <option name="name" value="StatusDashboardGroupingRule" />
        </RuleState>
      </list>
    </option>
  </component>

(2) 启动不成功

在这里插入图片描述

需要配置


    <artifactId>改成自己的服务</artifactId>
    <groupId>com.cloud.api</groupId>
    <version>1.0-SNAPSHOT</version>
    <modelVersion>4.0.0</modelVersion>

 <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.6.3</version>
        <relativePath/>
    </parent> 

   <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
</dependencies>  

  <!--2021毕业版本依赖-->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>2.6.3</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>2021.0.1</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>2021.0.1.0</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

5、配置cloud-Admin微服务模块

1)新增监控server依赖

<dependency>
    <groupId>de.codecentric</groupId>
    <artifactId>spring-boot-admin-starter-server</artifactId>
    <version>2.5.1</version>
</dependency>

2)启动类怎加注解

@EnableAdminServer

3)监控配置暴漏

spring:
  boot:
    admin:
      client:
        # Admin Server的URL,若是要注册到多个admin服务端上,用逗号分隔就可以
        # url: http://localhost:8080,http://localhost:8081
        url: http://192.168.2.110:3005
        instance:
          # 使用IP的方式
          prefer-ip: true

management:
  endpoint:
    health:
      show-details: always  # 显示health指标的详细信息,否则只会显示 status
  #  默认情况下,大多数Actuator端点都不通过http公开,这里我们公开了所有端点。
  #  对于生产,您应该仔细选择要公开的端点。

  endpoints:
    web:
      exposure:
        include: ["*"]

6、配置Cloud-common服务

1)增加依赖

这个是针对每一个服务需要注册到Admin服务的客户端

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

2)每个服务新增客户端配置

在resources 下创建application.properties
在这里插入图片描述

# Admin Server的URL,若是要注册到多个admin服务端上,用逗号分隔就可以
# url: http://localhost:8080,http://localhost:8081
spring.boot.admin.client.url=http://localhost:3000
#使用IP的方式
spring.boot.admin.client.instance.prefer-ip=true

#  默认情况下,大多数Actuator端点都不通过http公开,这里我们公开了所有端点。
#  对于生产,您应该仔细选择要公开的端点。
management.endpoints.web.exposure.include=*

#日志收集
logging.file.name=/var/log/sample-boot-application.log
logging.pattern.file=%clr(%d{
   yyyy-MM-dd HH:mm:ss.SSS}){
   faint} %clr(%5p) %clr(${
   PID}){
   magenta} %clr(---){
   faint} %clr([%15.15t]){
   faint} %clr(%-40.40logger{
   39}){
   cyan} %clr(:){
   faint} %m%n%wEx

#按实例显示标签
#元数据 ---改成自己的服务名称
spring.boot.admin.client.instance.metadata.tags.environment=cloud_data
#信息断点---改成自己的服务名称
info.tags.environment=cloud_data

3)每个微服务客户端新增依赖

<dependency>
    <groupId>de.codecentric</groupId>
    <artifactId>spring-boot-admin-starter-client</artifactId>
    <version>2.5.1</version>
</dependency>

4)新增整体工具依赖

 <properties>
        <fastjson.version>1.2.60</fastjson.version>
 <org.projectlombok.version>1.18.8</org.projectlombok.version>
</properties>

<dependencies>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>${
   org.projectlombok.version}</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>${
   fastjson.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</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-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

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

    </dependencies>

5)全部启动查看效果

7、整合Alibaba Cloud gateway服务

1)配置gateway依赖

   <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>

2)配置sentinel-gateway限流监控依赖

  <!--网关流控-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
        </dependency>

3)Gateway跨域

Gateway服务新增配置类

创建 com.api.gateway 的包 在创建配置类

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.reactive.CorsWebFilter;
import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;

@Configuration
public class ApiCorsConfiguration {
   

    @Bean
    public CorsWebFilter corsWebFilter() {
   
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();

        CorsConfiguration corsConfiguration = new CorsConfiguration();

        //1、配置跨域
        corsConfiguration.addAllowedHeader("*");
        corsConfiguration.addAllowedMethod("*");
        corsConfiguration.addAllowedOrigin("*");
        corsConfiguration.setAllowCredentials(true);

        source.registerCorsConfiguration("/**", corsConfiguration);
        return new CorsWebFilter(source);
    }
}

4)Gateway 路由

spring:
  cloud:
    gateway:
      routes:
        - id: test_route
          uri: https://www.baidu.com
          predicates:
            - Query=url,baidu

        - id: qq_route
          uri: https://www.qq.com
          predicates:
            - Query=url,qq

        - id: party_route
          uri: lb://cloud-party
          predicates:
            - Path=/api/party/**,/hello
          filters:
            - RewritePath=/api/(?<segment>.*),/$\{segment}

        - id: login_route
          uri: lb://cloud-login
          predicates:
            - Path=/api/login/**
          filters:
            - RewritePath=/api/(?<segment>.*),/$\{segment}

        - id: gateway-route
          uri: lb://cloud-gateway
          predicates:
            - Path=/api/gateway/**
          filters:
            - RewritePath=/api/(?<segment>.*),/$\{segment}

        - id: admin-route
          uri: lb://cloud-admin
          predicates:
            - Path=/api/admin/**
          filters:
            - RewritePath=/api/(?<segment>.*),/$\{segment}

        - id: production-route
          uri: lb://cloud-production
          predicates:
            - Path=/api/production/**
          filters:
            - RewritePath=/api/(?<segment>.*),/$\{segment}

5)每个服务配置Sentinel注册

在dev环境下

spring:
  cloud:
      #监控限流
    sentinel:
      transport:
        dashboard: 192.168.2.110:8080 #看上面提前搭建好了

8、整合Alibaba Cloud Nacos注册中心

1)cloud-common服务增加Nacos依赖

       <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>

2)每个服务配置Nacos注册中心

spring:
  #监控限流
  cloud:
    nacos:
      server-addr: cloud.api.com:8848
      discovery:
        namespace: d4dc3568-39bc-4258-83bb-a88c56fa9321 #看上面提前搭建好了
        group: dev

3)每个启动类加注册Nacos注解

@EnableDiscoveryClient

4)启动看效果

在这里插入图片描述

9、整合Alibaba Cloud Config Nacos的配置中心

1)导入配置依赖

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>

2)Nacos配置创建文件

在这里插入图片描述
在这里插入图片描述

3)担心的话进行测试

以最简单的方式配置一下

在这里插入图片描述

加到启动类里面进行测试获取--可以看到动态获取到参数了

      while(true) {
   
            //当动态配置刷新时,会更新到 Enviroment中,
            //因此这里每隔一秒中从Enviroment中获取配置
            String userName = applicationContext.getEnvironment().getProperty("user.name");

            System.err.println("user name :"+userName);
            TimeUnit.SECONDS.sleep(1);
        }

4)配置各个微服务模块YML

spring:
#注册中心
  cloud:
    nacos:
      server-addr: cloud.api.com:8848
      discovery:
        namespace: d4dc3568-39bc-4258-83bb-a88c56fa9321
        group: dev
#配置中心
      config:
        server-addr: cloud.api.com:8848
        group: dev
        file-extension: yaml
        namespace: d4dc3568-39bc-4258-83bb-a88c56fa9321

5、优化YML配置优先级

不进行优化导致配置拉取不到
在这里插入图片描述

把自己的application全部修改为bootstrap即可

10、整合Alibaba Cloud zkpin链路追踪

1)介绍

在大型系统的微服务化构建中,一个系统被拆分成了许多模块。这些模块负责不同的功能,组合成 系统,最终可以提供丰富的功能。在这种架构中,一次请求往往需要涉及到多个服务。互联网应用构建 在不同的软件模块集上,这些软件模块,有可能是由不同的团队开发、可能使用不同的编程语言来实 现、有可能布在了几千台服务器,横跨多个不同的数据中心,也就意味着这种架构形式也会存在一些问题:

如何快速发现问题?
如何判断故障影响范围?
如何梳理服务依赖以及依赖的合理性?
如何分析链路性能问题以及实时容量规划?

2)common工具配置zkpin依赖

          <!-- 链路跟踪 sleuth和zipkin  -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zipkin</artifactId>
            <version>2.2.8.RELEASE</version>
        </dependency>

3)在各个微服务模块加入

spring:
  sleuth:
    web:
      client:
        # 开启采集链路
        enabled: true
    sampler:
      # 默认采集是 0.1(百分之十),生产环境采用默认,测试环境可以修改为1.0
      probability: 1.0

  # zipkin服务所在地址
  zipkin:
    base-url: http://cloud.api.com:9411/
    discovery-client-enabled: false #让nacos把它当成一个URL,而不要当做服务名

4)启动看效果

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

5、各个服务迁移到Nacos配置中心

spring:
  sleuth:
    web:
      client:
        # 开启采集链路
        enabled: true
    sampler:
      # 默认采集是 0.1(百分之十),生产环境采用默认,测试环境可以修改为1.0
      probability: 1.0

  # zipkin服务所在地址
  zipkin:
    base-url: http://cloud.api.com:9411/
    discovery-client-enabled: false #让nacos把它当成一个URL,而不要当做服务名

11、整合Alibaba Cloud Feign组件

1)导入依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

2)增加注解

启动类增加注解

@EnableFeignClients

3)配置请求注解

@FeignClient("cloud_login")

4)Feign整合问题一

(1) 修改每个服务的

application.properties配置文件
两个服务名改为-

在这里插入图片描述

(2) 修改每个服务的YML

每一个application.name= 下划线_变成-

在这里插入图片描述

(3) 修改Nacos的配置文件名为-

删除重新创建即可

在这里插入图片描述

(4) 启动报错

Caused by: java.lang.IllegalStateException: No Feign Client for loadBalancing defined. Did you forget to include spring-cloud-starter-loadbalancer?
    at org.springframework.cloud.openfeign.FeignClientFactoryBean.loadBalance(FeignClientFactoryBean.java:382) ~[spring-cloud-openfeign-core-3.1.1.jar:3.1.1]
    at org.springframework.cloud.openfeign.FeignClientFactoryBean.getTarget(FeignClientFactoryBean.java:427) ~[spring-cloud-openfeign-core-3.1.1.jar:3.1.1]
    at org.springframework.cloud.openfeign.FeignClientFactoryBean.getObject(FeignClientFactoryBean.java:402) ~[spring-cloud-openfeign-core-3.1.1.jar:3.1.1]
    at org.springframework.cloud.openfeign.FeignClientsRegistrar.lambda$registerFeignClient$0(FeignClientsRegistrar.java:235) ~[spring-cloud-openfeign-core-3.1.1.jar:3.1.1]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.obtainFromSupplier(AbstractAutowireCapableBeanFactory.java:1249) ~[spring-beans-5.3.15.jar:5.3.15]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1191) ~[spring-beans-5.3.15.jar:5.3.15]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:582) ~[spring-beans-5.3.15.jar:5.3.15]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) ~[spring-beans-5.3.15.jar:5.3.15]
    ... 33 common frames omitted

2022-10-06 16:01:58.614  WARN [cloud-data,,] 24988 --- [      Thread-27] c.a.nacos.common.notify.NotifyCenter     : [NotifyCenter] Start destroying Publisher
2022-10-06 16:01:58.614  WARN [cloud-data,,] 24988 --- [      Thread-27] c.a.nacos.common.notify.NotifyCenter     : [NotifyCenter] Destruction of the end
Exception in thread "Thread-17" zipkin2.reporter.ClosedSenderException
    at zipkin2.reporter.AsyncReporter$BoundedAsyncReporter.flush(AsyncReporter.java:265)
    at org.springframework.cloud.sleuth.autoconfig.zipkin2.ZipkinAutoConfiguration$2.run(ZipkinAutoConfiguration.java:142)

(5) 原因

引入openfeign时报No Feign Client for loadBalancing defined. Did you forget to
 include spring-cloud-starter-loadbalancer错误
原因:由于SpringCloud Feign高版本不使用Ribbon而是使用spring-cloud-loadbalancer,
所以需要引用spring-cloud-loadbalancer或者降版本、

解决方案在common工程加入此依赖

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-loadbalancer</artifactId>
        </dependency>

排除注册中心中的ribbon

 <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.cloud</groupId>
                    <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

12、整合Alibaba Cloud Feign超时配置

1)超时配置存在Ribbon(过时)

默认fegin客户端只等待一秒、但是服务端处理需要等待1秒中、导致fegin客户端不想等待了、
直接返回报错、为了避免这样的情况、有时候我们需要设置fegin客户端的超时时间

需要在消费者 yml加入超时配置

#设置fegin客户端超时时间(OpenFegin 默认ribbon)
ribbon:
  #指的是建立连接所用的时间,适用于网络状态正常情况下、两端连接所用的时间
  ReadTimeout: 5000
  #指的是建立连接后从服务器读取到可用资源所用时间
  ConnecTimeout: 5000

2)不存在Ribbon的超时配置(重点)

feign:
  client:
    config:
      #服务名称
      cloud-production:
        # 连接超时时间
        connectTimeout: 90000
        # 请求处理超时时间
        readTimeout: 90000

3)超时配置全局

可新增配置类来解决超时

    @Bean
    public Request.Options options(){
   
        // Request.Options(int connectTimeoutMillis, int readTimeoutMillis)方法已经过时
        return new Request.Options(10000,60000);
    }

13、整合Alibaba Cloud Feign性能优化

全部服务都配置

1)介绍

Feign底层的客户端实现:
1、URLConnection:默认实现,不支持连接池
2、Apache HttpClient:支持连接池
3、OKHttp:支持连接池

因此优化feign主要包括:
1、使用连接池代替默认的URLConnection
2、日志级别,最好用basic或none

2)引入依赖

 <dependency>
     <groupId>io.github.openfeign</groupId>
     <artifactId>feign-httpclient</artifactId>
 </dependency>

3) yml新增配置

feign:
  client:
    config:
      default: # default 全局配置
        loggerLevel: BASIC #日志级别,BASIC就是最基本的请求和响应信息
  httpclient:
    enabled: true # 支持httpClient的开关
    max-connections: 200 #最大连接数
    max-connections-per-route: 50 # 单个路径的最大连接数

14、整合Feign整合Alibaba Cloud sentinel

全部服务都配置----随便找个服务测试、具体可参数我的视频来做

1)YML新增配置

#开启fegin对sentinel支持
feign:
  sentinel:
    enabled: true

2)创建容错类

@Slf4j
@Component
public class FallbackFactoryService implements FallbackFactory<DataProductionFeignService> {
   
    @Override
    public DataProductionFeignService create(Throwable cause) {
   
        log.error("服务异常。。。。。。。。。。。。。。。。。。。" + cause);
        return new DataProductionFeignService() {
   
            @Override
            public String getProduction(String id) {
   
                JSONObject data = new JSONObject();
                data.put("code","414");
                data.put("message","Fallback回滚");
                return data.toJSONString();
            }

        };
    }
}

3)创建Feign请求

@FeignClient(value = "cloud-production", fallbackFactory = FallbackFactoryService.class)
public interface DataProductionFeignService {
   

    @GetMapping("/production/all/getMysql")
    String getProduction(@RequestParam("id") String id);

}

15、整合Alibaba Cloud Feign整合日志

1)新增日志类

  public class DefaultFeignConfiguration  {
   
    @Bean
    public Logger.Level feignLogLevel(){
   
        return Logger.Level.BASIC; // 日志级别为BASIC
    }
}

2)新增日志配置

feign:  
  client:
    config: 
      default: # 这里用default就是全局配置,如果是写服务名称,则是针对某个微服务的配置
        loggerLevel: FULL #  日志级别

如果要全局生效,将其放到启动类的@EnableFeignClients这个注解中
@EnableFeignClients(defaultConfiguration = DefaultFeignConfiguration .class)

局部生效

feign:  
  client:
    config: 
      userservice: # 针对某个微服务的配置
        loggerLevel: FULL #  日志级别

如果是局部生效,则把它放到对应的@FeignClient这个注解中:
@FeignClient(value = "userservice", configuration = DefaultFeignConfiguration .class)

3)高级配置法

logging:
  level:
    com.cloud.api.data.feign.DataProductionFeignService: debug  #扫描的是你那个service的类全类名

4)各个服务模块新增

都需要配置同样的配置和日志类

16、整合Alibaba Cloud Feign重试机制

给各个服务模块配置重试机制

当feign调用返回HTTP报文时,会触发这个方法,方法内可以获得HTTP状态码,可以用来定制一些处理逻辑等等。

/**
 * @summary fegin 客户端的自定义配置
 */
@Slf4j
public class MyConfiguration {
   

    /**
     * 自定义重试机制
     * @return
     */
    @Bean
    public Retryer feignRetryer() {
   
        //最大请求次数为5,初始间隔时间为100ms,下次间隔时间1.5倍递增,重试间最大间隔时间为1s,
        return new Retryer.Default();
    }

    @Bean
    public ErrorDecoder feignError() {
   
        return (key, response) -> {
   
            if (response.status() == 400) {
   
                log.error("请求xxx服务400参数错误,返回:{}", response.body());
            }

            if (response.status() == 409) {
   
                log.error("请求xxx服务409异常,返回:{}", response.body());
            }

            if (response.status() == 404) {
   
                log.error("请求xxx服务404异常,返回:{}", response.body());
            }

            // 其他异常交给Default去解码处理
            // 这里使用单例即可,Default不用每次都去new
            return new ErrorDecoder.Default().decode(key, response);
        };
    }

}

17、整合优化Alibaba Cloud Feign压缩

gzip是一种数据格式,采用deflate算法压缩数据。当Gzip压缩到一个纯文本数据时,可以减少70%以上的数据大小。
gzip作用:网络数据经过压缩后实际上降低了网络传输的字节数,最明显的好处就是可以加快网页加载的速度。
只配置Feign请求-应答的GZIP压缩

1)Feign压缩配置

给各个服务模块配置feign压缩

feign:
#Feign 压缩数据
  compression:
    request:
      enabled: true
      # 配置压缩的类型
      mime-types: text/xml,application/xml,application/json
      # 最小压缩值
      min-request-size: 2048
    response:
      enabled: true

2)Springboot开启压缩

给各个服务模块配置Springboot压缩

server:
  compression:
    min-response-size: 512
    mime-types: application/json,application/xml,text/html,text/xml,text/plain
    excluded-user-agents: gozilla,traviata
    enabled: true

application.properties配置形式

# spring boot gzip
# 开启spring boot中的gzip压缩。就是针对和当前应用所有相关的http请求-应答的gzip压缩。
server.compression.enabled=true
# 哪些客户端发出的请求不压缩,默认是不限制
server.compression.excluded-user-agents=gozilla,traviata
# 配置想压缩的请求/应答数据类型,默认是 text/html,text/xml,text/plain
server.compression.mime-types=application/json,application/xml,text/html,text/xml,text/plain
# 执行压缩的阈值,默认为2048
server.compression.min-response-size=512

18、移Feign配置到Alibaba Cloud Nacos中心

1)把feign压缩迁移Nacos

具体看我的视频

屏蔽Yml的配置

2)把SpringBoot压缩迁移Nacos

具体看我的视频

屏蔽Yml的配置

19、整合Alibaba Cloud OSS服务

1)导入OSS依赖

给party图片服务加入如下依赖

    <properties>
        <oss.version>2.2.0.RELEASE</oss.version>
    </properties>
        <!--com.alibaba.cloud-OSS-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alicloud-oss</artifactId>
            <version>${
   oss.version}</version>
        </dependency>

2)导入到cloud_common工具类

1)导入转换Base64工具类

package com.api.common.utils.img;

import org.springframework.web.multipart.MultipartFile;
import sun.misc.BASE64Decoder;

import java.io.*;
/**
 *  base64图片转为MultipartFile
 * 类 名 称:BASE64DecodedMultipartFile
 * 类 描 述:base64转MultipartFile
*/
public class BASE64DecodedMultipartFile implements MultipartFile {
   
    private final byte[] imgContent;
    private final String header;

    public BASE64DecodedMultipartFile(byte[] imgContent, String header) {
   
        this.imgContent = imgContent;
        this.header = header.split(";")[0];
    }

    @Override
    public String getName() {
   
        // TODO - implementation depends on your requirements
        return System.currentTimeMillis() + Math.random() + "." + header.split("/")[1];
    }

    @Override
    public String getOriginalFilename() {
   
        // TODO - implementation depends on your requirements
        return System.currentTimeMillis() + (int) Math.random() * 10000 + "." + header.split("/")[1];
    }

    @Override
    public String getContentType() {
   
        // TODO - implementation depends on your requirements
        return header.split(":")[1];
    }

    @Override
    public boolean isEmpty() {
   
        return imgContent == null || imgContent.length == 0;
    }

    @Override
    public long getSize() {
   
        return imgContent.length;
    }

    @Override
    public byte[] getBytes() throws IOException {
   
        return imgContent;
    }

    @Override
    public InputStream getInputStream() throws IOException {
   
        return new ByteArrayInputStream(imgContent);
    }

    @Override
    public void transferTo(File dest) throws IOException, IllegalStateException {
   
        new FileOutputStream(dest).write(imgContent);
    }

    /**
     * base64转MultipartFile文件
     *
     * @param base64
     * @return
     */
    public static MultipartFile base64ToMultipart(String base64) {
   
        try {
   
            String[] baseStrs = base64.split(",");

            BASE64Decoder decoder = new BASE64Decoder();
            byte[] b = new byte[0];
            b = decoder.decodeBuffer(baseStrs[1]);

            for (int i = 0; i < b.length; ++i) {
   
                if (b[i] < 0) {
   
                    b[i] += 256;
                }
            }

            return new BASE64DecodedMultipartFile(b, baseStrs[0]);
        } catch (IOException e) {
   
            e.printStackTrace();
            return null;
        }
    }

}

2)状态码工具类

package com.cloud.api.common.utils;

public enum BizCodeEnume {
   
    BD_BASE64_TYPE(200, "BASE64"),    //百度Base64 类型
    BD_URL_TYPE(200, "URL"),   //通用URL格式图片
    KS_IMG_HTTPS(200, "https"),//矿视 Base64图片类型
    KS_IMG_TYPE(200, "image_base64"),//矿视 Base64图片类型


    TO_MANY_REQUEST(10002, "请求流量过大"),
    UNKNOW_EXCEPTION(10000, "系统未知异常"),
    VAILD_EXCEPTION(10001, "参数格式校验失败"),
    SMS_EXCEPTION(10002, "验证码获取频率太高,稍后再试"),
    PRODUCT_UP_EXCEPTION(11000, "商品商家异常"),
    USER_EXIT_EXCEPTION(15001, "用户存在"),
    PHONE_EXIT_EXCEPTION(15002, "手机号存在"),
    NO_STOCK_EXCEPTION(21000, "商品库存不足"),
    BASE64_UTILS(001, "BASE64"),
    URL_UTILS(002, "URL"),
    MultiParTile_UTILS(003, "MultiParTile"),
    ALI_BUCKET(004, "api-uexpo");


    private int code;
    private String msg;

    BizCodeEnume(int code, String msg) {
   
        this.code = code;
        this.msg = msg;
    }

    public int getCode() {
   
        return code;
    }

    public String getMsg() {
   
        return msg;
    }
}

3)封装返回结果

package com.cloud.api.common.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import org.apache.http.HttpStatus;

import java.util.HashMap;
import java.util.Map;

/**
 * 返回数据
 *
 * @author Mark sunlightcs@gmail.com
 */
public class R extends HashMap<String, Object> {
   
    private static final long serialVersionUID = 1L;


    public <T> T getData(String key, TypeReference<T> typeReference){
   
        Object data = get(key);
        String s = JSON.toJSONString(data);
        T t = JSON.parseObject(s, typeReference);
        return t;
    }



    public R() {
   
        put("code", 200);
        put("msg", "success");
    }

    public static long getSerialVersionUID() {
   
        return serialVersionUID;
    }

    public static R error() {
   
        return error(HttpStatus.SC_INTERNAL_SERVER_ERROR, "未知异常,请联系管理员");
    }

    public static R error(String msg) {
   
        return error(HttpStatus.SC_INTERNAL_SERVER_ERROR, msg);
    }

    public static R error(int code, String msg) {
   
        R r = new R();
        r.put("code", code);
        r.put("msg", msg);
        return r;
    }

    public static R ok(String msg) {
   
        R r = new R();
        r.put("msg", msg);
        return r;
    }

    public static R ok(Map<String, Object> map) {
   
        R r = new R();
        r.putAll(map);
        return r;
    }

    public static  R ok(Object data) {
   
        R r = new R();
        r.put("data", data);
        return r;
    }

    public static R ok() {
   
        return new R();
    }

    public <T> T getDta(TypeReference<T> typeReference) {
   
        Object data = get("data"); //默认是map
        String s = JSON.toJSONString(data);
        T t = JSON.parseObject(s, typeReference);
        return t;
    }

    public R setDta(Object data) {
   
        put("data", data);
        return this;
    }

    public R put(String key, Object value) {
   
        super.put(key, value);
        return this;
    }


    public Integer getCode() {
   
        return (Integer) this.get("code");
    }
}

4)自定义异常

package com.cloud.api.common.utils;

/**
 * 自定义异常
 *
 * @author Mark sunlightcs@gmail.com
 */
public class RRException extends RuntimeException {
   
    private static final long serialVersionUID = 1L;

    private String msg;
    private int code = 500;

    public RRException(String msg) {
   
        super(msg);
        this.msg = msg;
    }

    public RRException(String msg, Throwable e) {
   
        super(msg, e);
        this.msg = msg;
    }

    public RRException(String msg, int code) {
   
        super(msg);
        this.msg = msg;
        this.code = code;
    }

    public RRException(String msg, int code, Throwable e) {
   
        super(msg, e);
        this.msg = msg;
        this.code = code;
    }

    public String getMsg() {
   
        return msg;
    }

    public void setMsg(String msg) {
   
        this.msg = msg;
    }

    public int getCode() {
   
        return code;
    }

    public void setCode(int code) {
   
        this.code = code;
    }


}

3)整合Alibaba 0SS图片上传

(1)创建Controller

package com.cloud.api.party.controller;


import com.aliyun.oss.OSSClient;

import com.cloud.api.common.utils.R;
import com.cloud.api.party.service.ImgService;
import com.cloud.api.party.utils.OSSEntity;
import com.cloud.api.party.utils.ToImages;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;


import java.io.IOException;

/**
 * @Author 小坏
 * @Date 2022/08/29 14:44
 * @Version 1.0
 * @program: 图片上传服务
 */

@RestController
@RequestMapping("party/oss")
public class OSSController {
   

    @Autowired
    private ImgService imgService;

    /**
     * @param toImages
     * @return
     */
    @PostMapping("toImages")
    public R toImages(@RequestBody ToImages toImages) {
   
        return imgService.toImages(toImages);

    }


    /**
     * 图片文件流转换base64
     *
     * @param file
     * @return
     */
    @PostMapping("upLoad")
    public R toImages(@RequestParam("file") MultipartFile file) throws IOException {
   
        return R.ok();
    }


    /**
     * 阿里云文件图片上传
     *
     * @param file
     * @return
     */
    @PostMapping("toFilePutLoad")
    public R toFilePutLoad(@RequestParam("file") MultipartFile file) {
   
        return imgService.toFilePutLoad(file);
    }


    /**
     * 阿里云BASE64图片上传
     *
     * @return
     */
    @PostMapping("toBasePutLoad")
    public R toBasePutLoad(@RequestBody OSSEntity os) {
   
        return imgService.toBasePutLoad(os);
    }

}

(2)创建Service

package com.cloud.api.party.service;

import com.cloud.api.common.utils.R;
import com.cloud.api.party.utils.OSSEntity;
import com.cloud.api.party.utils.ToImages;
import org.springframework.web.multipart.MultipartFile;

public interface ImgService {
   
R toImages(ToImages toImages);

    R toFilePutLoad(MultipartFile file);

    R toBasePutLoad(OSSEntity oss);
}

(3)创建实现类

package com.cloud.api.party.service.impl;

import com.aliyun.oss.OSSClient;
import com.cloud.api.common.utils.BizCodeEnume;
import com.cloud.api.common.utils.R;
import com.cloud.api.party.service.ImgService;
import com.cloud.api.party.utils.OSSEntity;
import com.cloud.api.party.utils.OSSUtils;
import com.cloud.api.party.utils.ToImages;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.util.HashMap;

/**
 * @Author 小坏
 * @Date 2022/08/29 14:44
 * @Version 1.0
 * @program: 图片统一转换
 */
@Service
public class ImgServiceImpl implements ImgService {
   


    @Resource
    private OSSClient ossClient;

    @Override
    public R toImages(ToImages toImages) {
   
        return R.ok();
    }


    @Override
    public R toFilePutLoad(MultipartFile file) {
   
        OSSEntity ossEntity = OSSUtils.build().putOSS(file);
        HashMap<String, Object> map = getStringObjectHashMap(ossEntity);
        return R.ok().setDta(map);
    }

    @Override
    public R toBasePutLoad(OSSEntity os) {
   
        OSSEntity ossEntity = OSSUtils.build().putOSS(os.getImage());
        HashMap<String, Object> map = getStringObjectHashMap(ossEntity);
        return R.ok().setDta(map);

    }

    private HashMap<String, Object> getStringObjectHashMap(OSSEntity ossEntity) {
   
        ossClient.putObject(BizCodeEnume.ALI_BUCKET.getMsg(),
                ossEntity.getFilename(),
                ossEntity.getInputStream(),
                ossEntity.getObjectMetadata());
        String url = ossEntity.getUrl().concat(ossEntity.getFilename());
        HashMap<String, Object> map = new HashMap<>();
        map.put("url", url);
        return map;
    }
}

(4)创建图片使用的工具

@Data
public class OSSEntity {
   
    private String image;
    private String  filename;
    private InputStream inputStream;
    private ObjectMetadata objectMetadata;
    private String url;
}
package com.cloud.api.party.utils;

import com.aliyun.oss.model.ObjectMetadata;
import com.cloud.api.common.utils.BASE64DecodedMultipartFile;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;

public class OSSUtils {
   


    private final static String bucketName = "https://alibaba-api.oss-cn-shanghai.aliyuncs.com/";

    /**
     * 文件流上传阿里云
     *
     * @param file
     * @return
     */
    public OSSEntity putOSS(MultipartFile file) {
   
        return putLoadOSS(file);
    }

    /**
     * base64上传阿里云
     *
     * @param base64
     * @return
     */
    public OSSEntity putOSS(String base64) {
   
        String base = "data:image/jpg;base64,/".concat(base64);
        MultipartFile file = BASE64DecodedMultipartFile.base64ToMultipart(base);
        return putLoadOSS(file);
    }

    /**
     * base64上传阿里云
     * @param file
     * @return
     */
    private OSSEntity putLoadOSS(MultipartFile file) {
   

        ObjectMetadata objectMetadata = new ObjectMetadata();
        //获取上传文件的扩展名,截取扩展名
        //设置文本类型
        objectMetadata.setContentType("image/jpg");
        InputStream inputStream = null;
        try {
   
            inputStream = file.getInputStream();
        } catch (IOException e) {
   
            e.printStackTrace();
        }
        //获取上传的文件的名字
        String filename = file.getOriginalFilename();
        //随机uuid是为了拼接文件名,防止用户上传两个名字相同的文件后覆盖掉前一个
        UUID uuid = UUID.randomUUID();
        //这里是为了按上传时间分配目录。精确到月
        String date = new SimpleDateFormat("yyyy/MM/").format(new Date());
        //拼接成完整的文件名。
        filename = date.concat(uuid.toString()).concat(filename);

        OSSEntity oss = new OSSEntity();
        oss.setFilename(filename);
        oss.setInputStream(inputStream);
        oss.setObjectMetadata(objectMetadata);
        oss.setUrl(bucketName);
        return oss;
    }


    public static OSSUtils build() {
   
        return new OSSUtils();
    }
}
@Data
public class ToImages {
   
    private String type;
    private String images;
    private MultipartFile multipartFile;
}

(5)配置OSS YML文件

spring:
  cloud:
# 阿里云Alibaba-OSS
    alicloud:
      secret-key: 自己的
      access-key: 自己
      oss:
        endpoint: 自己

改成自己的OSS块

在这里插入图片描述

(6)项目效果图

在这里插入图片描述

(7)项目效果图

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

20、整合Alibaba Cloud SMS 短信服务

1)新增依赖

    <properties>
        <sms.version>2.2.0.RELEASE</sms.version>
    </properties>

       <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alicloud-sms</artifactId>
            <version>${
   sms.version}</version>
        </dependency>

         短信发送用到redis
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
       </dependency>

2)配置YML

spring:
  cloud:
    # 阿里云Alibaba-OSS
    alicloud:
      secret-key: 自己的 ---需要看我视频配置
      access-key: 自己的---需要看我视频配置
      oss:
        endpoint: 自己的---需要看我视频配置
  redis:
    host: cloud.api.com
    port: 6379
    password: 123456
    # 指定数据库 默认是0
    database: 0
    timeout: 5000

3)创建短信controller

package com.api.auth.controller;

import com.api.auth.service.SendSmsService;
import com.api.auth.vo.SendCodeVo;

import com.api.common.utils.R;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;


/**
* @Author 小坏
* @Date 2022/08/29 14:44
* @Version 1.0
* @program: 普通登录
*/

@RestController
@RequestMapping("/auth/login")
public class AuthLoginController {
   

@Autowired
private SendSmsService sendSmsService;


@GetMapping("sendMail")
public void sendMail() {
   
System.out.println("邮箱");
}

/**
* 阿里云获取验证码
* @param phone
* @return
*/
@GetMapping("sendCode")
public R sendCode(@RequestParam("phone") String phone) {
   
return R.ok(sendSmsService.sendCheckCode(phone));
}

/**
* 验证验证码
* @param vo
* @return
*/
@PostMapping("sendCheckPhoneCode")
public R sendCheckPhoneCode(@RequestBody SendCodeVo vo) {
   
return R.ok(sendSmsService.sendCheckPhoneCode(vo));
}

}

4)创建短信Service

package com.api.auth.service;

import com.api.auth.vo.SendCodeVo;
import com.api.common.utils.R;

public interface SendSmsService {
   

    //获取验证码
    R sendCheckCode(String phone);


    //验证验证码
    R sendCheckPhoneCode(SendCodeVo vo);
}

5)创建短信Service

package com.cloud.api.party.service.impl;

import com.alibaba.alicloud.sms.ISmsService;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
import com.aliyuncs.exceptions.ClientException;

import com.cloud.api.common.result.R;
import com.cloud.api.common.utils.AuthServerConstant;
import com.cloud.api.common.utils.BizCodeEnume;
import com.cloud.api.common.utils.UUIDGenerator;
import com.cloud.api.party.service.SendSmsService;
import com.cloud.api.party.utils.SendCodeVo;
import com.fasterxml.jackson.annotation.ObjectIdGenerators;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;

import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.concurrent.TimeUnit;

/**
 * @Author 小坏
 * @Date 2022/08/29 14:44
 * @Version 1.0
 * @program: 阿里云验证码封装
 */

@Service
public class SendSmsServiceImpl implements SendSmsService {
   

    @Value("${spring.cloud.alicloud.sms.code}")
    private String springAliSmsCode;

    @Autowired
    private ISmsService smsService;

    @Autowired
    private RedisTemplate<String,String> redisTemplate;

    @Override
    public R sendCheckCode(String phone) {
   

        //接口防刷
        //先验证redis是否有缓存验证码
        String redisCode = redisTemplate.opsForValue().get(AuthServerConstant.SMS_CODE_CACHE_PREFIX + phone);
        System.out.println(redisCode);
        //如果命中缓存走
        if (!StringUtils.isEmpty(redisCode)) {
   
            long l = Long.parseLong(redisCode.split("_")[1]);
            if (System.currentTimeMillis() - l < 60000) {
   
                return R.error(BizCodeEnume.SMS_EXCEPTION.getCode(), BizCodeEnume.SMS_EXCEPTION.getMsg());
            }
        }

        //防止同一个phone在60秒内再次发送验证码
        String code = UUIDGenerator.MobileVfCode();
        String currentTime = code + "_" + System.currentTimeMillis();

        //防止同一个phone在60秒内再次发送验证码
        redisTemplate.opsForValue().set(AuthServerConstant.SMS_CODE_CACHE_PREFIX + phone, currentTime, 10, TimeUnit.MINUTES);

        //调用发送短信服务
        R r = sendCheckCode(phone, code);
        if (r.getCode() == 200) {
   
            return R.ok("发送成功!");
        }
        return R.error(BizCodeEnume.SMS_EXCEPTION.getCode(), BizCodeEnume.SMS_EXCEPTION.getMsg());
    }


    /**
     * 验证码登录对比
     *
     * @param vo
     * @return
     */
    @Override
    public R sendCheckPhoneCode(SendCodeVo vo) {
   
        //1、校验验证码
        //从redis中获取
        String code = vo.getCode();
        String b = redisTemplate.opsForValue().get(AuthServerConstant.SMS_CODE_CACHE_PREFIX + vo.getPhone());
        //如果命中缓存
        if (!StringUtils.isEmpty(b)) {
   
            //就把获取的code和redis中做对比
            if (code.equals(b.split("_")[0])) {
   
                //删除验证码
                redisTemplate.delete(AuthServerConstant.SMS_CODE_CACHE_PREFIX + vo.getPhone());
                //验证码通过  //真正注册。调用远程服务进行注册/或者本地注册逻辑
                return R.ok("验证码对比成功!");

            } else {
   
                //验证不通过
                return R.error("验证码超时!");
            }
        } else {
   
            //如果等于null、就是没有查到
            return R.error("验证码错误!");
        }
    }

    public R sendCheckCode(String phone, String code) {
   
        SendSmsRequest request = new SendSmsRequest();
        // Required:the mobile number  接收短信的号码
        request.setPhoneNumbers(phone);
        // Required:SMS-SignName-could be found in sms console  签名
        request.setSignName("有铂科技");
        // Required:Template-could be found in sms console  模板
        request.setTemplateCode(springAliSmsCode);
        // Required:The param of sms template.For exmaple, if the template is "Hello,your verification code is ${code}". The param should be like following value
        request.setTemplateParam("{\"code\":\"" + code + "\"}");
        SendSmsResponse sendSmsResponse = null;
        try {
   
            sendSmsResponse = smsService.sendSmsRequest(request);
        } catch (ClientException e) {
   
            e.printStackTrace();
            sendSmsResponse = new SendSmsResponse();
        }

        if (sendSmsResponse.getCode().equals("OK")) {
   
            return R.ok(code);
        }

        if (sendSmsResponse.getCode().equals("isv.BUSINESS_LIMIT_CONTROL")) {
   
            return R.error("aliyun限流!");
        }
        return R.error("不存在");
    }


}

6)创建短信对象

@Data
public class SendCodeVo {
   
private String phone;
private String code;
}

7)创建随机数

package com.api.common.http;

import java.net.InetAddress;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Random;
import java.util.Set;

public class UUIDGenerator {
   

/**
* 产生一个32位的UUID
*
* @return
*/

public static String generate() {
   
return new StringBuilder(32).append(format(getIP())).append(
format(getJVM())).append(format(getHiTime())).append(
format(getLoTime())).append(format(getCount())).toString();

}

private static final int IP;

static {
   
int ipadd;
try {
   
ipadd = toInt(InetAddress.getLocalHost().getAddress());
} catch (Exception e) {
   
ipadd = 0;
}
IP = ipadd;
}

private static short counter = (short) 0;

private static final int JVM = (int) (System.currentTimeMillis() >>> 8);

private final static String format(int intval) {
   
String formatted = Integer.toHexString(intval);
StringBuilder buf = new StringBuilder("00000000");
buf.replace(8 - formatted.length(), 8, formatted);
return buf.toString();
}

private final static String format(short shortval) {
   
String formatted = Integer.toHexString(shortval);
StringBuilder buf = new StringBuilder("0000");
buf.replace(4 - formatted.length(), 4, formatted);
return buf.toString();
}

private final static int getJVM() {
   
return JVM;
}

private final static short getCount() {
   
synchronized (UUIDGenerator.class) {
   
if (counter < 0) {
   
counter = 0;
}
return counter++;
}
}

/**
* Unique in a local network
*/
private final static int getIP() {
   
return IP;
}

/**
* Unique down to millisecond
*/
private final static short getHiTime() {
   
return (short) (System.currentTimeMillis() >>> 32);
}

private final static int getLoTime() {
   
return (int) System.currentTimeMillis();
}

private final static int toInt(byte[] bytes) {
   
int result = 0;
for (int i = 0; i < 4; i++) {
   
result = (result << 8) - Byte.MIN_VALUE + (int) bytes[i];
}
return result;
}

public static String getNumber() {
   
Set<Integer> set = new HashSet<Integer>(); //定义一个set。
Random r = new Random(); //定义一个产生随机数的实体对象;
while (set.size() < 6) {
    //产生6个:因为set是无序唯一的;
int r_number = r.nextInt(10);// 产生0到9的整型数据
set.add(r_number);
}
/**
* 下面是遍历出产生的随机数
*/
Iterator<Integer> it = set.iterator();//迭代器
String s1 = "P";
while (it.hasNext()) {
   
Integer u = it.next();
String s = String.valueOf(u);

s1 += s;
}
return s1;
}

private final static int OFFSET = 538309;

public static String MobileVfCode() {
   
long seed = System.currentTimeMillis() + OFFSET;
SecureRandom secureRandom = null; // 安全随机类
try {
   
secureRandom = SecureRandom.getInstance("SHA1PRNG");
secureRandom.setSeed(seed);
} catch (NoSuchAlgorithmException e) {
   
e.printStackTrace();
}

String codeList = "1234567890"; // 验证码数字取值范围
String sRand = ""; // 定义一个验证码字符串变量

for (int i = 0; i < 6; i++) {
   
int code = secureRandom.nextInt(codeList.length() - 1); // 随即生成一个0-9之间的整数
String rand = codeList.substring(code, code + 1);
sRand += rand; // 将生成的随机数拼成一个六位数验证码
}
return sRand; // 返回一个六位随机数验证码
}

}

21、整合AlibabaCloud集成ELK收集日志

·此节搭建环境在上面、请参考我的视频·

1)创建日志文件

logback-spring.xml

在这里插入图片描述

<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false" scan="true" scanPeriod="1 seconds">
    <include resource="org/springframework/boot/logging/logback/base.xml" />
    <contextName>logback</contextName>

    <appender name="cloud_api" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
        <destination>cloud_api:5044</destination>
        <!-- encoder必须配置,有多种可选 -->
        <encoder charset="UTF-8" class="net.logstash.logback.encoder.LogstashEncoder" />
    </appender>

    <root level="info">
        <appender-ref ref="cloud_api" />
    </root>
</configuration>

2)依赖logstash日志

        <!--集成logstash-->
        <dependency>
            <groupId>net.logstash.logback</groupId>
            <artifactId>logstash-logback-encoder</artifactId>
            <version>5.3</version>
        </dependency>

3)启动服务

4)创建ES索引

在这里插入图片描述

5)查看日志

在这里插入图片描述

6、所有微服务日志

在这里插入图片描述

22、ELK监控MYSQL

·此节搭建环境在上面、请参考我的视频·

1)服务器下载metricbeat监控文件

curl -L -O https://artifacts.elastic.co/downloads/beats/metricbeat/metricbeat-7.10.2-linux-x86_64.tar.gz

2)解压监控文件

tar xzvf metricbeat-7.10.2-linux-x86_64.tar.gz

3)修改配置文件metricbeat.yml

setup.template.settings:
# 因为我这里es是单节点,所以设置主分片数为1,副本分片数为0.否则会报黄
  index.number_of_shards: 1
  index.number_of_replicas: 0
output.elasticsearch:
# 你的es所在服务器ip
  hosts: ["192.168.244.11:9200"]
  username: "elastic"
  password: "elastic"
setup.kibana:
# kibana所在服务器ip
  host: "192.168.2.110:5601"

4)启动mysql模块

metricbeat会根据modules.d/mysql.yml中的配置项来获取系统数据

./metricbeat modules enable mysql

5)配置要采集的内容,修改modules.d/mysql.yml配置文件

vi modules.d/mysql.yml

配置文件内容,这里我们将status、galera_status、performance的指标都开启,具体可根据自己的需要进行配置

注意:这里没有开启query指标集,这是因为query用于监控我们自定义查询语句的指标数据的,需要额外配置其他项并且需要自己构建看板,并不能拆箱即用,所以我们在以后单独介绍。如果直接开启query的话,会出现报错

- module: mysql
  metricsets:
    - status
    - galera_status
    - performance
   # - query
  period: 10s

  hosts: ["root:123456@tcp(192.168.2.110:3306)/"]

这里的mysql配置也可以采取如下形式

hosts: ["tcp(127.0.0.1:3306)/"]
username: root
password: 123456

6)加载kibana仪表盘

./metricbeat setup

7、启动metricbeat

./metricbeat -e

8、这里可以在kibana的mysql指标部署流程

在这里插入图片描述

9、mysql指标仪表板

我们对数据库做一下查询、新增、修改等操作,创造一些数据,然后点击mysql指标仪表板(Metricbeat MySQL)

可以看到mysql的相关指标都显示出来了

在这里插入图片描述

23、整合AlibabaCloud全局异常

1)在common服务创建exception包

创建异常类

package com.cloud.api.common.exception;

public class CloudApiException extends RuntimeException {
   
    private static final long serialVersionUID = 1L;

    public CloudApiException(String message){
   
        super(message);
    }

    public CloudApiException(Throwable cause)
    {
   
        super(cause);
    }

    public CloudApiException(String message, Throwable cause)
    {
   
        super(message,cause);
    }
}

实现异常接口

package com.cloud.api.common.exception;


import com.alibaba.fastjson.JSONObject;
import com.cloud.api.common.result.R;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.multipart.MaxUploadSizeExceededException;
import org.springframework.web.servlet.NoHandlerFoundException;

import java.util.Map;

/**
 * 异常处理器
 *
 * @Author scott
 * @Date 2019
 */
@RestControllerAdvice
public class CloudApiExceptionHandler {
   

    /**
     * 处理自定义异常
     * @param e
     * @return
     */
    @ExceptionHandler(CloudApiException.class)
    public R handleRRException(CloudApiException e) {
   
        return R.error(e.getMessage());
    }

    @ExceptionHandler(NoHandlerFoundException.class)
    public R handlerNoFoundException(Exception e) {
   
        return R.error(404, "路径不存在,请检查路径是否正确");
    }


    /**
     * 全局异常
     * @param e
     * @return
     */
    @ExceptionHandler(Exception.class)
    public R handleException(Exception e) {
   
        StackTraceElement stackTraceElement = e.getStackTrace()[0];
        JSONObject map = new JSONObject();
//        map.put("类名:", stackTraceElement.getClassName());
        map.put("class:", stackTraceElement.getFileName());
        map.put("error:", e.toString());
        map.put("methodName:", stackTraceElement.getMethodName());
        map.put("errorLine:", stackTraceElement.getLineNumber());

        Map<String, String> m = System.getenv();
        String userName = m.get("USERNAME");// 获取用户名
        System.out.println(userName);
        if (userName == null) {
   
             userName = "Linux";
        }

        //发送钉钉/邮箱
        return R.error(map);

    }


    /**
     * 请求格式不对
     * @param e
     * @return
     */
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public R HttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e) {
   
        StringBuffer sb = new StringBuffer();
        sb.append("不支持");
        sb.append(e.getMethod());
        sb.append("请求方法,");
        sb.append("支持以下");
        String[] methods = e.getSupportedMethods();
        if (methods != null) {
   
            for (String str : methods) {
   
                sb.append(str);
                sb.append("!");
            }
        }
        return R.error(405, sb.toString());
    }


    /**
     *  spring默认上传大小100MB 超出大小捕获异常MaxUploadSizeExceededException
     * @param e
     * @return
     */
    @ExceptionHandler(MaxUploadSizeExceededException.class)
    public R handleMaxUploadSizeExceededException(MaxUploadSizeExceededException e) {
   
        return R.error("文件大小超出10MB限制, 请压缩或降低文件质量! ");
    }

}

2)微服务增加扫包

各个微服务都增加扫包

@SpringBootApplication(scanBasePackages = "com.cloud.api")

24、AlibAbaCloud微服务负载均衡

1)复制微服务配置

在这里插入图片描述

2)配置副本微服务端口

在这里插入图片描述

3)生成副本

启动即可
在这里插入图片描述

4)测试效果

采用的轮询机制
在这里插入图片描述

在这里插入图片描述

25、整合AlibabaCloud全局日志注解

1)自定义注解

package com.cloud.api.common.log;

import java.lang.annotation.*;

/**
 * @Program: aop
 * @ClassName CloudApiAnnotation
 * @Description: 自定义系统操作注解
 * @Author: liutao
 * @DateTime: 2022/10/5 2:32
 * @Version: 1.0
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CloudApiAnnotation {
   
    String operMoudle() default "";//操作模块
    String operMethod() default "";//操作方法
    String operDes() default "";//操作描述
}

2)封装AOP请求

package com.cloud.api.common.log;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.stream.annotation.EnableBinding;
import org.springframework.cloud.stream.messaging.Source;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @Program: aop
 * @ClassName SysLogger
 * @Description: aop日志具体实现
 * @Author: liutao
 * @DateTime: 2022/6/5 2:38
 * @Version: 1.0
 */

//@EnableBinding(value = Source.class)
@Aspect
@Component
public class CloudApiLogger {
   

    /**
     * spring cloud stream里面发消息通过 Source 发送
     */
    //@Autowired
    //private Source source;

    private CloudApiLog logs = new CloudApiLog();

    private final Logger logger = LoggerFactory.getLogger(CloudApiLogger.class);

    @Value("${spring.application.name}")
    private String SpringApplicationName;


    private ThreadLocal startTime = new ThreadLocal<Long>();

    @Pointcut("@annotation(com.cloud.api.common.log.CloudApiAnnotation)")
    public void operLoggerPointCut() {
   
        logger.info("===============系统操作日志===============");
    }

    @Pointcut("execution(public * com.cloud.api.*.controller.*.*(..))")
    public void controllerMethod() {
   
    }

    @Before("operLoggerPointCut()")
    public void logBefore(JoinPoint joinPoint) {
   

        startTime.set(System.currentTimeMillis());
        Map<String, String> map = System.getenv();
        String userName = map.get("USERNAME");// 获取// 用户名


        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
        StringBuilder requestLog = new StringBuilder();
        Signature signature = joinPoint.getSignature();
        Method method = ((MethodSignature) signature).getMethod();
        CloudApiAnnotation sysAnnotation = method.getAnnotation(CloudApiAnnotation.class);//利用反射获取到自定义注解


        // 打印请求内容
        logger.info("===============请求内容开始===============");
        logger.info("请求时间:" + new Date());


        logger.info("开发电脑昵称:" + userName);
        logs.setUserName(userName);
        logger.info("服务模块:" + SpringApplicationName);
        logs.setSpringApplicationName(SpringApplicationName);
        logger.info("操作模块:" + sysAnnotation.operMoudle());
        logs.setOperationModular(sysAnnotation.operMoudle());
        logger.info("操作方法:" + sysAnnotation.operMethod());
        logs.setOperationMethod(sysAnnotation.operMethod());
        logger.info("操作描述:" + sysAnnotation.operDes());
        logs.setOperationDes(sysAnnotation.operDes());
        logger.info("请求地址:" + request.getRequestURL().toString());
        logs.setRequestURL(request.getRequestURL().toString());
        logger.info("请求IP:" + request.getRemoteAddr());
        logs.setRequestIp(request.getRemoteAddr());
        logger.info("请求方式:" + request.getMethod());
        logs.setRequestMethod(request.getMethod());
        logger.info("请求类方法:" + joinPoint.getSignature());
        logs.setRequestSignature(joinPoint.getSignature().toString());
        logger.info("请求类方法参数值:" + Arrays.toString(joinPoint.getArgs()));


        // 处理请求参数
        String[] paramNames = ((MethodSignature) signature).getParameterNames();
        Object[] paramValues = joinPoint.getArgs();
        int paramLength = null == paramNames ? 0 : paramNames.length;
        if (paramLength == 0) {
   
            requestLog.append(" {} ");
        } else {
   
            requestLog.append(" {");
            for (int i = 0; i < paramLength - 1; i++) {
   
                requestLog.append(paramNames[i]).append("=").append(JSONObject.toJSONString(paramValues[i])).append(",");
            }
            requestLog.append(paramNames[paramLength - 1]).append("=").append(JSONObject.toJSONString(paramValues[paramLength - 1])).append("}");
        }
        logger.info("请求参数明细:" + requestLog.toString());
        logs.setRequestArgs(requestLog.toString());
        logger.info("===============请求内容结束===============");


    }

    @AfterReturning(returning = "o", pointcut = "operLoggerPointCut()")
    public void logResultVOInfo(Object o) {
   
        long l = System.currentTimeMillis() - (long) startTime.get();

        System.out.println((long) startTime.get());
        System.out.println(System.currentTimeMillis());

        logger.info("--------------返回内容开始----------------");
        logger.info("Response内容:" + JSON.toJSONString(o));

        logs.setResult(o.toString());
        logger.info("--------------返回内容结束----------------");
        logger.info("--------------操作耗时----------------");
        logger.info(": " + l);
        logs.setRequestTime(l);

       // boolean send = source.output().send(MessageBuilder.withPayload(JSONObject.toJSONString(logs)).build());
       // System.out.println(send);
    }

    @AfterThrowing(pointcut = "controllerMethod()", throwing = "ex")
    public void doAfterThrowing(JoinPoint joinPoint, Exception ex) {
   
        String methodName = joinPoint.getSignature().getName();
        List<Object> args = Arrays.asList(joinPoint.getArgs());
        System.out.println("连接点方法为:" + methodName + ",参数为:" + args + ",异常为:" + ex);

    }
}

3)新增日志对象

package com.cloud.api.common.log;

import com.fasterxml.jackson.annotation.JsonFormat;

import java.io.Serializable;
import java.util.Date;

public class CloudApiLog implements Serializable {
   

    @JsonFormat(pattern = "yyyy.MM.dd",timezone = "GMT+8")
    private Date createTime;
    private String userName;
    private String springApplicationName;
    private String operationModular;
    private String operationMethod;
    private String operationDes;
    private String requestURL;
    private String requestIp;
    private String requestMethod;
    private String requestSignature;
    private String requestArgs;
    private String result;
    private Long requestTime;


    public String getResult() {
   
        return result;
    }

    public void setUserName(String userName) {
   
        this.userName = userName;
    }
    public void setSpringApplicationName(String springApplicationName) {
   
        this.springApplicationName = springApplicationName;
    }
    public void setOperationModular(String operationModular) {
   
        this.operationModular = operationModular;
    }

    public void setOperationMethod(String operationMethod) {
   
        this.operationMethod = operationMethod;
    }

    public void setOperationDes(String operationDes) {
   
        this.operationDes = operationDes;
    }

    public void setRequestURL(String requestURL) {
   
        this.requestURL = requestURL;
    }

    public void setRequestIp(String requestIp) {
   
        this.requestIp = requestIp;
    }

    public void setRequestMethod(String requestMethod) {
   
        this.requestMethod = requestMethod;
    }

    public void setRequestSignature(String requestSignature) {
   
        this.requestSignature = requestSignature;
    }

    public void setRequestArgs(String requestArgs) {
   
        this.requestArgs = requestArgs;
    }

    public void setResult(String result) {
   
        this.result = result;
    }

    public void setRequestTime(Long requestTime) {
   
        this.requestTime = requestTime;
    }
}

4)记录日志注解

方法上自定义

   @CloudApiAnnotation(operMoudle = "测试接口",operMethod="getName", operDes = "测试")

26、整合AlibabaCloud RocketMQ消息队列生产

1)网站

https://github.com/alibaba/spring-cloud-alibaba/wiki/RocketMQ-en

2)采用流式依赖

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-stream-rocketmq</artifactId>
</dependency>

3、整合common服务生产

(1)绑定发送

在日志类编码

@EnableBinding(value = Source.class)

(2)注入bean

  @Autowired
    private Source source;

(3)发送消息

boolean send = source.output().send(MessageBuilder.withPayload(JSONObject
.toJSONString(logs)).build());

(4)需要记录日志服务配置

spring:
  #注册中心
  cloud:
    stream:
      #RocketMQ 通用配置
      rocketmq:
        binder:
          name-server: cloud.api.com:9876
          # 不加, 会报错:Property 'group' is required - producerGroup
          group: rocketmq-group
      #bindings 具体生产消息、消费消息的桥梁
      bindings:
        #Produce Config
        output: # 查看org.springframework.cloud.stream.config.BindingProperties
          destination: log-topic #指定发送的topic
          contentType: application/json #默认是application/json
          group: log-group

27、新增AlibabaCloud RocketMQ日志服务消费

1)创建log日志服务

在这里插入图片描述

2)配置POM依赖

    <dependencies>
        <dependency>
            <artifactId>cloud_common</artifactId>
            <groupId>com.cloud.api</groupId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

    </dependencies>

    <!--2021毕业版本依赖-->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>2.6.3</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>2021.0.1</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>2021.0.1.0</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

3)配置YML

spring:
  #注册中心
  cloud:
    nacos:
      server-addr: cloud.api.com:8848
      discovery:
        namespace: d4dc3568-39bc-4258-83bb-a88c56fa9321
        group: dev
      #配置中心
      config:
        server-addr: cloud.api.com:8848
        group: dev
        file-extension: yaml
        namespace: d4dc3568-39bc-4258-83bb-a88c56fa9321
    stream:
      #RocketMQ 通用配置
      rocketmq:
        binder:
          #客户端接入点,必填  rocketMQ的连接地址,binder高度抽象
          name-server: cloud.api.com:9876
          # 不加, 会报错:Property 'group' is required - producerGroup
          group: rocketmq-group
      #bindings 具体生产消息、消费消息的桥梁
      bindings:
        #Consumer Config
        input:
          destination: log-topic
          contentType: application/json #默认是application/json
          group: log-group

4)监听消费日志消息

package com.cloud.api.log.controller;

import com.alibaba.fastjson.JSONObject;
import com.cloud.api.log.entity.CloudApiLogEntity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.stream.annotation.EnableBinding;
import org.springframework.cloud.stream.annotation.StreamListener;
import org.springframework.cloud.stream.messaging.Sink;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.messaging.Message;

import java.io.UnsupportedEncodingException;
import java.util.Date;

@EnableBinding(value = {
   Sink.class})
public class ReceiveService {
   

    /**
     * spring cloud stream里面通过 Sink 接收消息
     */


    @Autowired
    private MongoTemplate mongoTemplate;


    @StreamListener(value = Sink.INPUT)
    public void listener(Message<byte[]> message) throws UnsupportedEncodingException {
   
        System.out.println("headers:" + message.getHeaders());
        byte[] payload = message.getPayload();
        String s = new String(payload, "utf-8");
        CloudApiLogEntity cloudApiLog = JSONObject.parseObject(s, CloudApiLogEntity.class);
        System.out.println("接收到的消息:" + new String(payload, "utf-8"));

        cloudApiLog.setCreateTime(new Date());
        CloudApiLogEntity insert = mongoTemplate.insert(cloudApiLog);
        System.out.println("...."+insert);
        System.out.println(cloudApiLog);
    }
}

28、监听RocketMQ操作日志到MongoDB

1)配置依赖


        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-mongodb</artifactId>
        </dependency>

2)配置mongodb链接


  data:
    mongodb:
      uri: mongodb://root:root@cloud.api.com:27017/cloud-api-log??authSource=admin&authMechanism=SCRAM-SHA-1

3)注入Mongodb的模板

调用新增即可

4)新增表

package com.cloud.api.log.entity;

import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.core.mapping.Field;

import java.io.Serializable;
import java.util.Date;


@Data
@Document(collection = "cloud-api-log")  //指定要对应的文档名(表名)
public class CloudApiLogEntity implements Serializable {
   

    /*** 自定义mongo主键 加此注解可自定义主键类型以及自定义自增规则
     *  若不加 插入数据数会默认生成 ObjectId 类型的_id 字段
     *  org.springframework.data.annotation.Id 包下
     *  mongo库主键字段还是为_id (本文实体类中字段为为id,意思查询字段为_id,但查询结果_id会映射到实体对象id字段中)
     */
    @Id
    private String id;

    @JsonFormat(locale = "zh", timezone = "Asia/Shanghai", pattern = "yyyy-MM-dd HH:mm:ss")
    @Field("createTime")
    private Date createTime;
    private String userName;
    private String springApplicationName;
    private String operationModular;
    private String operationMethod;
    private String operationDes;
    private String requestURL;
    private String requestIp;
    private String requestMethod;
    private String requestSignature;
    private String requestArgs;
    private String result;

    private String requestTime;
}

5)效果展示

在这里插入图片描述
在这里插入图片描述

29、全部服务RockMQ配置迁移Nacos

1)配置中心服务依赖

为每一个服务新增日志依赖依赖迁移到Nacos

spring:
  #注册中心
  cloud:
    stream:
      #RocketMQ 通用配置
      rocketmq:
        binder:
          name-server: cloud.api.com:9876
          # 不加, 会报错:Property 'group' is required - producerGroup
          group: rocketmq-group
      #bindings 具体生产消息、消费消息的桥梁
      bindings:
        #Produce Config
        output: # 查看org.springframework.cloud.stream.config.BindingProperties
          destination: log-topic #指定发送的topic
          contentType: application/json #默认是application/json
          group: log-group

2)新增扫包

@SpringBootApplication(scanBasePackages = "com.cloud.api")

30、Nacos配置中心共享YML

1)新增共享配置文件

什么是共享配置、重复、一致的配置文件

user:
  name: aaa

spring:
  #注册中心
  cloud:
# 限流
    sentinel:
      transport:
        dashboard: cloud.api.com:8080
  sleuth:
    web:
      client:
        # 开启采集链路
        enabled: true
    sampler:
      # 默认采集是 0.1(百分之十),生产环境采用默认,测试环境可以修改为1.0
      probability: 1.0

  # zipkin服务所在地址
  zipkin:
    base-url: http://cloud.api.com:9411/
    discovery-client-enabled: false #让nacos把它当成一个URL,而不要当做服务名

# Springboot压缩算法
server:
  compression:
    min-response-size: 512
    mime-types: application/json,application/xml,text/html,text/xml,text/plain
    excluded-user-agents: gozilla,traviata
    enabled: true

feign:
  client:
    config:
      cloud-production:       #服务名称
        connectTimeout: 90000 #连接超时时间
        readTimeout: 90000    #请求处理超时时间

#Feign 压缩数据
  compression:
    request:
      enabled: true
      # 配置压缩的类型
      mime-types: text/xml,application/xml,application/json
      # 最小压缩值
      min-request-size: 2048
    response:
      enabled: true
#更改自带的连接池
  httpclient:
    enabled: true # 支持httpClient的开关
    max-connections: 200 #最大连接数
    max-connections-per-route: 50 # 单个路径的最大连接数
#开启fegin对sentinel支持
  sentinel:
    enabled: true

2)加入共享配置

spring:
  #注册中心
  cloud:
    nacos:
      server-addr: cloud.api.com:8848
      discovery:
        namespace: d4dc3568-39bc-4258-83bb-a88c56fa9321
        group: dev

      #配置中心
      config:
        server-addr: cloud.api.com:8848
        group: dev
        file-extension: yaml
        namespace: d4dc3568-39bc-4258-83bb-a88c56fa9321
        # 共享配置
        shared-configs:
          - data-id: application-dev.yaml
            group: dev

31、配置BootAdmin权限登录监控

1)增加依赖

   <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>

2)增加权限配置类

@Configuration
public class SecuritySecureConfig extends WebSecurityConfigurerAdapter {
   

    private final String adminContextPath;

    public SecuritySecureConfig(AdminServerProperties adminServer) {
   
        this.adminContextPath = adminServer.getContextPath();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
   
        SavedRequestAwareAuthenticationSuccessHandler successHandler = new SavedRequestAwareAuthenticationSuccessHandler();
        successHandler.setTargetUrlParameter("redirectTo");
        successHandler.setDefaultTargetUrl(adminContextPath + "/");

        http.authorizeRequests()
                .antMatchers(adminContextPath + "/login",
                        adminContextPath + "/assets/**",
                        adminContextPath + "/manage/**",
                        adminContextPath + "/actuator/**").permitAll()
                .anyRequest().authenticated()
                .and()
                .formLogin().loginPage(adminContextPath + "/login").successHandler(successHandler)
                .and()
                .logout().logoutUrl(adminContextPath + "/logout")
                .and()
                .csrf().disable();
    }

}

3)配置账户密码

spring:
  security:
    user:
      name: admin
      password: admin

32、CloudAlibaba整合报警配置

1)配置报警

@Component
public class AdminNotifier extends AbstractStatusChangeNotifier {
   

    private static final Logger log = LoggerFactory.getLogger(AdminNotifier.class);

    /**
     * 消息模板
     */
    private static final String template = "<<<%s>>> \n 【服务名】: %s(%s) \n 【状态】: %s(%s) \n 【服务ip】: %s \n 【详情】: %s";

    private String titleAlarm = "系统告警";

    private String titleNotice = "系统通知";

    private String[] ignoreChanges = new String[]{
   "UNKNOWN:UP","DOWN:UP","OFFLINE:UP"};

    public AdminNotifier(InstanceRepository repository) {
   
        super(repository);
    }

    @Override
    protected boolean shouldNotify(InstanceEvent event, Instance instance) {
   
        if (!(event instanceof InstanceStatusChangedEvent)) {
   
            return false;
        } else {
   
            InstanceStatusChangedEvent statusChange = (InstanceStatusChangedEvent)event;
            String from = this.getLastStatus(event.getInstance());
            String to = statusChange.getStatusInfo().getStatus();
            return Arrays.binarySearch(this.ignoreChanges, from + ":" + to) < 0 && Arrays.binarySearch(this.ignoreChanges, "*:" + to) < 0 && Arrays.binarySearch(this.ignoreChanges, from + ":*") < 0;
        }
    }


    @Override
    protected Mono<Void> doNotify(InstanceEvent event, Instance instance) {
   

        return Mono.fromRunnable(() -> {
   

            if (event instanceof InstanceStatusChangedEvent) {
   
                log.info("Instance {} ({}) is {}", instance.getRegistration().getName(),
                        event.getInstance(),
                        ((InstanceStatusChangedEvent) event).getStatusInfo().getStatus());

                String status = ((InstanceStatusChangedEvent) event).getStatusInfo().getStatus();
                String messageText = null;
                switch (status) {
   
                    // 健康检查没通过
                    case "DOWN":
                        log.info("发送 健康检查没通过 的通知!");
                        messageText = String
                                .format(template,titleAlarm, instance.getRegistration().getName(), event.getInstance(),
                                        ((InstanceStatusChangedEvent) event).getStatusInfo().getStatus(), "健康检查没通过通知",
                                        instance.getRegistration().getServiceUrl(), JSONObject.toJSONString(instance.getStatusInfo().getDetails()));
                        log.info(messageText);
                        break;
                    // 服务离线
                    case "OFFLINE":
                        log.info("发送 服务离线 的通知!");
                        messageText = String
                                .format(template,titleAlarm, instance.getRegistration().getName(), event.getInstance(),
                                        ((InstanceStatusChangedEvent) event).getStatusInfo().getStatus(), "服务离线通知",
                                        instance.getRegistration().getServiceUrl(), JSONObject.toJSONString(instance.getStatusInfo().getDetails()));
                        log.info(messageText);
                        break;
                    //服务上线
                    case "UP":
                        log.info("发送 服务上线 的通知!");
                        messageText = String
                                .format(template,titleNotice, instance.getRegistration().getName(), event.getInstance(),
                                        ((InstanceStatusChangedEvent) event).getStatusInfo().getStatus(), "服务上线通知",
                                        instance.getRegistration().getServiceUrl(), JSONObject.toJSONString(instance.getStatusInfo().getDetails()));
                        log.info(messageText);
                        break;
                    // 服务未知异常
                    case "UNKNOWN":
                        log.info("发送 服务未知异常 的通知!");
                        messageText = String
                                .format(template,titleAlarm, instance.getRegistration().getName(), event.getInstance(),
                                        ((InstanceStatusChangedEvent) event).getStatusInfo().getStatus(), "服务未知异常通知",
                                        instance.getRegistration().getServiceUrl(), JSONObject.toJSONString(instance.getStatusInfo().getDetails()));
                        log.info(messageText);
                        break;
                    default:
                        break;
                }
            } else {
   
                log.info("Instance {} ({}) {}", instance.getRegistration().getName(), event.getInstance(),
                        event.getType());
            }
        });
    }
}

2)邮箱报警整合

(1)整合邮箱依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-mail</artifactId>
</dependency>

(2)配置邮箱信息

# 邮件配置
spring.mail.host=smtp.qq.com
spring.mail.port=465
# 邮件发送人
spring.mail.username=1477227147@qq.com
# 授权码
spring.mail.password=ypqpgrqjojlnheef
spring.mail.default-encoding=utf-8
spring.mail.properties.mail.smtp.socketFactory.class=javax.net.ssl.SSLSocketFactory
spring.mail.properties.mail.debug=true
spring.mail.protocol=smtp
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.ssl.enable=true
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.test-connection=true

# 邮件发送人
spring.boot.admin.notify.mail.from=1477227147@qq.com
# 邮件接收人
spring.boot.admin.notify.mail.to=1477227147@qq.com
# 忽略什么情况才不发邮件,不填代表有变化都会发邮件
spring.boot.admin.notify.discord.ignore-changes=

(3)编写发送实现类代码

package com.cloud.api.admin.service.impl;

import com.cloud.api.admin.service.SendMailService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Service;

@Service
public class SendMailServiceImpl implements SendMailService {
   
    @Autowired
    private JavaMailSender javaMailSender;

    //发送人
    private String from = "1477227147@qq.com";
    //接收人
    private String to = "1477227147@qq.com";
    //标题
    private String subject = "cloud_api服务报警";
    //正文
    private String context = "测试邮件正文内容";

    @Override
    public void sendMail() {
   
        SimpleMailMessage message = new SimpleMailMessage();
        message.setFrom(from+"(小甜甜)");
        message.setTo(to);
        message.setSubject(subject);
        message.setText(context);
        javaMailSender.send(message);
    }
}

(5)编写实现类

package com.cloud.api.admin.service;

public interface SendMailService {
   

    public void sendMail();
}

(6)编写发送邮箱控制器

package com.cloud.api.admin.controller;

import com.cloud.api.admin.service.SendMailService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/admin/mail")
public class SendMailController {
   

    @Autowired
    private SendMailService sendMailService;


    @GetMapping("/sendMail")
    public void SendMail() {
   
        sendMailService.sendMail();
    }
}

四、AlibabaCloud微服务中级篇下鉴权

1、Sa-Token权限鉴权demo

加群领取
在这里插入图片描述

2)SpringSecurty权限认证demo

加群领取

五、AlibabaCloud微服高级篇章业务模型

具体看我的视频

1)微信APP统一登录

(1)微信网地址

https://open.weixin.qq.com/

(2)注册账户

在这里插入图片描述

(3)创建应用

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

(4)获取签名

https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1419319167&token=&lang=zh_CN

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

(5)

等待审核通过
在这里插入图片描述

(6)整合uniapp获取授权

uni.getProvider({
   
    service: 'oauth',
    success: function(res) {
   
        if (~res.provider.indexOf('weixin')) {
   
            uni.login({
   
                provider: 'weixin',
                success: function(loginRes) {
   

                    // 获取用户信息
                    uni.getUserInfo({
   
                        provider: 'weixin',
                        success: function(infoRes) {
   
                            // console.log('-------获取微信用户所有-----');
                            // console.log(JSON.stringify(infoRes .userInfo));
                            // console.log('-------获取微信用户所有1-----');
                            api.sendLoign({
   
                                "openId": infoRes.userInfo.openId,
                                "nickName": infoRes.userInfo.nickName,
                                "gender": infoRes.userInfo.gender,
                                "avatarUrl": infoRes.userInfo.avatarUrl,
                                "unionId": infoRes.userInfo.unionId,
                                "country": infoRes.userInfo.country,
                                "province": infoRes.userInfo.province,
                                "city": infoRes.userInfo.city
                            }).then(res = >{
   

                                if (res.datas.openId) {
   
                                    that.nickName = res.datas.nickName that.avatarUrl = res.datas.avatarUrl uni.setStorageSync('loign_status', res.datas.openId) uni.setStorageSync('loign_success', res.datas) uni.setStorageSync('radio', res.datas.radio) console.log(res)
                                } else {
   
                                    console.log('66')
                                }

                            }).
                            catch(err = >{
   
                                console.log(err)
                            })

                        },
                        fail(e) {
   
                            uni.showToast({
   
                                icon: 'none',
                                // title: '登陆失败,请确保已安装或已登录微信',
                                title: res.errMsg,
                                duration: 2000
                            });
                        }
                    });
                }
            });
        }
    },
    fail(e) {
   

        uni.showToast({
   
            icon: 'none',
            // title: '登陆失败,请确保已安装或已登录微信',
            title: "登陆失败,请确保已安装或已登录微信",
            duration: 2000
        });
    }
});

2)QQ APP统一登陆

1、QQ授权申请网站

https://connect.qq.com/

2、创建应用

在这里插入图片描述

3、获取签名

在这里插入图片描述

4、整合QQAPP授权

uni.login({
   
                    provider: 'qq',
                    success: function (loginRes) {
   
                        // 登录成功
                        uni.getUserInfo({
   
                            provider: 'qq',
                            success: function(info) {
   
                                // 获取用户信息成功, info.authResult保存用户信息
                                console.log(info.authResult)
                                console.log(info)
                                console.log(loginRes)
                            }
                        })
                    },
                    fail: function (err) {
   
                        // 登录授权失败  
                        // err.code是错误码
                    }
                });

5、效果

在这里插入图片描述

获取到的数据
在这里插入图片描述

3)微信小程序登录

六、kubesphere高级运维云原生

1)安装依赖

yum install socat -y
yum install conntrack -y
yum install ebtables -y
yum install ipset -y

2)关闭分区

临时生效

echo 0 > /proc/sys/vm/swappiness

永久生效

vi /etc/sysctl.conf
vm.swappiness = 0
sysctl -p

关闭

swapoff -a &

关闭swap挂载

vi /etc/fstab
# /dev/mapper/cl-swap     swap                    swap    defaults        0 0

3)关闭防火墙

systemctl stop firewalld
systemctl disable firewalld

4、DNF解析

Ip Master1
Ip Node1
Ip Node2

5、使用脚本快速安装

在这里插入图片描述

6、启动脚本

在这里插入图片描述

请去看我的视频搭建、由于命令太多

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

7、开启可插拔组件

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

8、监控日志

kubectl logs -n kubesphere-system $(kubectl get pod -n kubesphere-system -l 'app in (ks-install, ks-installer)' -o jsonpath='{.items[0].metadata.name}') -f

jar包下载

  • 搭建AlibabaCloud 首先搭建几个环境全部在Linux下
    1、[nacos     注册中心文档 ](https://nacos.io/enus/docs/quick-start.html)
    2、[nacos     注册中心jar包 ](https://github.com/alibaba/nacos/releases)
    3、[sentinel 流量控制,断路 文档](https://github.com/alibaba/Sentinel)  
    4、[apache-skywalking-apm-bin 链路跟踪](http://skywalking.apache.org/downloads/)   
    5、Rocketmq 的使用
    

项目下载地址
sentinel JAR下载地址

相关文章
|
1天前
|
人工智能 弹性计算 运维
阿里云大促选购攻略:新老用户权益区分,轻量、ECS、GPU、AI云产品采购怎么省钱
整体来看, 阿里云轻量应用服务器、阿里云ECS云服务器、阿里云GPU云服务器、阿里云大模型服务平台 大促给不同阶段使用者提供了差异化的资源方案。新用户抓住首购机会搭建起步业务,老用户借助续费折扣、限量算力套餐优化现有业务成本。轻量、 阿里云ECS云服务器 、GPU、AI云产品覆盖从基础建站到AI模型开发的各类场景,结合CLI命令查询资源价格,提前做好预算规划,才能用好大促优惠,拿到合适的云资源。
23 0
|
2天前
|
缓存 前端开发 程序员
DeepSeek-V4.1-Flash-1017 上手实测:3D 直出,效果到底如何
DeepSeek-V4.1-Flash-1017 上手实测:3D 飞行特斯拉、千里江山、折叠掌机一次直出,跑分 77%、最高档单任务 1.3 元
DeepSeek-V4.1-Flash-1017 上手实测:3D 直出,效果到底如何
|
4天前
|
自然语言处理 数据可视化 API
阿里云 2026 Qwen-image-3.0 能力全解:通义千问新版图像生成模型,核心特性、底层架构与实操教程
综合来看,Qwen-image-3.0代表图像生成模型向实用生产力方向演进的重要一步,超长指令理解、高精度文本渲染、多图编辑能力,补齐了文生图在结构化图文场景的短板。无论是个人创作者做海报、漫画,还是企业搭建自动化素材生产API服务,这套模型都提供了稳定可落地的方案。开发者可以基于上面提供的curl、Python同步、图生图编辑、异步任务代码快速搭建测试环境,通过大量提示词测试积累经验,把图像生成能力集成到各类多模态应用当中,挖掘图文自动化生产的效率提升空间。
246 0
|
4天前
|
人工智能 JSON 开发工具
Jev 决策模型 2026 技术详解:SystemOne 架构原理解读、实战测评与落地保姆指南
对于开发者来说,可以优先在原型环境用Playground验证业务可行性,小规模真实样本测试之后,再上线生产环境;优先使用SDK封装调用,高风险链路增加人工兜底逻辑。随着生态持续完善,System One这类决策模型,会成为AI应用架构中越来越重要的组成部分。
151 0
|
4天前
|
人工智能 移动开发 自然语言处理
阿里云千问办公 QwenWork详细介绍:产品核心能力、典型场景、价格及常见问题解答
千问办公(QwenWork)是阿里推出的一站式AI Agent生产力平台,主打“对话即交付”:用户用自然语言描述需求,即可自动生成PPT、Excel、网页、报告等可直接落地成果;深度集成钉钉,支持多模态解析、定时任务、技能复用与多端协同(网页/钉钉/桌面端),助力个人与企业提效降本。阿里千问办公QwenWork官网:https://t.aliyun.com/U/0VCTGt 阿里AI工作平台,一句话完成数据分析、PPT 生成、视频剪辑、网页搭建等复杂任务
|
4天前
|
人工智能 监控 安全
阿里云百炼 Token Plan 新版来了!四层调度怎么运作?套餐怎么选?项目怎么做?
新版百炼Token Plan以Credits统一计量为核心,通过四层云原生架构实现跨模型、跨模态、跨工具的额度共享与智能调度,兼容主流AI编程工具和MCP智能体生态。实际接入时,区分专属密钥、按需选择个人版或团队版、做好监控告警、合理设计Agent任务逻辑,就能在高频AI开发、多模态智能体、代码工程自动化等场景中显著降低管理复杂度。立即前往‌阿里云百炼Token Plan服务页面‌开启你的订阅之旅吧!
76 3
|
4天前
|
人工智能 安全 前端开发
面向邮箱 AI 助手的双目标钓鱼攻击风险与防御研究
本文分析AI时代新型“双目标钓鱼攻击”:攻击者在邮件中同时植入面向人类的欺诈内容和针对AI助手的隐藏提示注入载荷(如HTML注释、零字号文本等),诱导AI篡改摘要、伪造付款信息,间接误导业务决策。基于ACSC与Barracuda真实案例,揭示传统邮件防护与大模型安全机制的短板,提出涵盖邮件净化、AI权限管控、流程校验、人员培训与应急响应的闭环防御框架。(239字)
42 2
|
4天前
|
缓存 运维 安全
在阿里云上给 DSH 插件升级加一层稳妥保护
本文介绍DeepSeek Harness插件网关的内网部署与安全运维方案:支持私有Registry、Git、搜索及索引四类源内网化;提供快照回滚、自动禁用防护、进程外预检等机制;强调源收敛、日志巡检与磁盘规划,适用于阿里云VPC内需合规运维的团队。(239字)
45 2
|
1天前
|
人工智能 API 调度
给自己配一个云上常驻的超级 AI 助手,微信飞书钉钉都能找到它
CowAgent 是开源超级 AI 助手,具备任务规划、工具调用、技能扩展、个人知识库与长期记忆,支持主流大模型以及微信、飞书、钉钉等 IM 渠道。通过阿里云计算巢一键部署,2 分钟即可拥有一个云端常驻、随时可召唤的 AI 助手,统一 Web 控制台管理。
|
1天前
|
人工智能 安全 前端开发
把 DeepSeek 编程智能体放在云上,任何设备打开浏览器就能写代码
DeepSeek-Reasonix 是 DeepSeek 原生的 AI 编程智能体。通过阿里云计算巢一键部署,智能体常驻云端,任何设备打开浏览器就能进入同一个编程环境。支持配置驱动、插件扩展与多模型协作,API Key 保存在你自己的实例中,走计算巢安全代理访问,无需暴露公网端口。