当前位置: 首页 > news >正文

【BUG】记一次context canceled的报错

文章目录

    • 案例分析
    • gorm源码解读
    • gin context 生命周期
      • context什么时候cancel的
      • 什么时候context会被动cancel掉呢?
    • 野生协程如何处理

案例分析

报错信息

{"L":"ERROR","T":"2024-12-17T11:11:33.005+0800","file":"*/log.go:61","message":"sql_trace","__type":"sql","trace_id":"6ab69b5d333de40c8327d8572336fa2c","error":"context canceled; invalid connection","elapsed":"2.292ms","rows":0,"sql":"UPDATE `logs` SET `response_time`=1734405092,`status`='success' WHERE id = 226081"
}

案发代码:

func Sync(c *gin.Context) {var params services.Params// 参数绑定c.ShouldBindBodyWith(&params, binding.JSON)// 参数效验// 记录日志...// 开协程 更新日志go func() {defer helpers.Recovery(c)models.Log{Ctx: c.Request.Context()}.UpdateLog(logId, res)}()c.JSON(200, response.Success(nil))return 
}func UpdateLog(id uint, r *services.ResJson) bool {exec := models.DefaultDB().WithContext(s.Ctx).Where("id  = ?", id).Model(&Log{}).Updates(map[string]interface{}{"status":        StatusSuccess,"response_time": time.Now().Unix(),})return exec.RowsAffected > 0
}

在更新数据库时,开了一个协程去更新

gorm源码解读

gorm Find、Update方法会触发GORM内部的处理器链,其中包括构建SQL语句、准备参数等。

最终,会调用到processor.Execute(db *DB)方法,这个方法会遍历并执行一系列注册的回调函数。

gorm.io/gorm@v1.25.11/finisher_api.go

// Update updates column with value using callbacks. Reference: https://gorm.io/docs/update.html#Update-Changed-Fields
func (db *DB) Update(column string, value interface{}) (tx *DB) {tx = db.getInstance()tx.Statement.Dest = map[string]interface{}{column: value}return tx.callbacks.Update().Execute(tx)
}// gorm.io/gorm@v1.25.11/callbacks.gofunc (p *processor) Execute(db *DB) *DB {...for _, f := range p.fns {f(db)}
}

// 注册回调函数
gorm@v1.25.11/callbacks/callbacks.go

func RegisterDefaultCallbacks(db *gorm.DB, config *Config) {enableTransaction := func(db *gorm.DB) bool {return !db.SkipDefaultTransaction}if len(config.CreateClauses) == 0 {config.CreateClauses = createClauses}if len(config.QueryClauses) == 0 {config.QueryClauses = queryClauses}if len(config.DeleteClauses) == 0 {config.DeleteClauses = deleteClauses}if len(config.UpdateClauses) == 0 {config.UpdateClauses = updateClauses}createCallback := db.Callback().Create()createCallback.Match(enableTransaction).Register("gorm:begin_transaction", BeginTransaction)createCallback.Register("gorm:before_create", BeforeCreate)createCallback.Register("gorm:save_before_associations", SaveBeforeAssociations(true))createCallback.Register("gorm:create", Create(config))createCallback.Register("gorm:save_after_associations", SaveAfterAssociations(true))createCallback.Register("gorm:after_create", AfterCreate)createCallback.Match(enableTransaction).Register("gorm:commit_or_rollback_transaction", CommitOrRollbackTransaction)createCallback.Clauses = config.CreateClausesqueryCallback := db.Callback().Query()queryCallback.Register("gorm:query", Query)queryCallback.Register("gorm:preload", Preload)queryCallback.Register("gorm:after_query", AfterQuery)queryCallback.Clauses = config.QueryClausesdeleteCallback := db.Callback().Delete()deleteCallback.Match(enableTransaction).Register("gorm:begin_transaction", BeginTransaction)deleteCallback.Register("gorm:before_delete", BeforeDelete)deleteCallback.Register("gorm:delete_before_associations", DeleteBeforeAssociations)deleteCallback.Register("gorm:delete", Delete(config))deleteCallback.Register("gorm:after_delete", AfterDelete)deleteCallback.Match(enableTransaction).Register("gorm:commit_or_rollback_transaction", CommitOrRollbackTransaction)deleteCallback.Clauses = config.DeleteClausesupdateCallback := db.Callback().Update()updateCallback.Match(enableTransaction).Register("gorm:begin_transaction", BeginTransaction)updateCallback.Register("gorm:setup_reflect_value", SetupUpdateReflectValue)updateCallback.Register("gorm:before_update", BeforeUpdate)updateCallback.Register("gorm:save_before_associations", SaveBeforeAssociations(false))updateCallback.Register("gorm:update", Update(config))updateCallback.Register("gorm:save_after_associations", SaveAfterAssociations(false))updateCallback.Register("gorm:after_update", AfterUpdate)....
}

