学成在线- 6分片上传,8xxl-job
课程模块开发 分布式事务,消息表
spring-security oauth 用户认证授权 学成在线
学成在线认证授权 一些代码
黑马分布式事物
框架学习 - 若依 / RuoYi-Vue-Plus
统一数据权限
若依数据权限使用
数据权限表结构
eqm 接收设备报文信息。
设备的指标信息
),传递到其他服务,进行业务逻辑处理。通过emqx 中的web hook ,设备断开连接,执行回调函数,发送到服务器。
根据设备id 设置设备的 online status
emqx服务器配置代理主题,客户端连接上emqx就可以通过配置%c(客户端id),设备即可通过代理订阅方式,订阅主题。设备通过指定的主题发送客户端id到emqx。后台订阅主题,将客户端信息,和设备信息绑定。
influx db 主要用来存储一些时间序列的数据。(按时间维度索引的数据)
物联网设备发送过来的报文指标信息,存入influx db中
设备很多,传输过来的报文也很多。
InfuxDB中的概念 | 传统数据库概念 |
---|---|
database | 数据库 |
measurement | 数据库中的表 |
point | 表中的行 |
Point是由时间戳(time)、标签(tags)、数据(fields)
三部分组成,具体的含义如下:
point属性 | 含义 |
---|---|
time | 数据记录的时间,主索引,默认自动生成,相当于每行数据都具备的列 |
tags | 相当于有索引的列。tag中存储的值的类型是字符串类型 如果需要检索就 是tags |
fields | value值,没有索引的列。field中存储的值得类型:字符串、浮点数(Double)、整数、布尔型。一个field value总是和一个timestamp相关联 如果查询是就是这个值,就用fields |
上面的截图展示了在名字是test的measurement存储的一些数据,我们可以通过常规的sql语句查询到这些数据。这些测试数据是在一定时间内产生的温度指标数据,其中每行数据包含了具体产生的时间(time)、是否告警(alarm)、设备编号(deviceId)、告警级别(level)、指标名称(quotaName)、数值单位(unit)、指标数值(value)。
其中value列就是filed,里面存储的是Integer;time列是每条记录产生的时间;其余列都是tag,存储的数据都是字符串。
# hostname=server01 是索引列,继续添加索引列就使用逗号。 service 也是tag列
insert disk_free,hostname_ss1,service=app value=2222i
insert disk_free,hostname=server01 value=442221834240i
# tags 不用加引号,因为只能是字符串。
insert disk_free,hostname=server01 value=442221834240i,sv="aaaa"
sv 是filed类型,加引号,要识别是field 的字符串类型
其中 disk_free 就是表名,hostname是索引(tag),value=xx是记录值(field),记录值可以有多个,系统自带追加时间戳
retention policy 存储策略。 保存数据的时间
shard 分片
存储目录
influxdb的数据存储有三个目录,分别是meta、wal、data:
用于写的
用于查询的
设备通过eqm x 上报设备报文数据,服务端接收数据保存到influx db中。
这里需要说明的是:
在要执行的sql里的group by分组里使用了InfluxDB的time时间函数
之后配合select中的count函数就可以获取到具体时间维度里汇总里的总数了,这样就能获取到我们想要的汇总数据了。
InfluxDB除了会根据sql语句返回pointValue也会同时返回每一条数据对应的time时间列。
top() 函数
告警透传
,同样的告警,在沉默周期内不在重复提示告警。
redis 实现
String 类型,key 为设备id,过期时间为5minutes,存在就不再进行告警。
EMQ的webHook来实现实现设备断网监控,并更新设备状态。
webhook由emqx_web_hook
插件提供的,将EMQ X中的钩子事件(连接,断开
)通知到某个Web服务的功能
告警信息推送到emqx,前端订阅消费。
设备信息,设备指标信息。
执行流程:
1、用户登录,请求认证服务
2、认证服务认证通过,生成 jwt
令牌,将 jwt
令牌及相关信息写入 Redis
,并且将身份令牌写入 cookie
3、用户访问资源页面,带着 cookie
到网关
4、网关从 cookie
获取 token
,并查询 Redis 校验 token,如果 token 不存在则拒绝访问,否则放行
5、用户退出,请求认证服务,清除 redis 中的 token
,并且删除 cookie
中的 token
使用 redis
存储用户的身份令牌有以下作用:
1、实现用户退出注销功能,服务端清除令牌后,即使客户端请求携带 token 也是无效的。
2、由于 jwt 令牌过长
,不宜存储在cookie
中,所以将jwt
的 身份令牌 存储在 redis,客户端请求服务端时附带这个 身份令牌,服务端根据身份令牌到 redis 中取出身份令牌对应的 jwt 令牌。
本地消息表+任务调度方式。实现分布式事物最终数据一致性。
熔断是当下游服务异常时一种保护系统的手段,降级是熔断后上游服务处理熔断的方法。
消息可靠性、幂等性、消息堆积。
spring 事物原理
一个方法上加了@transaction注解,执行方法时,开启事物。
开启事物的时候,创建数据库连接,
编写可靠事物代码。
通过spring 声明式事务,多种情况下会失效。
/**
* @author hyp
* @date 2023/5/24
*/
public class TransactionDemo {
@Transactional
public void doTx() {
// start tx
//当前上下文事物执行完后,执行下面回调方法
TransactionUtils.doAfterTransaction(() -> {
//send mq rpc
});
// end tx
}
}
// 工具类
/**
* 本地事物提交后 回方法工具类
* TranscationSynazation
* @author hyp
* @date 2023/5/24
*/
public class TransactionUtils {
public static void doAfterTransaction(Runnable runnable){
//判断当前上下文是否由事物激活
if(TransactionSynchronizationManager.isActualTransactionActive()){
// 注册当前事务上下文同步器
TransactionSynchronizationManager.registerSynchronization(new TransactionCompletion(runnable));
}
}
}
class TransactionCompletion implements TransactionSynchronization{
private Runnable runnable;
public TransactionCompletion(Runnable runnable) {
this.runnable = runnable;
}
/**
* int STATUS_COMMITTED = 0;
* int STATUS_ROLLED_BACK = 1;
* int STATUS_UNKNOWN = 2;
* @param status 事物状态
*/
@Override
public void afterCompletion(int status) {
if(status==TransactionSynchronization.STATUS_COMMITTED){
// 事物成功提交后才执行回
//回调函数,
runnable.run();
}
}
}
多线程控制事物
先把整个大文件md5生成,检查是是否已经上传过。(MD5 文件)
判断数据库有,文件服务器有才不上传。
对分块文件上传前检查 是否存在 文件服务器目录**(md5前2位/md5 3-4位/md5名 目录)** md5 前4位 做2个子目录 ,chunk 存 分块 (接口 MD5,分块文件 序号)
上传分块 (MD5 ,分块序号,分块文件)
合并文件 (MD5 ,分块总数,文件名称)
合并文件
校验文件服务器合并后的MD5 和上传的MD5是否一致
文件信息入库
清除分块文件
在上传文件到文件存储服务器后,准备把文件信息入库。
非事物方法 直接调用事物方法( 并不是以代理对象调用)
upload方法 调用了本类的 信息入库的方法,upload方法没有事物,导致 信息入库方法的事物失效。
首先分页参数放在ThreadLocal中,拦截执行的sql,根据数据库的类型添加对应的sql语句。
计算出了 total总条数,pageNum当前第几页,pageSize 等数据。
#{} 是一个占位符,解析为SQL时,会将形参变量的值取出,并自动给其添加引号。
${}
解析为SQL时,将形参变量的值直接取出,直接拼接显示在SQL中
常见的使用${}的情况:
1.当sql中表名是从参数中取的情况
2.order by排序语句中,因为order by 后边必须跟字段名,这个字段名不能带引号,如果带引号会被识别会字符串,而不是字段。
-----------------线上问题--------------
线上问题处理案例:出乎意料的数据库连接池 | 京东云技术团队
Redis缓存的主要异常及解决方案
------------------mybatis---------
源码学习之MyBatis的底层查询原理 | 京东云技术团队
Mybatis的parameterType造成线程阻塞问题分析 | 京东云技术团队
------------------------------------并发编程------
关于并发编程与线程安全的思考与实践 | 京东云技术团队–synchronized
架构师日记-从代码到设计的性能优化指南 | 京东云技术团队
JAVA多线程并发编程-避坑指南
rt下降40%?程序并行优化六步法 | 京东云技术团队
------------------------------模式-----------------------
1分钟学会、3分钟上手、5分钟应用,快速上手责任链框架详解 | 京东云技术团队
烂怂if-else代码优化方案 | 京东云技术团队
---------------------------返回结果----------------------
一站式统一返回值封装、异常处理、异常错误码解决方案—最强的Sping Boot接口优雅响应处理器 | 京东云技术团队
如何优雅的处理异常
--------------------------------jvm-------------------------------
线上FullGC问题排查实践——手把手教你排查线上问题
谈JVM参数GC线程数ParallelGCThreads合理性设置
jvm中类和对象定义存储基础知识 | 京东云技术团队
源码剖析JVM类加载机制
从原理聊JVM(一):染色标记和垃圾回收算法
线上FullGC问题排查实践——手把手教你排查线上问题
------------事务、幂等--------------------
幂等设计详解 | 京东云技术团队
如何实现数据库读一致性 | 京东云技术团队
如何在微服务下保证事务的一致性 | 京东云技术团队
------------redis-----
Redis缓存高可用集群
缓存空间优化实践
Redis数据结构(一)-Redis的数据存储及String类型的实现
京东云开发者|Redis数据结构(二)-List、Hash、Set及Sorted Set的结构实现
-----mysql-----------
一文了解MySQL中的多版本并发控制
一文带你搞懂如何优化慢SQL
记录一次数据库CPU被打满的排查过程
这个 MySQL bug 99% 的人会踩坑!
MySQL性能优化浅析及线上案例
深入理解MySQL索引底层数据结构
【实践篇】教你玩转JWT认证—从一个优惠券聊起 | 京东云技术团队
多个对象间,存在一对多的依赖关系,当一个对象的状态发生关系时,所有依赖于它的对象都得到通知并被自动更新。这种模式有时候又被称为发布订阅模式,
spring 事件机制。
不同事件业务触发的情况下,会去通知用户邮件、短信、推送等。不同的事件,不同的业务场景下,可能时不同的推送组合,通知用户。
首先就是通过 不同业务场景 if else 判断 应该调用哪几个。
改进:
通过观察者模式,让事件的发生和通知分开处理,在代码上进行解耦。
接着,关于每种业务场景,有哪几种通知,又抽取了策略模式的接口,动态的组合每一种业务需要对应哪些通知类型。后期更灵活之后,把业务,通知组合可以放到配置中心区,达到的效果,如果需要新增业务,只需要改一下配置中心的配置,就能够组合不同的通知的模式。进行通知。 从而更加解耦,更有扩展性。
通过温度,湿度,电压,获取对应的level。根据level,通过策略模式在map中获取发送消息组合的list。
遍历所有发送消息实现类,判断是否在以上获取到的消息组合集合中。
(1)使用redis来保存每个人的工单数据,每次创建工单在redis里使用原子增,不用考虑锁。这样得到每日最低工单人员的查询可以做到对数据库零查询。
(2)使用redis的ZSet可以实现数据的自动排序,无需手动排序,再次提升了程序的运行效率,降低了代码的复杂度。
(3)key的规则,以固定字符串(前缀)+时间+区域+工单类别(运营/运维)为大key,以人员id做小key,过期时间为2天。
(4)redis工单数列表初始化,由xxl-job负责处理,每日下午生成第2天的工单数列表。
mqtt 以数据为中心,而http是以文本为中心。http 是应用于服务端、客户端请求响应协议。mqtt 是轻量级的(将数据作为二进制字节数组传输)和发布订阅的模型。适用于资源受限的设备,有助于节省带宽。
发布订阅模式,可以进行解耦。(发布者和订阅者的解耦)不需要直接建立联系,无需等待。
文本传输协议,无状态的,请求、响应方式运行的协议。
报文格式
起始行
头部字段集合
空行
消息正文
Syn 同步位,
第一次:客户端发送 同步位Syn=1,seq=x(x是随机的)发送给客户端。
第二次:服务器发送 Syn=1,ACK=1,ack=x+1, seq=y(服务器随机生成)
第三次:客户端 ACK=1,ack=y+1, seq=x+1
可以进行数据传送。
Syn 洪泛攻击是在osi 的第四层,传输层。
例用三次握手,攻击者发送TCP SYN,syn是tcp 三次握手中的第一个数据包。而当服务器发送ACK后,攻击者就不对其进行再确认,那这个TCP连接就会处于挂起状态。即办连接状态。服务器收不到 确认的确认,还会重复发送ACK给攻击者,服务器上有大量的挂起TCP连接,消耗CPU和内存。
防火墙技术,
负载均衡,限流。缓存。
FIN=1 断开连接,客户端停止向服务端发送数据
HTTP 是超文本传输协议,信息是明文传输,存在安全风险的问题。HTTPS 则解决 HTTP 不安全的缺陷,在 TCP 和 HTTP 网络层之间加入了 SSL/TLS 安全协议,使得报文能够加密传输。
HTTP 连接建立相对简单, TCP 三次握手之后便可进行 HTTP 的报文传输。而 HTTPS 在 TCP 三次握手之后,还需进行 SSL/TLS 的握手过程,才可进入加密报文传输。
两者的默认端口不一样,HTTP 默认端口号是 80,HTTPS 默认端口号是 443。
HTTPS 协议需要向 CA(证书权威机构)申请数字证书,来保证服务器的身份是可信的。
HTTP 由于是明文传输,所以安全上存在以下三个风险:
窃听风险,比如通信链路上可以获取通信内容,用户号容易没。
篡改风险,比如强制植入垃圾广告,视觉污染,用户眼容易瞎。
冒充风险,比如冒充淘宝网站,用户钱容易没。
HTTPS 在 HTTP 与 TCP 层之间加入了 SSL/TLS 协议
HTTPS 是如何解决上面的三个风险的?
机密性
,解决了窃听的风险。完整性
,它能够为数据生成独一无二的「指纹」,指纹用于校验数据的完整性,解决了篡改的风险。HTTP/2协议是基于HTTPS的,所以HTTP/2的安全性是有保障的。
HTTP/2会压缩头(Header),如果你同时发送多个请求,他们的头是一样的或者是相似的,那么协议会帮你消除重复的部分。
HTTP/2不再像HTTP/1.1里的纯文本的报文,而是全面采用了二进制格式。头信息和数据体都是二进制,并且统称为帧(frame):头信息帧和数据帧。
HTTP/2的数据包不是按顺序发送的,同一个连接里面连续的数据包,可能属于不同的回应。客户端还可以指定数据流的优先级。
HTTP/2的连接可以并发多个请求
(多路复用),而不用按照顺序一一对应。移除了HTTP/1.1中的串行请求,不需要排队等待,不会再出现「队头阻塞」问题。
比如:在一个TCP连接里,服务器收到了客户端A和B的两个请求,如果发现A处理过程非常耗时,于是就回应A请求已经处理好的部分,接着回应B请求,完成后,再回应A请求剩下的部分。
服务器推送,HTTP/2在一定程度上改善了传统的「请求-应答」工作模式,服务不再是被动地响应,也可以主动向客户端发送消息。
比如:在浏览器刚请求HTML的时候,就提前把可能用到的JS、CSS文件等静态资源主动发给客户端,减少延时的等待,也就是服务器推送(Server Push,也叫Cache Push)
HTTP/2 是基于 TCP 协议来传输数据的,TCP 是字节流协议,TCP 层必须保证收到的字节数据是完整且连续的,这样内核才会将缓冲区里的数据返回给 HTTP 应用,那么当「前 1 个字节数据」没有到达时,后收到的字节数据只能存放在内核缓冲区里,只有等到这 1 个字节数据到达时,HTTP/2 应用层才能从内核中拿到数据,这就是 HTTP/2 队头阻塞问题。