Spring Cloud Alibaba(六)
目录:
- 分布式链路追踪-SkyWalking
- 为什么需要链路追踪
- 什么是SkyWalking
- SkyWalking核心概念
- 什么是探针Java Agent
- Java探针日志监控实现之环境搭建
- Java探针日志监控实现之探针实现
- 编写探针类TestAgent
- 搭建 Elasticsearch
- SkyWalking服务环境搭建
- 搭建微服务
- 微服务接入SkyWalking探针
- SkyWalking日志
- SkyWalioking告警
- Skywalking自定义告警规则
- SkyWalking网络钩子Webhooks
- SkyWalking短信通知
- SkyWalking邮件告警
分布式链路追踪-SkyWalking
为什么需要链路追踪
在这个微服务系统中,用户通过浏览器的 H5页面访问系统,这个用户请求会先抵达微服务网关组件,然后网关再把请求分发给各个微服务。所以你会发现,用户请求从发起到结束要经历 很多个微服务的处理,这里面还涉及到消息组件的集成。
存在的问题:
- 服务之间的依赖与被依赖的关系如何能够清晰的看到?
- 出现异常时如何能够快速定位到异常服务?
- 出现性能瓶颈时如何能够迅速定位哪个服务影响的?
链路
可以将链路理解为物理电路图
- 链路和电路图都有起点和终点。
- 链路和电路图都通过可视化得技术手段,来模拟真实组件得运行轨迹。
- 链路和电路图都非常复杂,并且随着系统复杂程度得增加,其可视化复杂度也会成几何倍数增加。
解决:
为了能够在分布式架构中快速定位问题,分布式链路追踪应运而生。将一次分布式请求还原成调用链路,进行日志记录,性能监控并将一次分布式请求的调用情况集中展示。比如各个服务节点上的耗时、请求具体到达哪台机器上、每个服务节点的请求状态等等。
常见链路追踪技术有那些
市面上有很多链路追踪的项目,其中也不乏一些优秀的,如下:
-
Sleuth:SpringCloud 提供的分布式系统中链路追踪解决方案。很可惜的是阿里系并没有链路追踪相关的开源项目,我们可以采用Spring Cloud Sleuth+Zipkin来做链路追踪的解决方案。
-
zipkin:由Twitter公司开源,开放源代码分布式的跟踪系统,用于收集服务的定时数据,以解决微服务架构中的延迟问题,包括:数据的收集、存储、查找和展现。该产品结合spring-cloud-sleuth使用较为简单, 集成很方便, 但是功能较简单。
-
pinpoint:韩国人开源的基于字节码注入的调用链分析,以及应用监控分析工具。特点是支持多种插件,UI功能强大,接入端无代码侵入
-
Skywalking:SkyWalking是本土开源的基于字节码注入的调用链分析,以及应用监控分析工具。特点是支持多种插件,UI功能较强,接入端无代码侵入。目前已加入Apache孵化器。
什么是SkyWalking
SkyWalking是开源的可观测平台,主要用于收集,分析,聚合和可视化服务和云原生基础设施的数据。Skywalking提供了一种简单得方式来维护分布式系统得视图关系。
SkyWalking
SkyWalking是开源的一款分布式追踪,分析,告警的工具,现已属于Apache旗下开源项目, SkyWalking为服务提供了自动探针代理,将数据通过gRPC或者HTTP传输给后端平台,后端平台将数据存储在Storage中,并且分析数据将结果展示在UI中。
优点:
- 多种监控手段多语言自动探针,Java,.NET Core 和 Node.JS
- 轻量高效,不需要大数据
- 模块化,UI、存储、集群管理多种机制可选,
- 支持告警
- 社区活跃
缺点:
较为新兴,成熟度不够高
SkyWalking核心概念
注意:
- 上部分 Agent :负责从应用中,收集链路信息,发送给 SkyWalking OAP 服务器。目前支持
SkyWalking、Zikpin、Jaeger 等提供的 Tracing 数据信息。而我们目前采用的是,SkyWalking Agent
收集 SkyWalking Tracing 数据,传递给服务器。- 下部分 SkyWalking OAP :负责接收 Agent 发送的
Tracing 数据信息,然后进行分析(Analysis Core) ,存储到外部存储器( Storage ),最终提供查询( Query
)功能。- 左部分 Storage :Tracing 数据存储。目前支持 ES、MySQL、Sharding Sphere、TiDB、H2
多种存储器。而我们目前采用的是 ES ,主要考虑是 SkyWalking 开发团队自己的生产环境采用 ES 为主。- 右部分SkyWalking UI :负责提供控台,查看链路等等。
什么是探针Java Agent
探针产生的背景
在开发过程中,开发人员经常会使用IDEA的Debug功能(包含本地和远程)调试应用,在JVM进程期间获取应用运行的JVM信息,变量信息等。这些个技术通过Java Agent来实现的,那么Java Agent到底是啥,为啥这么吊?
哪里有Java Agent:
- idea得Debug功能
- 热部署 JRebel
- 各种线上诊断工具
- 代码覆盖率工具
- 性能分析
什么是探针
Java Agent 又叫做 Java 探针,是在 JDK1.5 引入的一种可以动态修改 Java 字节码的技术。Java 类编译之后形成字节码被 JVM 执行,在 JVM 在执行这些字节码之前获取这些字节码信息,并且通过字节码转换器对这些字节码进行修改,来完成一些额外的功能。
Java探针工具技术原理
流程:
- 在JVM加载class二进制文件的时候,利用ASM动态的修改加载的class文件,在监控的方法前后添加计时器功能,用于计算监控方法耗时;
- 将监控的相关方法 和 耗时及内部调用情况,按照顺序放入处理器;
- 处理器利用栈先进后出的特点对方法调用先后顺序做处理,当一个请求处理结束后,将耗时方法轨迹和入参map输出到文件中;
- 然后区分出耗时的业务,转化为xml格式进行解析和分析。
Java探针日志监控实现之环境搭建
引入依赖
<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency>
编写HelloController
@RestController
public class HelloController {@GetMapping("/hello")public String hello() {return "hello agent";}
}
打包SpringBoot项目
Java探针日志监控实现之探针实现
如何使用Java Agent
JDK1.5引入了java.lang.instrument包,开发者可以很方便的实现字节码增强。其核心功能由java.lang.instrument.Instrumentation接口提供。
Instrumentation 有两种使用方式:
- 在应用运行之前,通过premain()方法来实现,在应用启动时侵入并代理应用。
- 在应用运行之后,通过调用Attach AP和agentmain()方法来实现
注意:
javassist是一个库,实现ClassFileTransformer接口中的transform()方法。ClassFileTransformer
这个接口的目的就是在class被装载到JVM之前将class字节码转换掉,从而达到动态注入代码的目的。
新建Maven项目javaagentdemo
Pom引入依赖
<dependencies><dependency><groupId>org.javassist</groupId><artifactId>javassist</artifactId><version>3.22.0-GA</version></dependency></dependencies><build><finalName>javaagent</finalName><plugins><!--META-INF 下 MANIFEST.MF 文件 内容Manifest-Version: 1.0Premain-Class: com.jenson.TestAgent下面Maven插件可以自动实现--><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-shade-plugin</artifactId><version>3.0.0</version><executions><execution><phase>package</phase><goals><goal>shade</goal></goals><configuration><transformers><transformerimplementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"><manifestEntries><Premain-Class>com.itbaizhan.PreMainTraceAgent</Premain-Class></manifestEntries></transformer></transformers></configuration></execution></executions></plugin></plugins></build>
编写探针类TestAgent
package com.jenson;import java.lang.instrument.Instrumentation;/*** @author Jenson*/
public class TestAgent {/*** 在main方法运行前,与main方法运行于同一JVM中** @param agentArgs agentArgs是premain函数得到的程序参数,随同"-javaagent"一同传入,* 与main函数不同的是,该参数是一个字符串而不是一个字符串数组,* 如果程序参数有多个,程序将自行解析这个字符串* @param inst 一个java.lang.instrument.Instrumentation实例,由JVM自动传入,* java.lang.instrument.Instrumentation是instrument包中的一个接口,* 也是核心部分,集中了其中几乎所有的功能方法,例如类定义的转换和操作*/public static void premain(String agentArgs, Instrumentation inst) {System.out.println("==============premain1 执行===================");System.out.println("agentArgs : " + agentArgs);// 添加Transformerinst.addTransformer(new TestTransformer());}
}
编写TestTransformer
/*** @author Jenson*/
public class TestTransformer implements ClassFileTransformer {public final String TEST_CLASS_NAME = "com.jjy.controller.HelloController";public final String METHOD_NAME = "hello";public byte[] transform(ClassLoader loader,String className,Class<?> classBeingRedefined,ProtectionDomain protectionDomain,byte[] classfileBuffer) throws IllegalClassFormatException {// System.out.println("className : " + className);String finalClassName = className.replace("/", ".");if (TEST_CLASS_NAME.equals(finalClassName)) {System.out.println("class name 匹配上了 !");CtClass ctClass;try {ctClass = ClassPool.getDefault().get(finalClassName);System.out.println("ctClass is OK !");CtMethod ctMethod = ctClass.getDeclaredMethod(METHOD_NAME);System.out.println("CtMethod is OK !");ctMethod.insertBefore("System.out.println(\"字节码添加成功,打印日志 !\");");return ctClass.toBytecode();} catch (Exception e) {e.printStackTrace();System.out.println(e.getMessage());}}return null;}
}
项目测试打包
添加javaagent启动参数
java -javaagent:agent路径 -jar 项目名.jar
启动,打印出日志
发送请求http://localhost:8080/hello
搭建 Elasticsearch
-
准备一台搭载有CentOS7系统的虚拟机,使用XShell连接虚拟机
-
关闭防火墙,方便访问ES
#关闭防火墙:
systemctl stop firewalld.service#禁止防火墙自启动:
systemctl disable firewalld.service
- 配置最大可创建文件数大小
#打开系统文件:
vim /etc/sysctl.conf#添加以下配置:
vm.max_map_count=655360#配置生效:
sysctl -p
- 由于ES不能以root用户运行,我们需要创建一个非root用户,此处创建一个名为es的用户:
#创建用户:
useradd es
安装服务
-
使用rz命令将linux版的ES上传至虚拟机
-
解压ES
#解压:
tar -zxvf elasticsearch-8.10.4-linux-x86_64.tar.gz#重命名:
mv elasticsearch-8.10.4 elasticsearch1#移动文件夹:
mv elasticsearch1 /usr/local/#es用户取得该文件夹权限:
chown -R es:es /usr/local/elasticsearch1
- 启动ES服务:
#切换为es用户:
su es#进入ES安装文件夹:
cd /usr/local/elasticsearch1/bin/#启动ES服务:
./elasticsearch
SkyWalking服务环境搭建
前置条件
- 安装jdk17
- 安装Elasticsearch
下载SkyWalking包
解压SkyWalking包
tar -zxvf apache-skywalking-apm-9.7.0.tar.gz -C /usr/local/
SkyWalking包目录介绍
介绍:
- webapp: Ul前端(web 监控页面)的jar包和配置文件
- oap-libs:后台应用的jar包,以及它的依赖jar包
- config:启动后台应用程序的配置文件,是使用的各种配置
- bin:各种启动脚本,一般使用脚本startup.*来启动web页面和对应的后台应用
- agent:代理服务jar包
修改配置文件
修改/usr/local/apache-skywalking-apm-bin/config/application.yml
启动 SkyWalking OAP 服务
bin/oapService.sh
SkyWalking OAP started successfully!
是否真正启动成功,打开 logs/skywalking-oap-server.log
日志文件,查看是否有错误日志。 首次启动时,因为 SkyWalking OAP 会创建 Elasticsearch 的索引,所以会“疯狂”的打印日志。
友情提示:
因为首次启动会创建 Elasticsearch 索引,所以可能会比较慢。
最终,我们看到如下日志,基本可以代表 SkyWalking OAP 服务启动成功:
启动 SkyWalking UI 服务
bin/webappService.shSkyWalking Web Application started successfully!
测试服务
请求http://192.168.66.100:8080
搭建微服务
引入依赖
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.49</version>
<!-- <scope>runtime</scope>--></dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.4</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency>
编写核心配置
创建application.yml文件
spring:application:# 应用名字name: cloud-payment-providercloud:nacos:discovery:# Nacos注册中心的地址server-addr: 192.168.47.100:8848# 数据库配置datasource:driver-class-name: com.mysql.jdbc.Driverurl: jdbc:mysql://localhost:3306/test?useSSL=false&useUnicode=true&characterEncoding=utf8&useSSL=false&useTimezone=true&serverTimezone=GMT%2B8username: rootpassword: 123456
server:port: 8003
编写主启动类
@MapperScan("com.jjy.mapper")
@SpringBootApplication
@Slf4j
public class PaymentMain8003 {public static void main(String[] args) {SpringApplication.run(PaymentMain8003.class,args);log.info("********* 服务提供者启动成功 ******");}
}
现有一张 User 表,其表结构如下:
id | name | age |
---|---|---|
1 | Jone | 18 |
2 | Jack | 20 |
3 | Tom | 28 |
4 | Sandy | 21 |
其对应的数据库 Schema 脚本如下:
DROP TABLE IF EXISTS `user`;CREATE TABLE `user`
(id BIGINT NOT NULL COMMENT '主键ID',name VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名',age INT NULL DEFAULT NULL COMMENT '年龄',PRIMARY KEY (id)
);
其对应的数据库 Data 脚本如下:
DELETE FROM `user`;INSERT INTO `user` (id, name, age) VALUES
(1, 'Jone', 18),
(2, 'Jack', 20),
(3, 'Tom', 28),
(4, 'Sandy', 21),
(5, 'Billie', 24);
编写实体类 User.java
@Data
@TableName("`user`")
public class User {private Long id;private String name;private Integer age;private String email;
}
编写 Mapper 包下的 UserMapper
接口
public interface UserMapper extends BaseMapper<User> {}
微服务接入SkyWalking探针
探针,用来收集和发送数据到归集器。
下载官方提供探针
网址https://skywalking.apache.org/downloads/
拷贝探针文件到项目中
修改项目的VM运行参数
点击菜单栏中的 Run -> EditConfigurations…,此处我们以 cloud-gateway-gateway9527 项目为例,修改参数如下:
-javaagent:C:\Users\Administrator\IdeaProjects\jjy_cloud\jjy_cloud\skywalking-agent\skywalking-agent.jar
-DSW_AGENT_NAME=consumer-order
-DSW_AGENT_COLLECTOR_BACKEND_SERVICES=192.168.47.100:11800
参数:
-javaagent:用于指定探针路径。
-DSW_AGENT_NAME:服务名字
-DSW_AGENT_COLLECTOR_BACKEND_SERVICES:连接地址
测试监控
SkyWalking日志
POM中引入相关依赖
Skywalking8.4.0版本开始才支持收集日志功能,同时pom需引用以下依赖。
<dependency><groupId>org.apache.skywalking</groupId><artifactId>apm-toolkit-logback-1.x</artifactId>**<version>9.1.0</version>
</dependency>
Logback配置
在resource文件中创建logback.xml并且加入配置。
<?xml version="1.0" encoding="utf-8" ?>
<configuration><appender name="console" class="ch.qos.logback.core.ConsoleAppender"><!-- 日志输出编码 --><encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder"><layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout"><pattern>%d{HH:mm:ss.SSS} [%thread] %-5level logger_name:%logger{36} - [%tid] - message:%msg%n</pattern></layout></encoder></appender><root level="info"><appender-ref ref="console"/></root></configuration>
Skywalking通过gRPC上报日志
gRPC报告程序可以将收集到的日志发送给Skywalking OAP服务器上。
<appender name="log" class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.log.GRPCLogClientAppender"><!-- 日志输出编码 --><encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder"><layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout"><pattern>%d{HH:mm:ss.SSS} [%thread] %-5level logger_name:%logger{36} - [%tid] - message:%msg%n</pattern></layout></encoder></appender><root level="info"><appender-ref ref="console"/><appender-ref ref="log"/></root>
打开你的agent/config/agent.config配置文件,添加如下配置信息,注意skywalking的log通信用的grpc:
# 指定要向其报告日志数据的GRPC服务器主机
plugin.toolkit.log.grpc.reporter.server_host=${SW_GRPC_LOG_SERVER_HOST:192.168.47.100}
# 指定要向其报告日志数据的GRPC服务器端口
plugin.toolkit.log.grpc.reporter.server_port=${SW_GRPC_LOG_SERVER_PORT:11800}
# 指定GRPC客户端要报告的日志数据的最大大小
plugin.toolkit.log.grpc.reporter.max_message_size=${SW_GRPC_LOG_MAX_MESSAGE_SIZE:10485760}
# 客户端向上游发送数据时将超时多长时间,单位是秒
plugin.toolkit.log.grpc.reporter.upstream_timeout=${SW_GRPC_LOG_GRPC_UPSTREAM_TIMEOUT:30}
注意:
注:gRPC报告程序可以将收集到的日志转发到SkyWalking OAP服务器或SkyWalking Satellite卫星。
测试
SkyWalioking告警
什么是skyWalking告警功能
SkyWalking是一个开源的分布式系统追踪和性能监控工具。除了提供实时的系统性能监控和分析功能外,SkyWalking还提供了告警功能,用于监控系统的指标数据,并在数据超过预设阈值时触发告警。
Skywalking默认支持7中通知:
web、grpc、微信、钉钉、飞书、华为weLink、slack
为什么要使用skyWalking的告警功能
- 及时发现异常情况
- 提高故障处理效率
- 避免数据丢失和损坏
- 提升系统性能和稳定性
如何使用skyWalking的告警功能
- 告警规则
告警规则定义了要监控的指标数据、阈值和触发条件。可以根据实际需求,定义多个告警规则。例如,可以设置当系统的平均响应时间超过100ms时,触发告警。 - 告警通知
告警通知定义了当告警触发时,要发送通知的方式和接收人员。可以通过邮件、短信。钉钉等方式发送告警通知。 - 告警持续时间
告警持续时间定义了告警状态的持续时间。当告警触发后,会持续发送通知,直到告警状态解除或达到设定的持续时间。
#告警配置文件: alarm-settings.yml
service_response_time rule:
#指定的规则
metrics-name : service _resp_time
op: ">"
# 阈值
threshold:1 #单位毫秒
#多久检查一次当前的指标数据是否符合告警规则
period:5
# 达到多少次告警后,发送告警消息
count:1
#告警消息内容
message:服务{name}最近5分钟以内响应时间超过了1ms
Skywalking自定义告警规则
默认告警规则
rules:service_resp_time_rule:metrics-name: service_resp_timeop: ">"threshold: 1000period: 10count: 3silence-period: 5message: Response time of service {name} is more than 1000ms in 3 minutes of last 10 minutes.service_sla_rule:metrics-name: service_slaop: "<"threshold: 8000period: 10count: 2silence-period: 3message: Successful rate of service {name} is lower than 80% in 2 minutes of last 10 minutes.service_p90_sla_rule:metrics-name: service_p90op: ">"threshold: 1000period: 10count: 3silence-period: 5message: 90% response time of service {name} is more than 1000ms in 3 minutes of last 10 minutes.service_instance_resp_time_rule:metrics-name: service_instance_resp_timeop: ">"threshold: 1000period: 10count: 2silence-period: 5message: Response time of service instance {name} is more than 1000ms in 2 minutes of last 10 minutes.webhooks:- http://127.0.0.1/notify/- http://127.0.0.1/go-wechat/
以上文件定义了默认的4种规则
- 最近3分钟内服务的平均响应时间超过1秒
- 最近2分钟服务成功率低于80%
- 最近3分钟90%服务响应时间超过1秒
- 最近2分钟内服务实例的平均响应时间超过1秒 规则中的参数属性如下
自定义告警规则
修改Skywalking配置文件。vim alarm-settings.yml
# vim config/alarm-settings.yml
service_response_time_rule:metrics-name: service_resp_timeop: ">"threshold: 1period: 1count: 1message: 服务{name}最近1分钟以内响应时间超过了1ms
温馨提示:注意预警属性对其
属性参照表
属性 | 含义 |
---|---|
metrics-name | oal脚本中的度量名称 |
threshold | 阈值,与metrics-name和下面的比较符号相匹配 |
op | 比较操作符,可以设定>,<,= |
period | 多久检查一次当前的指标数据是否符合告警规则,单位分钟 |
count | 达到多少次后,发送告警消息 |
silence-period | 在多久之内,忽略相同的告警消息 |
message | 告警消息内容 |
include-names | 本规则告警生效的服务列表 |
测试
SkyWalking网络钩子Webhooks
Webhooks网络钩子
Webhok可以简单理解为是一种Web层面的回调机制。告警就是一个事件,当事件发生时Skywalking会主动调用一个配置好的接口,这个接口就是所谓的Webhook;
注意:
Skywalking的告警消息会通过借HTTP请求进行发送,请求方法为POST (Content-Type
为application/json。其JSON数据实基于List<org.apache.skywalking.oap.server.core.alarm.AlarmMessage>进行序列化的。
JSON数据示例
[{"scopeId": 1, "scope": "SERVICE","name": "serviceA", "id0": "12", "id1": "", "ruleName": "service_resp_time_rule","alarmMessage": "alarmMessage xxxx","startTime": 1560524171000}]
创建项目
引入依赖
<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.22</version></dependency>
</dependencies>
创建接收实体类AlarmMessageDto
https://github.com/apache/skywalking/blob/v8.5.0/docs/en/setup/backend/backend-alarm.md
import lombok.Data;@Datapublic class AlarmMessageDto {private int scopeId;private String scope;private String name;private String id0;private String id1;private String ruleName;private String alarmMessage;private List<Tag> tags;private long startTime;private transient int period;private transient boolean onlyAsCondition;@Datapublic static class Tag{private String key;private String value;}
}
编写钩子接口
/*** 订单机器人通知的*/
@PostMapping("/alarm")
public void sendDinging(@RequestBody List<AlarmMessageDto> alarmMessageDtoList) {StringBuilder builder = new StringBuilder();alarmMessageDtoList.forEach(info -> {builder.append("\nscopeId:").append(info.getScopeId()).append("\nScope实体:").append(info.getScope()).append("\n告警消息:").append(info.getAlarmMessage()).append("\n告警规则:").append(info.getRuleName()).append("\n\n--------------").append("----------\n\n");});
}
配置网络钩子
alarm-settings.yml 增加alarm接口
SkyWalking短信通知
申请阿里短信服务
访问阿里云https://www.aliyun.com/,完成登录
进入短信服务
开通短信服务
购买短信条数
购买完成进入阿里云短信控制台https://dysms.console.aliyun.com/overview
绑定测试手机号
点击调用API发送短信,可以看到发送短信的JAVA代码。
申请阿里云秘钥,该秘钥在发送短信时会作为参数传入
添加相关依赖
<dependency><groupId>com.aliyun</groupId><artifactId>dysmsapi20170525</artifactId><version>2.0.24</version>
</dependency>
在通用模块编写发送短信服务接口
/*** 短信服务*/
public interface MessageService {/*** 发送短信** @param phoneNumber 手机号* @param code 验证码* @return 返回结果*/BaseResult sendMessage(String phoneNumber, String code);
}
在短信服务模块编写发送短信实现类
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import lombok.SneakyThrows;/*** 短信服务实现类*/
@Service
public class MessageServiceImpl implements MessageService {/*** 访问密钥ID*/@Value("${message.accessKeyId}")private String accessKeyId;/*** 访问密钥秘密*/@Value("${message.accessKeySecret}")private String accessKeySecret;/*** 使用AK&SK初始化账号Client** @param accessKeyId 访问密钥ID* @param accessKeySecret 访问密钥秘密* @return Client Client实例* @throws Exception 可能抛出的异常*/@SneakyThrowsprivate Client createClient(String accessKeyId, String accessKeySecret) {Config config = new Config().setAccessKeyId(accessKeyId).setAccessKeySecret(accessKeySecret);// 访问的域名config.endpoint = "dysmsapi.aliyuncs.com";return new Client(config);}/*** 发送短信** @param phoneNumber 手机号* @param code 验证码* @return BaseResult 返回结果*/@SneakyThrows@Overridepublic BaseResult sendMessage(String phoneNumber, String code) {Client client = createClient(accessKeyId, accessKeySecret);SendSmsRequest sendSmsRequest = new SendSmsRequest().setSignName("阿里云短信测试").setTemplateCode("SMS_154950909").setPhoneNumbers(phoneNumber).setTemplateParam("{\"code\":\"" + code + "\"}");RuntimeOptions runtime = new RuntimeOptions();// 复制代码运行请自行打印API的返回值SendSmsResponse sendSmsResponse = client.sendSmsWithOptions(sendSmsRequest, runtime);SendSmsResponseBody body = sendSmsResponse.getBody();if ("OK".equals(body.getCode())) {return new BaseResult(200, body.getCode(), body.getMessage());} else {return new BaseResult(500, body.getCode(), body.getMessage());}}
}
SkyWalking邮件告警
邮件发送原理
SMTP 协议全称为 Simple Mail Transfer Protocol,译作简单邮件传输协议,它定义了邮件客户端软件与 SMTP 服务器之间,以及 SMTP 服务器与 SMTP 服务器之间的通信规则。
授权过程
所以在使用springboot发送邮件之前,要开启POP3和SMTP协议,需要获得邮件服务器的授权码,这里以qq邮箱为例,展示获取授权码的过程:pkzljvxjbzvgbeci
在账户的下面有一个开启SMTP协议的开关并进行密码验证:
成功后会出现
POM引入依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-mail</artifactId>
</dependency>
配置邮箱基本信息
spring:mail:# 配置 SMTP 服务器地址host: smtp.qq.com# 发送者邮箱username: 877910962@qq.com# 配置密码,注意不是真正的密码,而是刚刚申请到的授权码password: pkzljvxjbzvgbeci# 默认的邮件编码为UTF-8default-encoding: UTF-8properties:mail:smtp:# 需要验证用户名密码auth: true# 设置为配置SMTP连接的属性。要使用STARTTLS,必须设置以下属性starttls:enable: truerequired: true
注意:
- 126邮箱SMTP服务器地址:smtp.126.com,端口号:465或者994
- 163邮箱SMTP服务器地址:smtp.163.com,端口号:465或者994
- yeah邮箱SMTP服务器地址:smtp.yeah.net,端口号:465或者994
- qq邮箱SMTP服务器地址:smtp.qq.com,端口号465或587
编写接口
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;import java.util.List;/*** 使用REST API发送邮件*/
@RestController
public class EmailController {/*** 注入JavaMailSender对象*/@Autowiredprivate JavaMailSender javaMailSender;/*** 发送邮件** @param alarmMessages 告警消息列表*/@GetMapping("sendMail")public void sendEmail(@RequestBody List<AlarmMessage> alarmMessages) {alarmMessages.forEach(info -> {SimpleMailMessage simpleMailMessage = new SimpleMailMessage();// 发件人simpleMailMessage.setFrom("877910962@qq.com");// 收件人simpleMailMessage.setTo("877910962@qq.com");// 邮件主题simpleMailMessage.setSubject(info.getScope());// 邮件内容simpleMailMessage.setText(info.getAlarmMessage());// 发送邮件javaMailSender.send(simpleMailMessage);});}
}
如果我的内容对你有帮助,请点赞,评论,收藏。创作不易,大家的支持就是我坚持下去的动力
相关文章:
Spring Cloud Alibaba(六)
目录: 分布式链路追踪-SkyWalking为什么需要链路追踪什么是SkyWalkingSkyWalking核心概念什么是探针Java AgentJava探针日志监控实现之环境搭建Java探针日志监控实现之探针实现编写探针类TestAgent搭建 ElasticsearchSkyWalking服务环境搭建搭建微服务微服务接入Sky…...
Http请求系列---【http的几个请求时间分别代表什么?以及如何设置?】
在HTTP客户端编程中,通常涉及以下几种关键的超时设置: 连接超时 (connectTimeout): 定义:在与服务器建立连接时等待的最大时间。这包括DNS解析时间、连接建立时间等。作用:如果在指定的时间内无法建立连接,…...
如何将CSDN博客下载为PDF文件
1.打开CSDN文章内容 2.按键盘上的f12键(或者右键—审查元素)进入浏览器调试模式,点击控制台(Console)进入控制台 3.在控制台输入以下代码,回车 4.在弹出的打印页面中将布局设置成横向,纵向会…...
关于IDEA 2024.2.1 Java EE 无框架配置Tomcat环境以及servlet使用教程
前言 这里的IDEA使用的是专业版,大学生认证后即可使用,社区版没有接触过暂不提,如果你是社区版,那么很可惜,本博客并不适用。本博客适用于java web刚入门的朋友学习使用,并不适用于高级部署。注意…...
【23种设计模式】七种设计原则:理论与 Java 实践
文章目录 23 种设计模式之七种设计原则:理论与 Java 实践一、单一职责原则(SRP - Single Responsibility Principle)(一)理论介绍(二)Java 实现示例(三)关键步骤…...
数据库与数据库管理系统概述
title: 数据库与数据库管理系统概述 date: 2024/12/7 updated: 2024/12/7 author: cmdragon excerpt: 在信息化迅速发展的时代,数据已成为企业和组织的重要资产。数据库与数据库管理系统(DBMS)是高效存储、管理和利用数据的核心工具。本文首先定义了数据库的基本概念和特…...
42_GAN网络详解(2)---常见的GAN
DCGAN CGAN 条件生成对抗网络(Conditional Generative Adversarial Networks, CGAN)是生成对抗网络(Generative Adversarial Networks, GAN)的一种变体,由Mehdi Mirza和Simon Osindero在2014年提出。CGAN的主要改进在…...
目前国内【齿轮检测仪】行业整体较为分散,行业竞争日趋激烈
摘要 根据 HengCe (恒策咨询)的统计及预测,2023年全球齿轮检测仪市场销售额达到了6.2亿美元,预计2030年将达到9.4亿美元,年复合增长率(CAGR)为6.0%(2024-2030)。地区层面来看&#…...
【学习路线】Java
Java基础 基础 基础语法 面向对象 集合框架 JCF 进阶 并发编程 JVM 企业级开发 框架 Spring Boot Spring Cloud 分布式 高性能 高可用 安全 基建 Docker 实战 数据库 MySQL Redis 计算机基础 计算机组成原理 操作系统 计算机网络 数据结构与算法 设计模式 参考:…...
一文说清flink从编码到部署上线
引言:目前flink的文章比较多、杂,很少有一个文章,从一个简单的例子入手,说清楚从编码、构建、部署全流程是怎么样的。所以编写本文,自己做个记录备查同时跟大家分享一下。本文以简单的mysql cdc为例展开说明。 环境说明…...
dolphinScheduler 任务调度
#Using docker-compose to Start Server #下载:https://dlcdn.apache.org/dolphinscheduler/3.1.9/apache-dolphinscheduler-3.1.9-src.tar.gz $ DOLPHINSCHEDULER_VERSION3.1.9 $ tar -zxf apache-dolphinscheduler-"${DOLPHINSCHEDULER_VERSION}"-src.t…...
【opencv入门教程】14. 矩阵乘除运算
文章选自: 一、函数multiply、divide //乘法 CV_EXPORTS_W void multiply(InputArray src1, InputArray src2,OutputArray dst, double scale 1, int dtype -1); brief 计算两个数组的每个元素的按比例缩放乘积 note 当输出数组的深度为 CV_32S 时,…...
SpEL
SPEL(Spring Expression Language)是一个强大的 支持查询和操作对象的表达式语言 Spring:https://docs.spring.io/spring-framework/docs/3.2.x/spring-framework-reference/html/expressions.html#expressions 表达式语言支持以下功能 文本…...
【SpringMVC】参数传递 重定向与转发 REST风格
文章目录 参数传递重定向与转发REST风格 参数传递 ModelAndView:包含视图信息和模型数据信息 public ModelAndView index1(){// 返回页面ModelAndView modelAndView new ModelAndView("视图名");// 或// ModelAndView modelAndView new ModelAndView(…...
OD B卷【考勤信息】
题目 公司用一个字符串来表示员工的出勤信息: absent: 缺勤;late: 迟到;leaveearly: 早退;present: 正常上班 现在根据员工出勤信息,判断本次能否获得出勤奖,能获得出勤奖的条件如下:缺勤不超…...
CTF学习24.11.19[音频隐写]
MISC07[音频隐写] 隐写术 隐写术是一门关于信息隐藏的技巧与科学,所谓信息隐藏指的是不让除预期的接收者之外的任何人知晓信息的传递事件或者信息的内容。隐写术的英文叫做Steganography,来源于特里特米乌斯的一本讲述密码学与隐写术的著作Steganograp…...
万字长文解读深度学习——VQ-VAE和VQ-VAE-2
🌺历史文章列表🌺 深度学习——优化算法、激活函数、归一化、正则化 深度学习——权重初始化、评估指标、梯度消失和梯度爆炸 深度学习——前向传播与反向传播、神经网络(前馈神经网络与反馈神经网络)、常见算法概要汇总 万字长…...
电脑投屏到电脑:Windows,macOS及Linux系统可以相互投屏!
本篇其实是电脑远程投屏到另一台电脑的操作介绍。本篇文章的方法可用于Windows,macOS及Linux系统的相互投屏。 为了避免介绍过程中出现“这台电脑”投屏到“那台电脑”的混乱表述,假定当前屏幕投出端是Windows系统电脑,屏幕接收端是Linux系统…...
【JuMP.jl】埃尔米特矩阵半定规划
考虑一个埃尔米特矩阵的半定规划问题: 给定矩阵 P [ 1 i i − 1 ] P\left[\begin{matrix} 1 & i\\ i & -1 \end{matrix}\right] P[1ii−1] 计算 min X ⪰ 0 R e ( t r ( P H X ) ) \begin{aligned} \min_{X\succeq 0} Re(tr(P^HX)) \end{aligned}…...
MyCat(mysql的中间件)
文章目录 1 1...
Spring AI入门到精通:气象天气预测技术详解
引言 在全球气候变化的背景下,气象天气的准确预测对于农业、交通、能源等多个领域具有极其重要的意义。随着人工智能(AI)技术的飞速发展,特别是生成式AI和深度学习技术的突破,气象天气预测迎来了新的机遇。Spring AI&…...
ollama的本地部署内含推荐模型!
下载ollama 1.从官网(https://ollama.com/)下载ollama软件并且安装 注意软件是默认安装在C盘 打开cmd后输入:查看命令ollama --version 查看模型仓库:ollama list 显示模型信息: ollama show 在cmd中去拉模型: ollama pull 模…...
要使用 OpenResty 创建一个接口,返回客户端的 IP 地址,并以 JSON 格式输出
要使用 OpenResty 创建一个接口,返回客户端的 IP 地址,并以 JSON 格式输出 要使用 OpenResty 创建一个接口,返回客户端的 IP 地址,并以 JSON 格式输出方案一解决方案(openresty使用cjson)说明:使…...
排序的事
排序的事 C语言实现C实现Java实现Python实现 💐The Begin💐点点关注,收藏不迷路💐 输入n个不相同的正整数,每个数都不超过n。现在需要你把这些整数进行升序排序,每次可以交换两个数的位置,最少需…...
基于Matlab扩展卡尔曼滤波的GPS与DME组合无人机导航系统设计与实现
随着无人机(UAV)在农业监测、环境保护、物流运输、灾害救援等各个领域的广泛应用,精准且可靠的导航系统已成为提升无人机性能和任务执行能力的关键因素。传统的导航方法依赖于单一传感器,往往难以在复杂和动态的环境中提供足够的定…...
GEOBench-VLM:专为地理空间任务设计的视觉-语言模型基准测试数据集
2024-11-29 ,由穆罕默德本扎耶德人工智能大学等机构创建了GEOBench-VLM数据集,目的评估视觉-语言模型(VLM)在地理空间任务中的表现。该数据集的推出填补了现有基准测试在地理空间应用中的空白,提供了超过10,000个经过人工验证的指…...
重邮+数字信号处理实验三:z变换及离散LTI系统的z域分析
实验目的: ( 1 )学会运用 Matlab 求离散时间信号的有理函数 z 变换的部分分式展开; ( 2 )学会运用 Matlab 分析离散时间系统的系统函数的零极点; ( 3 )学会运用 …...
跟 Synchronized 相比,可重入锁 ReentrantLock 其实现原理有什么不同?
与Synchronized相比,可重入锁ReentrantLock在实现原理上存在显著差异。以下是对两者实现原理的详细比较: 一、基本机制 Synchronized: 是JVM基于监视器(Monitor)的实现,提供的内置锁。每个对象都有一个监…...
如何在 Cursor-AI 中配置 Conda 虚拟环境
如何在 CursorAI 中配置 Conda 虚拟环境并使用快捷键 引言 在数据科学和机器学习的开发过程中,使用虚拟环境来管理项目的依赖库是非常重要的。Conda 是一个常用的环境管理工具,它可以帮助我们创建和管理虚拟环境。在这篇博客中,我将介绍如何…...
carsim2020安装记录
step1:双击carsim安装包,进行正常安装, 参考连接:carsim安装流程 这里注意如何破解,踩了一晚上坑 step2:破解d 大体步骤为: 将param目录以及生成MSCLIC_SSQ.lic文件以及MADLIC_SSQ.lic文件,将这两个文件…...
前端开发底层逻辑全解析
前端开发就像是构建一座数字大厦的外表装饰与交互系统,而理解其底层逻辑则是打好坚实基础的关键。今天,我们就来深入剖析前端开发的底层逻辑。 一、浏览器的工作机制:幕后的魔法手 当我们在浏览器中打开一个网页时,一系列复杂的操…...
WSL2下如何部署CosyVoice并开启API服务
环境: WSL2 英伟达4070ti 12G Win10 Ubuntu22.04 问题描述: WSL下如何部署CosyVoice并开启API服务 解决方案: CosyVoice 下载不顺的时候,最好提前开科学 一、部署 1.拉取源码 git clone –recursive https://github.com/FunAudioLLM/CosyVoice.gitwsl下拉取 gi…...
操作系统Lesson8 - 同步互斥机制和编程方法
文章目录 忙等互斥与睡眠唤醒如何解决设立临界区 忙等互斥屏蔽中断可行性对单核处理系统上,最简单 锁变量严格轮询法Peterson算法问题代码:两个人互相谦让,造成死锁。解决方案 TSL指令 忙等互斥与睡眠唤醒 为了解决多个进程之间的操作不会相…...
OSGeo4W64和qtcreator环境配置
OSGeo4W64 release 64位,放在哪个盘都行 随便找个msvc64编译器 完整demo:OSGeo4W64和qtcreator 分享文件:osg4w64和qt.7z 链接:https://pan.xunlei.com/s/VODV85IkEKqQO88_QWNO_Be0A1# 提取码:8k8f 复制这段内容后打开…...
Ubuntu22部署MySQL5.7详细教程
Ubuntu22部署MySQL5.7详细教程 一、下载MySQL安装包二、安装MySQL三、启动MySQL 检查状态登录MySQL 四、开启远程访问功能 1、允许其他主机通过root访问数据库2、修改配置文件,允许其他IP通过自定义端口访问 五、使用Navicat连接数据库 默认情况下,Ubun…...
http和https分别是什么?区别是什么?
HTTP和HTTPS是两种常见的网络协议,用于在Web上进行数据传输。以下是它们的简要解释和主要区别: HTTP(Hypertext Transfer Protocol) HTTP是一种应用层协议,用于在Web上传输数据。它是互联网上应用最为广泛的一种网络…...
文件IO——01
1. 认识文件 1)文件概念 “文件”是一个广义的概念,可以代表很多东西 操作系统里,会把很多的硬件设备和软件资源抽象成“文件”,统一管理 但是大部分情况下的文件,都是指硬盘的文件(文件相当于是对“硬…...
23种设计模式之装饰模式
目录 1. 简介2. 代码2.1 ABatterCake (抽象组件)2.2 BatterCake (具体组件)2.3 ADecorator (抽象装饰者)2.4 EggDecorator (具体装饰者)2.5 SausageDecorator(具体装饰者…...
Ubuntu22.04系统源码编译OpenCV 4.10.0(包含opencv_contrib)
因项目需要使用不同版本的OpenCV,而本地的Ubuntu22.04系统装了ROS2自带OpenCV 4.5.4的版本,于是编译一个OpenCV 4.10.0(带opencv_contrib)版本,给特定的项目使用,这就不用换个设备后重新安装OpenCV 了&…...
《OpenCV:视觉世界的魔法钥匙》
《OpenCV:视觉世界的魔法钥匙》 一、OpenCV 是什么1. 起源与发展支持2. 特点与优势3. 编程语言支持 二、OpenCV 的发展历程1. 重要版本发布时间线2. 版本更新内容 三、OpenCV 的主要功能1. 图像处理2. 特征提取3. 目标检测4. 运动分析5. 人脸识别6. 其他功能 四、Op…...
Day7 苍穹外卖项目 缓存菜品、SpringCache框架、缓存套餐、添加购物车、查看购物车、清空购物车
目录 1.缓存菜品 1.1 问题说明 1.2 实现思路 1.3 代码开发 1.3.1 加入缓存 1.3.2 清除缓存 1.3.2.1 新增菜品优化 1.3.2.2 菜品批量删除优化 1.3.2.3 修改菜品优化 1.3.2.4 菜品起售停售优化 1.4 功能测试 1.4.1 加入缓存 1.4.2 菜品修改 1.5 代码提交 2.缓存套餐 2.1 Spring C…...
华为路由策略和策略路由学习笔记
控制网络流量可达性 思考:如何控制网络流量可达性? 解决方案一:可通过修改路由条目(即对接收和发布的路由进行过滤)来控制流量可达性,这种方式称为路由策略。 解决方案二:可直接通过依据用户制定的策略进行转发,且该策略优于路由…...
网上图书购物管理系统|Java|SSM|VUE| 前后端分离
【一】可以提供远程部署安装,包扩环境 【二】提供软件相关的安装包 【三】如果需要提供java入门资料可咨询 【技术栈】 1⃣️:架构: B/S、MVC 2⃣️:系统环境:Windowsh/Mac 3⃣️:开发环境:IDEA、JDK1.8、M…...
杂发单的单据类型一个参数的逻辑
【核准中可改】被产线滥用了。它们可以这样做,开立一张杂发单,打印出来交领导层签名。单据要交财务做核算的。然后去修改杂发单的材料。以为可以瞒天过海。2个仓库,一个中掉坑里,一个发现了它们的拙劣的手段,上报之后没…...
AUTOSAR CP中基于通信模块(COM)的Transformer-R24的规范导读
该文档是关于 AUTOSAR CP中基于通信模块(COM)的Transformer的规范说明,主要内容包括引言、相关文档、约束与假设、功能规范、API 规范、配置规范等,旨在为汽车电子系统开发中基于 COM 的Transformer提供全面的技术规范和指导。 一…...
yarn : 无法加载文件 C:\Users\L\AppData\Roaming\npm\yarn.ps1,因为在此系统上禁
关于执行安装yarn命令后执行yarn -v报错: 先确认执行安装yarn命令是否有误 # 安装yarn npm install yarn -g 终端输入set-ExecutionPolicy RemoteSigned 当然如果yarn -v仍然执行失败,考虑使用管理员方式运行IDEA, 注:如上操作…...
证明直纹面是可展曲面沿着直母线,曲面的切平面不变
目录 证明直纹面是可展曲面的当且仅当沿着直母线,曲面的切平面不变 证明直纹面是可展曲面的当且仅当沿着直母线,曲面的切平面不变 直纹面是可展曲面当且仅当沿着直母线,曲面的切平面不变. 证明:设直纹面 S S S的参数式为 r ( u …...
一种将png图像批量转换为RGB格式的方法
1.前言 大家在做2D图像分类的时候,代码经常要求图像是RGB格式。有时候我们的图像并不是RGB,尤其是处理病理图像切分的pach的时候,这时候就需要批量进行格式转换了。好了,直接上代码: import os from PIL import Image…...
Python 中的继承机制是什么样的?
Python的继承机制允许一个类(子类)继承另一个类(父类或基类)的属性和方法。 通过继承,可以实现代码复用,同时也能让代码结构更加清晰、易于维护。 Python支持单继承和多继承,并且有丰富的特性…...
MyBatis注解开发(一)
目录 使用注解完成CRUD 1. SqlMapConfig.xml配置文件 2. UserDao接口方法和注解的编写 3. UserTest测试方法的编写 注解方式比较简单,但是实际开发不推荐使用注解,使用配置文件的方式,不需要改源代码。 Insert:添加 Update:修改 Delete:删…...