gorm.io/gorm@v1.25.11/callbacks/update.go

// Update update hook
func Update(config *Config) func(db *gorm.DB) {supportReturning := utils.Contains(config.UpdateClauses, "RETURNING")return func(db *gorm.DB) {if db.Error != nil {return}if db.Statement.Schema != nil {for _, c := range db.Statement.Schema.UpdateClauses {db.Statement.AddClause(c)}}if db.Statement.SQL.Len() == 0 {db.Statement.SQL.Grow(180)db.Statement.AddClauseIfNotExists(clause.Update{})if _, ok := db.Statement.Clauses["SET"]; !ok {if set := ConvertToAssignments(db.Statement); len(set) != 0 {defer delete(db.Statement.Clauses, "SET")db.Statement.AddClause(set)} else {return}}db.Statement.Build(db.Statement.BuildClauses...)}checkMissingWhereConditions(db)if !db.DryRun && db.Error == nil {if ok, mode := hasReturning(db, supportReturning); ok {// Update函数最终会调用到底层数据库驱动的QueryContext方法,这个方法接受一个context.Context对象作为参数。if rows, err := db.Statement.ConnPool.QueryContext(db.Statement.Context, db.Statement.SQL.String(), db.Statement.Vars...); db.AddError(err) == nil {dest := db.Statement.Destdb.Statement.Dest = db.Statement.ReflectValue.Addr().Interface()gorm.Scan(rows, db, mode)db.Statement.Dest = destdb.AddError(rows.Close())}} else {result, err := db.Statement.ConnPool.ExecContext(db.Statement.Context, db.Statement.SQL.String(), db.Statement.Vars...)if db.AddError(err) == nil {db.RowsAffected, _ = result.RowsAffected()}}}}
}

调用数据库驱动:

Update函数最终会调用到底层数据库驱动的QueryContext方法,这个方法接受一个context.Context对象作为参数。

go1.22.3/src/database/sql/sql.go:1727

// QueryContext executes a query that returns rows, typically a SELECT.
// The args are for any placeholder parameters in the query.
func (db *DB) QueryContext(ctx context.Context, query string, args ...any) (*Rows, error) {var rows *Rowsvar err errorerr = db.retry(func(strategy connReuseStrategy) error {rows, err = db.query(ctx, query, args, strategy)return err})return rows, err
}

底层数据库连接:

QueryContext方法会进一步调用query方法,这个方法会处理数据库连接的重试逻辑。

在query方法中,会调用conn方法来获取一个数据库连接,并在这个连接上执行查询。

conn方法会处理context的取消和超时信号,如果context被取消或超时,它会中断数据库连接操作并返回错误。

go1.22.3/src/database/sql/sql.go:1748

func (db *DB) query(ctx context.Context, query string, args []any, strategy connReuseStrategy) (*Rows, error) {dc, err := db.conn(ctx, strategy)if err != nil {return nil, err}return db.queryDC(ctx, nil, dc, dc.releaseConn, query, args)
}// conn returns a newly-opened or cached *driverConn.
func (db *DB) conn(ctx context.Context, strategy connReuseStrategy) (*driverConn, error) {db.mu.Lock()if db.closed {db.mu.Unlock()return nil, errDBClosed}// Check if the context is expired.select {default:case <-ctx.Done():db.mu.Unlock()return nil, ctx.Err()}

那为什么会出现context canceled?

gin context 生命周期

在这里插入图片描述

大多数情况下,context一直能持续到请求结束
当请求发生错误的时候,context会立刻被cancel掉

context什么时候cancel的

server端接受新请求时会起一个协程go c.serve(connCtx)

func (srv *Server) Serve(l net.Listener) error {// ...for {rw, err := l.Accept()connCtx := ctx// ...go c.serve(connCtx)}
}

协程里面for循环从链接中读取请求,重点是这里每次读取到请求的时候都会启动后台协程(w.conn.r.startBackgroundRead())继续从链接中读取。

// Serve a new connection.
func (c *conn) serve(ctx context.Context) {// ...// HTTP/1.x from here on.ctx, cancelCtx := context.WithCancel(ctx)c.cancelCtx = cancelCtxdefer cancelCtx()// ...for {// 从链接中读取请求w, err := c.readRequest(ctx)if c.r.remain != c.server.initialReadLimitSize() {// If we read any bytes off the wire, we're active.c.setState(c.rwc, StateActive, runHooks)}// ....// 启动协程后台读取链接if requestBodyRemains(req.Body) {registerOnHitEOF(req.Body, w.conn.r.startBackgroundRead)} else {w.conn.r.startBackgroundRead()}// ...// 这里转到gin里面的serverHttp方法serverHandler{c.server}.ServeHTTP(w, w.req)// 请求结束之后cancel掉contextw.cancelCtx()// ...}
}

gin中执行ServeHttp方法

// ServeHTTP conforms to the http.Handler interface.
func (engine *Engine) ServeHTTP(w http.ResponseWriter, req *http.Request) {// ...// 执行我们写的handle方法engine.handleHTTPRequest(c)// ...
}

正常请求结束之后gin框架会主动cancel掉context, ctx会清空,回收到ctx pool中。

// github.com/gin-gonic/gin@v1.7.7/gin.go// ServeHTTP conforms to the http.Handler interface.
func (engine *Engine) ServeHTTP(w http.ResponseWriter, req *http.Request) {c := engine.pool.Get().(*Context)c.writermem.reset(w)c.Request = reqc.reset()engine.handleHTTPRequest(c)engine.pool.Put(c)
}// github.com/gin-gonic/gin@v1.7.7/context.go
func (c *Context) reset() {c.Writer = &c.writermemc.Params = c.Params[0:0]c.handlers = nilc.index = -1c.fullPath = ""c.Keys = nilc.Errors = c.Errors[0:0]c.Accepted = nilc.queryCache = nilc.formCache = nil*c.params = (*c.params)[:0]*c.skippedNodes = (*c.skippedNodes)[:0]
}

什么时候context会被动cancel掉呢?

秘密就在w.conn.r.startBackgroundRead()这个后台读取的协程里了。

func (cr *connReader) startBackgroundRead() {// ...go cr.backgroundRead()
}func (cr *connReader) backgroundRead() {n, err := cr.conn.rwc.Read(cr.byteBuf[:])// ...if ne, ok := err.(net.Error); ok && cr.aborted && ne.Timeout() {// Ignore this error. It's the expected error from// another goroutine calling abortPendingRead.} else if err != nil {cr.handleReadError(err)}// ...
}func (cr *connReader) handleReadError(_ error) {// 这里cancel了contextcr.conn.cancelCtx()cr.closeNotify()
}

startBackgroundRead -> backgroundRead -> handleReadError。在handleReadError函数里面会把context cancel掉。

当服务端在处理业务的同时,后台有个协程监控链接的状态,如果链接有问题就会把context cancel掉。(cancel的目的就是快速失败——业务不用处理了,就算服务端返回结果了,客户端也不处理了)

野生协程如何处理

  • http请求如有野生协程,不能使用request context(因为response之后context就会被cancel掉了),应当使用独立的context(比如context.Background()
  • 禁用野生协程,控制协程生命周期

相关文章:

【BUG】记一次context canceled的报错

文章目录 案例分析gorm源码解读gin context 生命周期context什么时候cancel的什么时候context会被动cancel掉呢&#xff1f; 野生协程如何处理 案例分析 报错信息 {"L":"ERROR","T":"2024-12-17T11:11:33.0050800","file"…...

JAVA前端开发中type=“danger“和 type=“text“的区别

在前端开发中&#xff0c;type 属性通常用于指定按钮或其他元素的样式或行为。不同的框架和库可能对 type 属性有不同的定义和用法。常见的框架包括 Bootstrap、Ant Design&#xff08;antd&#xff09;、Element Plus 等。下面我将分别介绍在这些框架中 type"danger"…...

sqlite3 支持位运算 和view和 triger

数据设置条件以后可以.根据门限自动调整其他的值 由数据库记录修改时间,及记录-> 网元设备的告警产生时间,设置超时清除时间,记录系统的原始时间戳 CPp 有 sqlite 支持 json 导出字符串,json 库将字符串,映射为结构体 triger update table 更新到一个 可设置参数列表 ,view …...

Mysql复习(一)

数据库系统的核心是&#xff08; 数据库管理系统 &#xff09;。 以下的标识符中符合标识符命名规则的有几个?&#xff08;3个&#xff09; 3abc7, abc73, bc73a, c73ab,*73abc 标识符的第一个字符允许包括哪些符号?&#xff08; _ 或者 或者 #&#xff09; 关系表达式运算的…...

Redis bitmaps 使用

应用场景&#xff1a; 记录id为 1 的用户&#xff0c;2024年12月签到情况&#xff0c;并统计&#xff1b; 记录 1号签到 zxys-redis:0>setbit 1:202412 1 1 记录 2号签到 zxys-redis:0>setbit 1:202412 2 1 记录 3号未签到 zxys-redis:0>setbit 1:202412 3 0 …...

计算无人机俯拍图像的地面采样距离(GSD)矩阵

引言 在无人机遥感、测绘和精细农业等领域&#xff0c;地面采样距离&#xff08;Ground Sampling Distance&#xff0c;简称 GSD&#xff09;是一个非常重要的指标。GSD 是指图像中每个像素在地面上实际代表的物理距离&#xff0c;通常以米或厘米为单位。GSD 决定了图像的空间…...

Java基础 | 数据库的命名规范

数据库的命名规范 1. 基本原则2. 命名规范详解2.1 命名禁止项2.2 命名规范3. 通用字段规范4. 特殊表命名建议 1. 基本原则 统一性&#xff1a;全库采用一致的命名规范简洁性&#xff1a;在表达清晰的前提下尽量简短规范性&#xff1a;遵循数据库标准规范可读性&#xff1a;命名…...

计算机网络基础(2):网络安全/ 网络通信介质

1. 网络安全威胁 网络安全&#xff1a;目的就是要让网络入侵者进不了网络系统&#xff0c;及时强行攻入网络&#xff0c;也拿不走信息&#xff0c;改不了数据&#xff0c;看不懂信息。 事发后能审查追踪到破坏者&#xff0c;让破坏者跑不掉。 网络威胁来自多方面&#xff1a…...

Reactor

文章目录 正确的理解发送double free问题 1.把我们的reactor进行拆分2.链接管理3.Reactor的理论 listensock只需要设置_recv_cb&#xff0c;而其他sock&#xff0c;读&#xff0c;写&#xff0c;异常 所以今天写nullptr其实就不太对&#xff0c;添加为空就没办法去响应事件 获…...

介绍 Html 和 Html 5 的关系与区别

HTML&#xff08;HyperText Markup Language&#xff09;是构建网页的标准标记语言&#xff0c;而 HTML5 是 HTML 的最新版本&#xff0c;包含了一些新的功能、元素、API 和属性。HTML5 相对于早期版本的 HTML&#xff08;比如 HTML4&#xff09;有许多重要的改进和变化。以下是…...

已有 containerd 的情况下部署二进制 docker 共存

文章目录 [toc]学习目的开始学习dockerd启动 containerd准备配置文件启动 containerd 启动 docker准备配置文件启动 docker 环境验证停止 docker 和 containerd 学习目的 使用容器的方式做一些部署的交付&#xff0c;相对方便很多&#xff0c;不需要担心别人的环境缺少需要的依…...

Springboot @Transactional使用时需注意的几个问题

一、事务的隔离级别 在Springboot应用中&#xff0c;如果我们想实现方法一旦执行有异常产生&#xff0c;就触发事务回滚&#xff0c;可以在方法上面添加Transactional注解。如果应用采用mysql数据库&#xff0c;虽然mysql本身也有事务隔离机制&#xff0c;但在Sping数据库的应…...

西游记战力排名、笔记等

文章目录 战力排名对西游记的理解各个版本游戏题材西游记关卡和妖怪 西游记家喻户晓&#xff0c;没有谁不知道吧&#xff0c;无论是电视剧、影视&#xff0c;还是小说&#xff0c;乃至游戏&#xff0c;很多地方都有西游记的身影。 虽然知道&#xff0c;但总不如对三国啊、水浒啊…...

(2024.12)Ubuntu20.04安装ZED-SDK

一.官网地址 ZED SDK 4.2 - Download | Stereolabs 选择适配版本进行下载 二.安装程序 下载完成后&#xff0c;进入文件目录&#xff0c;打开终端&#xff0c;输入&#xff1a; chmod x ZED_SDK_Ubuntu20_cuda11.8_v4.2.2.zstd.run ./ZED_SDK_Ubuntu20_cuda11.8_v4.2.2.zst…...

Pytorch | 从零构建GoogleNet对CIFAR10进行分类

Pytorch | 从零构建GoogleNet对CIFAR10进行分类 CIFAR10数据集GoogleNet网络结构特点网络整体架构应用与影响Inceptionv1到Inceptionv2 GoogleNet结构代码详解结构代码代码详解Inception 类初始化方法前向传播 forward GoogleNet 类初始化方法前向传播 forward 训练过程和测试结…...

蓝桥杯刷题——day9

蓝桥杯刷题——day9 题目一题干解题思路一代码解题思路二代码 题目二题干解题思路代码 题目一 题干 小蓝最近在研究一种浮点数的表示方法&#xff1a;R格式。对于一个大于0的浮点数d&#xff0c;可以用R格式的整数来表示。给定一个转换参数n&#xff0c;将浮点数转换为R格式整…...

ffmpeg翻页转场动效的安装及使用

文章目录 前言一、背景二、选型分析2.1 ffmpeg自带的xfade滤镜2.2 ffmpeg使用GL Transition库2.3 xfade-easing项目三、安装3.1、安装依赖([参考](https://trac.ffmpeg.org/wiki/CompilationGuide/macOS#InstallingdependencieswithHomebrew))3.2、获取ffmpeg源码3.3、融合xf…...

分布式刚度编织,让可穿戴触觉更出色 ——Haptiknit

大家好&#xff01;今天来了解一项非常有趣的科技成果 ——“Haptiknit&#xff1a;用于可穿戴触觉的分布式刚度编织”——《Haptiknit: Distributed stiffness knitting for wearable haptics》发表于《SCIENCE ROBOTICS》。在现代科技发展中&#xff0c;可穿戴触觉设备越来越…...

Elasticsearch:什么是查询语言?

查询语言定义 查询语言包括数据库查询语言 (database query language - DQL)&#xff0c;是一种用于查询和从数据库检索信息的专用计算机语言。它充当用户和数据库之间的接口&#xff0c;使用户能够管理来自数据库管理系统 (database management system - DBMS) 的数据。 最广…...

PyQt介绍

**PyQt 和 PySide (Qt for Python) 简介** **PyQt** 和 **PySide** 是 Python 中用于开发图形用户界面 (GUI) 应用程序的两个主要框架&#xff0c;它们都是基于 Qt 库的绑定。Qt 是一个跨平台的应用程序开发框架&#xff0c;广泛用于创建图形用户界面、应用程序开发以及嵌入式…...

Oracle 数据库函数的用法(一)

Oracle数据库提供了大量的内置函数&#xff0c;可以用于完成各种操作&#xff0c;如字符串操作&#xff0c;数学计算&#xff0c;日期时间处理&#xff0c;条件判断&#xff0c;序列生成&#xff0c;聚合统计等。以下是一些常用的Oracle数据库函数&#xff1a; 一、oracle 使用…...

labelme标签批量转换数据集json_to_dataset

文章目录 labelme标签批量转换数据集json_to_dataset转换原理单张图片转换多张图片批量转换bat脚本循环法 标注图片提取标注图片转单通道 labelme标签批量转换数据集json_to_dataset 转自labelme批量制作数据集教程。 转换原理 在安装了labelme的虚拟环境中有一个labelme_js…...

《QT 5.14.1 搭建 opencv 环境全攻略》

《QT 5.14.1 搭建 opencv 环境全攻略》 一、引言二、准备工作&#xff08;一&#xff09;软件下载&#xff08;二&#xff09;系统环境确认 三、安装 QT 5.14.1&#xff08;一&#xff09;安装包下载与运行&#xff08;二&#xff09;环境变量配置 四、OpenCV 安装与配置&#…...

Sentry日志管理thinkphp8 tp8 sentry9 sentry8 php8.x配置步骤, tp8自定义异常处理类使用方法

tp8的默认使用的就是composer来管理第三方包, 所以直接使用 composer 来安装 sentry9 即可. 同时tp8和tp5的配置方式不太一样, 这里我们直接使用自定义异常类来处理Sentry的异常. 1. 安装 sentry9 包 # 安装 sentry9 包 composer require "tekintian/sentry9-php" …...

MySQL 基础:开启数据库之旅

MySQL 基础&#xff1a;开启数据库之旅 在当今数字化的时代&#xff0c;数据扮演着至关重要的角色&#xff0c;而数据库管理系统则是存储、管理和操作这些数据的强大工具。MySQL 作为一款广受欢迎的开源关系型数据库管理系统&#xff0c;被广泛应用于各类网站、应用程序以及企业…...

OpenTK 中帧缓存的深度解析与应用实践

摘要: 本文深入探讨了 OpenTK 中帧缓存的使用。首先介绍了帧缓存的基本概念与在图形渲染管线中的关键地位,包括其与颜色缓存、深度缓存、模板缓存等各类缓存的关联。接着详细阐述了帧缓存对象(FBO)的创建、绑定与解绑等操作,深入分析了纹理附件、渲染缓冲区附件在 FBO 中的…...

stm32制作CAN适配器5--WinUsb上位机编写

上次我们要stm32制作了一个基于winusb有canfd适配器&#xff0c;今天我们来制作一个上位机程序来进行报文收发。 上位机还是用以前写好的&#xff0c;只是更改下dll文件。 项目链接器&#xff0c;输入&#xff0c;附加依赖项中增加winusb.lib winusb初始化&#xff1a;#incl…...

【时间之外】IT人求职和创业应知【71】-专利费

目录 2025 ICT产业趋势年会召开&#xff0c;2024年度ICT十大新闻重磅揭晓 海纳致远数字科技申请定制化插件驱动的数据分析专利 阿波罗智联取得语音数据的处理方法、装置、设备和存储介质专利 心勿贪&#xff0c;贵知足。 感谢所有打开这个页面的朋友。人生不如意&#xff0…...

springboot vue 会员营销系统

springboot vue 会员营销系统介绍 演示地址&#xff1a; 开源版本&#xff1a;http://8.146.211.120:8083/ 完整版本&#xff1a;http://8.146.211.120:8086/ 移动端 http://8.146.211.120:8087/ 简介 欢迎使用springboot vue会员营销系统。本项目包含会员储值卡、套餐卡、计…...

Kafka快速扫描

Architecture 系统间解耦&#xff0c;异步通信&#xff0c;削峰填谷 Topic 消息主题&#xff0c;用于存储消息 Partition 分区&#xff0c;通过扩大分区&#xff0c;可以提高存储量 Broker 部署Kafka服务的设备 Leader kafka主分区 Follwer kafka从分区 高性能之道&#xff1a…...

scala基础学习(数据类型)-字符串

文章目录 scala中的字符串引号单引号双引号三引号 常用内置函数length 获取字符串长度charAt 字符串元素访问substring 获取字串indexOf 获取字串位置replace 字符串替换toLowerCase,toUpperCase 字符串大小写转换trim 去除首位空白符split 字符串切割以及查看startsWith,endsW…...

网络架构与IP技术:4K/IP演播室制作的关键支撑

随着科技的不断发展&#xff0c;广播电视行业也在不断迭代更新&#xff0c;其中4K/IP演播室技术的应用成了一个引人注目的焦点。4K超高清技术和IP网络技术的结合&#xff0c;不仅提升了节目制作的画质和效果&#xff0c;还为节目制作带来了更高的效率和灵活性。那么4K超高清技术…...

如何优雅的关闭GoWeb服务器

以下内容均为Let’s Go Further内容节选以及作者本人理解。 这里创建了一个后台进程用于捕获关闭信号&#xff0c;在后台进程中&#xff0c;主要内容为&#xff1a; 创建一个缓冲通道 quit使用signal.Notify函数监听并捕获关机信号SIGINT,SIGTERM&#xff0c;在捕获关机信号后…...

Python爬虫(5) --爬取网页视频

文章目录 爬虫爬取视频指定url发送请求UA伪装请求页面 获取想要的数据解析定位定位音视频位置 存放视频完整代码实现总结 爬虫 Python 爬虫是一种自动化工具&#xff0c;用于从互联网上抓取网页数据并提取有用的信息。Python 因其简洁的语法和丰富的库支持&#xff08;如 requ…...

simulink离散传递函数得到差分方程并用C语言实现

一. 创建连续时间的传递函数 G ( s ) s 2 217 s s 2 384 s 8989 G(s) \frac{s^2217s}{s^2384s8989} G(s)s2384s8989s2217s​ 二. 离散连续时间的传递函数G(s) 2.1 在matlab中用c2d函数双线性变换法离散G(s)&#xff0c; 下面是matlab脚本代码 % 创建连续时间传递函数 …...

第十七届山东省职业院校技能大赛 中职组“网络安全”赛项任务书正式赛题

第十七届山东省职业院校技能大赛 中职组“网络安全”赛项任务书-A 目录 一、竞赛阶段 二、竞赛任务书内容 &#xff08;一&#xff09;拓扑图 &#xff08;二&#xff09;模块A 基础设施设置与安全加固(200分) &#xff08;三&#xff09;B模块安全事件响应/网络安全数据取证/…...

Redis内存碎片详解

什么是内存碎片? 你可以将内存碎片简单地理解为那些不可用的空闲内存。 举个例子&#xff1a;操作系统为你分配了 32 字节的连续内存空间&#xff0c;而你存储数据实际只需要使用 24 字节内存空间&#xff0c;那这多余出来的 8 字节内存空间如果后续没办法再被分配存储其他数…...

Python球球大作战

系列文章 序号直达链接表白系列1Python制作一个无法拒绝的表白界面2Python满屏飘字表白代码3Python无限弹窗满屏表白代码4Python李峋同款可写字版跳动的爱心5Python流星雨代码6Python漂浮爱心代码7Python爱心光波代码8Python普通的玫瑰花代码9Python炫酷的玫瑰花代码10Python多…...

机器学习(Machine Learning)的安全问题

最近看论文&#xff0c;看到了”对抗样本“的一些内容&#xff0c;然后又研究了一下其背后的东西&#xff0c;发现还有”机器学习的安全“这一问题&#xff0c;然后找了几篇博客看了一下&#xff0c;发现了篇2019年的比较有意思的文章&#xff0c;这里整理一下&#xff0c;方编…...

ROS1安装教程

一、环境准备 操作系统&#xff1a;Ubuntu 20.04 LTS 注&#xff1a;为保证系统干净&#xff0c;本文使用Docker进行 演示&#xff0c;如已安装相应的Ubuntu系统请忽略。 Docker安装Ubuntu系统步骤如下&#xff1a; # 拉取镜像 docker pull ubuntu:20.04# 创建容器 docker ru…...

大腾智能CAD:国产云原生三维设计新选择

在快速发展的工业设计领域&#xff0c;CAD软件已成为不可或缺的核心工具。它通过强大的建模、分析、优化等功能&#xff0c;不仅显著提升了设计效率与精度&#xff0c;还促进了设计思维的创新与拓展&#xff0c;为产品从概念构想到实体制造的全过程提供了强有力的技术支持。然而…...

Docker 入门:如何使用 Docker 容器化 AI 项目(一)

引言 在人工智能&#xff08;AI&#xff09;项目的开发和部署过程中&#xff0c;环境配置和依赖管理往往是开发者遇到的挑战之一。开发者通常需要在不同的机器上运行同样的代码&#xff0c;确保每个人使用的环境一致&#xff0c;才能避免 “在我的机器上可以运行”的尴尬问题。…...

【04-数据库面试】

如何创建一个新的数据库 数据库是现代信息技术中不可或缺的一部分&#xff0c;它为存储、检索和管理数据提供了强大的工具。无论是企业还是个人&#xff0c;都可能需要创建自己的数据库以满足特定的需求。本文将详细介绍创建一个新数据库的步骤&#xff0c;包括规划、选择数据…...

单元测试使用记录

什么是单元测试 简单来说就是对一个类中的方法进行测试&#xff0c;对输出的结果检查判断是否符合预期结果 但是在多年的工作中&#xff0c;从来没有哪个项目中真正系统的用到了单元测试&#xff0c;因此对它还是很陌生的&#xff0c;也就造成更加不会在项目中区使用它。 如何…...

《深入浅出 Servlet:Java Web 开发的基石》(二)

ServletConfig(熟练) ServletConfig对象对应web.xml文件中的<servlet>元素。例如你想获取当前Servlet在web.xml文件中的配置名&#xff0c;那么可以使用servletConfig.getServletName()方法获取&#xff01; 你不能自己去创建ServletConfig对象&#xff0c;Servlet的in…...

Pytorch | 从零构建MobileNet对CIFAR10进行分类

Pytorch | 从零构建MobileNet对CIFAR10进行分类 CIFAR10数据集MobileNet设计理念网络结构技术优势应用领域 MobileNet结构代码详解结构代码代码详解DepthwiseSeparableConv 类初始化方法前向传播 forward 方法 MobileNet 类初始化方法前向传播 forward 方法 训练过程和测试结果…...

冯诺依曼架构与哈佛架构的对比与应用

冯诺依曼架构&#xff08;Von Neumann Architecture&#xff09;&#xff0c;也称为 冯诺依曼模型&#xff0c;是由著名数学家和计算机科学家约翰冯诺依曼&#xff08;John von Neumann&#xff09;在1945年提出的。冯诺依曼架构为现代计算机奠定了基础&#xff0c;几乎所有现代…...

【Java基础面试题032】Java中的字节码是什么?

回答重点 Java字节码是Java编译器将Java源代码编译后生成的 位于Java源代码与JVM执行的执行的机器码之间。 Java字节码由JVM解释或即时编译&#xff08;JIT&#xff09;为机器码执行 扩展知识 Java字节码的关键点 1&#xff09;字节码结构&#xff1a; Java字节码是与平…...

K8s ConfigMap的基础功能介绍

在 Kubernetes 中&#xff0c;ConfigMap 是一种用于管理配置信息的资源对象&#xff0c;它允许你将 配置信息与代码解耦&#xff0c;方便管理和更新应用配置&#xff0c;而无需重新构建镜像或重启服务。 ConfigMap 的功能 存储配置信息&#xff1a; 可以以 键值对 的形式存储配…...

stm32制作CAN适配器4--WinUsb的使用

前面使用STM32G474芯片的USB模块做了一个CANFD程序&#xff0c;当时用的是HID模式&#xff0c;在实际使用时发现HID模块的通讯速率太慢了&#xff0c;只能1ms传输一帧&#xff0c;就会造成有些掉帧现象。 现在就把HID模块改为在Window下同样免驱的WinUsb来实现CANFD数据的传输。…...