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

【AI图像生成网站Golang】项目测试与优化

AI图像生成网站

目录

一、项目介绍

二、雪花算法

三、JWT认证与令牌桶算法

四、项目架构

五、图床上传与图像生成API搭建

六、项目测试与优化


六、项目测试与优化

在开发过程中,性能优化是保证项目可扩展性和用户体验的关键步骤。本文将详细介绍我如何使用一些主流的性能评估工具进行项目性能检测,并在此基础上进行优化。

1. 性能评估工具

我使用的性能检测工具如下:

  • k6: 用于负载测试的开源工具,可以通过编写简单的javascript测试脚本,模拟高并发场景下的用户行为。
  • k6 cloud: 是k6的云服务扩展,能够提供比本地运行更详细的性能监控和分析报告。
  • pprof: 用于捕获CPU、内存等的使用情况进行采样分析,帮助定位性能瓶颈
  • trace: 可以通过可视化的时间线查看goroutine的执行和调度情况。

在后文中,我们会使用k6运行测试文件,并根据k6 cloud上通过的请求数和RPS(Requests Per Second,每秒请求数)来简单评估性能,之后会使用pprof和trace工具查找性能瓶颈和突破口。

2. 性能评估与分析

测试流程

在进行负载测试之前,我首先进行了单用户的性能测试,用于了解每个请求的处理时长,确保基本功能的正常工作。之后,我模拟了并发场景,逐渐增加并发量测试系统的表现。

使用 k6 进行负载测试

单用户测试: 在单用户场景下,我编写了一个的k6脚本,模拟了一个用户从注册到上传作品的一套API调用流程。

import http from 'k6/http';
import { sleep, check } from 'k6';
import {generateImage, generateRandomPrompt, generateUniqueUsername,generateUniqueEmail} from "./dynamic_data.js";// 配置接口的基本 URL
const BASE_URL = 'http://localhost:8080/api/v1';// 读取 Base64 数据
const base64Image = open("image_base64.txt");// 定义一个变量来跟踪是否正在刷新 token
let refreshing = false;// k6 入口函数
export default function () {// 用户注册信息const USER_CREDENTIALS = {avatar: `data:image/png;base64,${generateImage(base64Image)}`,username: generateUniqueUsername(),password: 'password123',confirm_password: 'password123',email: generateUniqueEmail(),};// 1. 用户注册const res = http.post(`${BASE_URL}/signup`, JSON.stringify(USER_CREDENTIALS), {headers: { 'Content-Type': 'application/json' },});check(res, { 'signup succeeded': (r) => r.status === 200 });// 2. 用户登录const loginRes = http.post(`${BASE_URL}/login`, JSON.stringify(USER_CREDENTIALS), {headers: { 'Content-Type': 'application/json' },});check(loginRes, {'Login succeeded': (r) => r.status === 200,});const accessToken = loginRes.json('data.access_token');const refreshTokenValue = loginRes.json('data.refresh_token');if (!accessToken || !refreshTokenValue) {throw new Error('Login failed, tokens not received');}// 3. 创建分组const genCategory = {cover: `data:image/png;base64,${generateImage(base64Image)}`,category_name: `category_${Math.random().toString(36).substring(2, 15)}`,description: generateRandomPrompt(),};const createGroupRes = apiRequest('POST', `${BASE_URL}/createCategory`, genCategory, accessToken);check(createGroupRes, { 'Create group succeeded': (r) => r.status === 200 });// 4. 浏览分组const groupRes = apiRequest('GET', `${BASE_URL}/category`, null, accessToken);check(groupRes, { 'Browse groups succeeded': (r) => r.status === 200 });const groups = groupRes.json('data');const groupId = groups[0].category_id;// 5. 浏览作品const worksRes = apiRequest('GET', `${BASE_URL}/categoryDetail/${groupId}`, null, accessToken);check(worksRes, { 'Browse works succeeded': (r) => r.status === 200 });// 6. 提交图像处理任务const imageTaskPayload = {ori_image: `data:image/png;base64,${generateImage(base64Image)}`,category_id: groupId,prompt: generateRandomPrompt(),};const processRes = apiRequest('POST', `${BASE_URL}/processImage`, imageTaskPayload, accessToken);check(processRes, { 'Process task submitted': (r) => r.status === 200 });// 7. 上传作品const newWork = {work_image: `data:image/png;base64,${generateImage(base64Image)}`,// work_image: `data:image/png;base64,${genImage}`,category_id: groupId,prompt: generateRandomPrompt(),};const uploadRes = apiRequest('POST', `${BASE_URL}/uploadWork`, newWork, accessToken);check(uploadRes, { 'Upload work succeeded': (r) => r.status === 200 });
}// 刷新 Token 的逻辑
function refreshToken(refreshToken) {const refreshRes = http.post(`${BASE_URL}/refresh_token`, JSON.stringify({ refresh_token: refreshToken }), {headers: { 'Content-Type': 'application/json' },});check(refreshRes, {'Token refreshed': (r) => r.status === 200,});const newToken = refreshRes.json('access_token');if (!newToken) {throw new Error('Failed to refresh token');}return newToken;
}// API 请求方法
function apiRequest(method, url, body, token) {const headers = {'Content-Type': 'application/json',Authorization: `Bearer ${token}`,};let res;if (method === 'GET') {res = http.get(url, { headers });} else if (method === 'POST') {res = http.post(url, JSON.stringify(body), { headers });}// 如果遇到 401 错误,且没有正在刷新 tokenif (res.status === 401 && !refreshing) {console.log('Access token expired, refreshing...');// 设置 refreshing 为 true,避免并发请求时重复刷新refreshing = true;// 刷新 tokenconst newToken = refreshToken(refreshTokenValue);// 刷新完成后,重新发送请求res = apiRequest(method, url, body, newToken);// 刷新完成,重置 refreshing 状态refreshing = false;}return res;
}

测试结果(单用户场景):

点击图中链接即可进入 k6 cloud 界面查看更详细的数据,可以看到单例用户的运行时长为8.3s。

在这里插入图片描述在这里插入图片描述
进入可视化界面可以看到,单例用户的总请求为7个,平均响应时间为 4372 ms,失败率为 0% ,每秒请求数(RPS)在 1~2 之间。
在这里插入图片描述在这里插入图片描述
在单用户场景下,系统表现良好,响应时间低,且无错误发生。接下来,我开始使用并发用户场景进行测试,模拟“高负载”下的表现(展示实验用的电脑配置低,不能模拟真正的高并发,在此仅做示例
^_^")。

并发测试

在使用之前编写的Python API代码进行并发测试时,出现了报错: Model inference error: index 11 is out of bounds for dimension 0 with size 11 ,这时将 Python API 中这一段的 num_inference_steps=10 改小一些即可。

具体原因不在这里占用篇幅,请移步这里查看:解决并发情况下调用 Instruct-pix2pix 模型推理错误

images = pipe(prompt=request.prompt, image=image, num_inference_steps=5, image_guidance_scale=1).images

在之前的代码中加入以下部分即可进行并发测试。这里我使用了 k6 的 constant-arrival-rate 执行器模式来控制请求的速率和并发用户数。

constant-arrival-rate 配置下,k6 会持续不断地以固定速率发送请求,在本测试环境下,rate: 5 意味着 k6 会保持每秒发送 5 个请求,直到测试结束。这种配置适合模拟某些稳定的请求负载。

export const options = {scenarios: {my_test: {executor: 'constant-arrival-rate',rate: 5, // 每秒发送 5 个请求duration: '5m', // 持续 5 分钟preAllocatedVUs: 5, // 提前分配的虚拟用户数maxVUs: 10, // 最大虚拟用户数},},
};

当然,除了 constant-arrival-rate 之外,k6 还提供了其他几种执行器模式,适用于不同的负载场景,比如:

  • virtual-users (VUs):

这是最常见的执行器模式,适用于模拟一群用户的行为,可以模拟不同用户的交替请求。

export const options = {stages: [{ duration: '10s', target: 10 }, // 10 秒内增加到 10 个虚拟用户{ duration: '1m', target: 10 },  // 保持 10 个虚拟用户 1 分钟{ duration: '10s', target: 0 },  // 10 秒内减少到 0],
};
  • ramping-arrival-rate

这种模式用于模拟请求逐步增加的情况,可以通过配置startRate(起始速率)、endRate(结束速率)和 duration(持续时间)来设置请求的增长速率。

export const options = {scenarios: {my_test: {executor: 'ramping-arrival-rate',startRate: 10, // 初始请求速率每秒 10 个请求endRate: 50, // 最终请求速率每秒 50 个请求duration: '2m', // 持续 2 分钟},},
};
  • shared-iterations

在这种模式下,所有虚拟用户共同执行相同数量的请求,直到所有请求完成。

export const options = {scenarios: {my_test: {executor: 'shared-iterations',iterations: 100, // 共有 100 次请求vus: 10, // 使用 10 个虚拟用户},},
};
  • per-vu-iterations

这种模式下,每个虚拟用户会执行一定次数的操作。

export const options = {scenarios: {my_test: {executor: 'per-vu-iterations',vus: 10, // 使用 10 个虚拟用户iterations: 100, // 每个虚拟用户执行 100 次操作},},
};

并发测试完成后,进入 k6 cloud 界面查看测试数据。

在这里插入图片描述
可以看出,虽然我使用了 constant-arrival-rate 配置,但是图中的请求数量和响应数量很不稳定。

并且可以观察到,随着并发量的增加,一些需要调用API的接口响应时间明显上升,尤其是 p95p99

初步判断是 API 调用部分出现了阻塞。

在这里插入图片描述
pprof 分析

使用 pprof 跟踪代码的 CPU 占用率发现,耗时最长的是 net.(*Resolver) lookupIP ,占用了 56.46% 的 CPU 时间。该函数负责 DNS 查询,用于将域名解析为IP地址,解析流程通常包括:

  • 本地缓存查询
  • 向 DNS 服务器发送请求
  • 等待服务器返回解析结果

在项目中,如果短时间内发起大量外部请求,且每次请求都需要进行完整的 DNS 查询流程,将会导致 DNS 查询成为性能瓶颈。

此外,SetupRouter 中的日志记录(19.24%)和身份验证(12.48%)中间件是系统的次要瓶颈。

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

3. 优化方案

在 Go 中,默认 HTTP 客户端会在每次请求时触发新的 DNS 查询,如果复用 htttp.Client,则可以有效减少 DNS 查询次数。

同时,将外部 API 调用解耦到 Goroutine 中异步执行,可以让主线程快速处理其他任务,如日志写入等。

我们还需要引入 redis 来缓存一些会重复查询的信息,如已经验证过的用户信息等。

4. 优化实践

4.1 引入 Goroutine 解耦外部 API 调用

之前,外部 API 调用在主线程中直接执行,导致主线程需要等待外部服务返回结果。我们通过以下方式进行优化:

(1)图像上传与处理的异步化:

  • 将图像上传和处理 API 任务拆分为两个 Goroutine。
  • 使用 Redis 和 RabbitMQ 实现消息队列,将任务放入队列中,由独立的消费者处理,避免主线程阻塞。
  • 使用 sync.WaitGroupchannel 进行任务同步与通信。
var wg sync.WaitGroupwg.Add(3) // 我们要等待两个消费者 goroutinego func() {defer wg.Done()controller.ConsumeUploadTasks("upload_image")}()go func() {defer wg.Done()controller.ConsumeProcessTasks("process_image")}()

(2)HTTP 客户端复用:

  • 创建一个全局的 http.Client,启用连接池复用。
var ossClient *oss.Clientfunc init() {// 确保配置已经加载if err := settings.Init(); err != nil {log.Fatalf("failed to load settings: %v", err)}// 初始化 OSS 客户端配置cfg := oss.LoadDefaultConfig().WithRegion(settings.Conf.Region).WithCredentialsProvider(credentials.NewStaticCredentialsProvider(settings.Conf.AccessKeyID, settings.Conf.AccessKeySecret, ""))// 创建全局 OSS 客户端实例ossClient = oss.NewClient(cfg)
}// UploadImageToOSS 上传图片的函数
func UploadImageToOSS(base64Image string) (string, error) {if strings.HasPrefix(base64Image, "data:image") {base64Image = strings.Split(base64Image, ",")[1]}// 解码 Base64 数据imageData, err := base64.StdEncoding.DecodeString(base64Image)if err != nil {return "", fmt.Errorf("failed to decode base64 data: %v", err)}// 生成文件名objectName := GenerateUniqueFileName("png")// 创建上传对象的请求request := &oss.PutObjectRequest{Bucket: oss.Ptr(settings.Conf.Bucket), // 存储空间名称Key:    oss.Ptr(objectName),           // 对象名称Body:   bytes.NewReader(imageData),    // 图片数据}// 上传文件_, err = ossClient.PutObject(context.TODO(), request)if err != nil {return "", fmt.Errorf("failed to upload image to OSS: %v", err)}// 生成文件的 URLurl := fmt.Sprintf("%s/%s", settings.Conf.Endpoint, objectName)return url, nil
}

4.2 身份验证优化

对于身份验证逻辑,我引入了 Redis 缓存来避免频繁查询数据库。

// CacheUserInfo 缓存用户信息
func CacheUserInfo(userInfo map[string]interface{}) error {key := fmt.Sprintf("user_info:%s", userInfo["user_id"])err := client.HMSet(ctx, key, userInfo).Err()if err != nil {return fmt.Errorf("failed to HMSet: %w", err)}err = client.Expire(ctx, key, time.Duration(settings.Conf.RedisConfig.DefaultTTL)).Err()if err != nil {return fmt.Errorf("failed to set expire: %w", err)}// 如果都成功,返回 nilreturn nil}// GetCachedUserInfo 获取缓存的用户信息
func GetCachedUserInfo(userID string) (map[string]string, error) {key := fmt.Sprintf("user_info:%s", userID)return client.HGetAll(ctx, key).Result()
}

4.3 效果测试

在对项目进行优化后,通过 k6 cloud 工具对性能进行对比测试发现,系统的并发能力提升了近 7 倍,总请求数较之前增长了 2.3 倍,系统处理请求的效率得到了显著提升。

项目优化前优化后
总请求数5981.4K
请求速率峰值(reqs/s)6.3344.33
95% 的响应时间(ms)321323.3

在 k6 可视化界面,可以看到在测试初期,请求速率(RPS)和响应时间会快速上升到一个较高的峰值。这说明系统能够快速响应并处理高并发请求。

峰值过后,请求速率和响应时间会迅速下降到一个较低的数值,并且请求速率始终保持一定的小幅波动。这是因为在高并发情况下,CPU 和内存资源的分配会随着请求数量的波动而调整,导致 RPS 的小幅变化。

在这里插入图片描述
在优化前,系统中耗时最多的四个请求占用大量时间,优化后有了显著的降低。

在这里插入图片描述

DNS 查询的 CPU 占用率从 56.46% 降低到 21.16% 。

主线程负载显著减轻,高耗时任务被转移到 Goroutine 中异步处理。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在 trace 可视化界面中,能看到Goroutines 使用数量平稳,分布较为均匀,未出现 Goroutine 阻塞的尖峰现象。同时运行的 Goroutines 数量略高,但在合理范围内。

Heap 的内存分配曲线波动较大,但回收相对及时,未出现内存泄漏或超量分配的现象。GC 活跃,Heap 内存峰值控制在可接受范围。

Threads 数量略高,可能与 HTTP 客户端连接池、Redis 以及 RabbitMQ 的 I/O 操作相关。

GC 曲线与 Heap 使用曲线基本同步,垃圾回收频繁但时间较短。未来会考虑进一步优化数据结构设计,避免频繁分配临时对象。

网络 I/O 分布均匀,RabbitMQ 和 Redis 的使用改善了对数据库的直接依赖。外部 API 调用已异步化,但响应时间稍长。

在这里插入图片描述
对各个 Proc,PU 核心的使用较为均匀,任务分配合理。Goroutine 与 Proc 的调度平衡较好,未观察到 Proc 长时间空闲。

在未来的工作中,将会考虑尝试将 RabbitMQ 的消费者分布式部署,以进一步增加并发量。

相关文章:

【AI图像生成网站Golang】项目测试与优化

AI图像生成网站 目录 一、项目介绍 二、雪花算法 三、JWT认证与令牌桶算法 四、项目架构 五、图床上传与图像生成API搭建 六、项目测试与优化 六、项目测试与优化 在开发过程中,性能优化是保证项目可扩展性和用户体验的关键步骤。本文将详细介绍我如何使用一…...

使用Docker启用MySQL8.0.11

目录 一、Docker减小镜像大小的方式 1、基础镜像选择 2、减少镜像层数 3、清理无用文件和缓存 4、优化文件复制(COPY和ADD指令) 二、Docker镜像多阶段构建 1、什么是dockers镜像多阶段构建 1.1 概念介绍 1.2 构建过程和优势 2、怎样在Dockerfil…...

部署Mysql、镜像和容器、常见命令

目录 部署Mysql 镜像和容器 常见命令 部署Mysql 可以有多个容器 docker run -d \--name mysql \-p 3306:3306 \-e TZAsia/Shanghai \-e MYSQL_ROOT_PASSWORD123 \mysql docker run -d \--name mysql2 \-p 3307:3307 \-e TZAsia/Shanghai \-e MYSQL_ROOT_PASSWORD123 \mys…...

Windows部署Docker及PostgreSQL数据库相关操作

一、Windows安装Docker 1.wsl安装 以管理员身份启动命令行,运行:wsl --install; 安装结束后,重启电脑,以管理员身份启动命令行,运行:wsl --install -d Ubuntu; 中间需要输入用户名…...

Halcon例程代码解读:安全环检测(附源码|图像下载链接)

安全环检测核心思路与代码详解 项目目标 本项目的目标是检测图像中的安全环位置和方向。通过形状匹配技术,从一张模型图像中提取安全环的特征,并在后续图像中识别多个实例,完成检测和方向标定。 实现思路 安全环检测分为以下核心步骤&…...

Unity3D用正则判断身份证号或邮箱

系列文章目录 unity工具 文章目录 系列文章目录👉前言👉一、正则判断邮箱格式👉二、正则判断身份证号👉壁纸分享👉总结👉前言 C#正则表达式(Regex)是一种用来匹配字符串模式的强大工具。在C#中,可以使用System.Text.RegularExpressions命名空间下的Regex类来处…...

PostgreSQL表达式的类型

PostgreSQL表达式是数据库查询中非常重要的组成部分,它们由一个或多个值、运算符和PostgreSQL函数组合而成,用于计算出一个单一的结果。这些表达式类似于公式,可以用查询语言编写,并用于查询数据库中的特定数据集。 PostgreSQL表…...

C++简明教程(文章要求学过一点C语言)(10)

类的教程 C 类的完整教程 C 中,类(class)是面向对象编程的核心概念,用于定义对象的属性(数据成员)和行为(成员函数)。本教程将带你从零开始,循序渐进地学习如何定义和使…...

从腾讯云的恶意文件查杀学习下PHP的eval函数

问题来自于腾讯云的主机安全通知&#xff1a; &#x1f680;一键接入&#xff0c;畅享GPT及AI大模型服务&#xff01;【顶级API中转品牌】&#xff1a; https://api.ablai.top/ 病毒文件副本内容如下&#xff1a; <?php function x($x){eval($x);}x(str_rot13(riny($_CBF…...

OpenWRT——官方镜像安装Docker(网络环境需设置)并配置Sun-Panel

Pro更多功能预览地址https://pro.sun-panel.top/#/hpage/pro Github地址https://github.com/hslr-s/sun-panel?tabreadme-ov-file 首先确认宿主机网络环境符合要求 curl Google.com1.确认没问题后开始安装Docker opkg update opkg install dockerd docker luci-app-docker…...

MySQL 中的常见错误与排查

在 MySQL 数据库的日常运维中&#xff0c;管理员可能会遇到各种错误。无论是查询性能问题、连接异常、数据一致性问题&#xff0c;还是磁盘空间不足等&#xff0c;及时排查并解决这些问题是保证数据库稳定运行的关键。本文将列出 MySQL 中一些常见的错误及其排查方法。 一、连接…...

workman服务端开发模式-应用开发-gateway长链接端工作原理

一、长链接的工作原理 Register类其实也是基于基础的Worker开发的。Gateway进程和BusinessWorker进程启动后分别向Register进程注册自己的通讯地址&#xff0c;Gateway进程和BusinessWorker通过Register进程得到通讯地址后&#xff0c;就可以建立起连接并通讯了。而Gateway进程…...

8位移位寄存器的verilog语言

module shift_register (output reg [7:0] Q, // 8位移位寄存器输出input D, // 输入数据input rst, // 复位信号input clk // 时钟信号 );always (posedge clk) beginif (!rst)Q < 8b00000000; // 复位时将Q清零elseQ < {Q[6:0], D}; // 否则…...

Android学习(五)-Kotlin编程语言-面向对象中的 继承-构造函数-接口三模块学习

首先&#xff0c;我们需要定义一个 Person 类&#xff1a; open class Person {var name ""var age 0fun eat() {println("$name is eating.")} } 注意&#xff0c;Person 类前面加上了 open 关键字&#xff0c;表示这个类可以被继承。在 Kotlin 中&am…...

Java 集合框架中的 List、ArrayList 和 泛型 实例

— Java 集合框架中的 List、ArrayList 和 泛型 在 Java 中&#xff0c;集合框架提供了许多不同类型的集合类&#xff0c;用于存储和操作对象。List 和 ArrayList 是最常用的两种集合类型&#xff0c;而泛型&#xff08;Generics&#xff09;则是 Java 中的一项重要特性&…...

计算机网络-L2TP VPN基础概念与原理

一、概述 前面学习了GRE和IPSec VPN&#xff0c;今天继续学习另外一个也很常见的VPN类型-L2TP VPN。 L2TP&#xff08;Layer 2 Tunneling Protocol&#xff09; 协议结合了L2F协议和PPTP协议的优点&#xff0c;是IETF有关二层隧道协议的工业标准。L2TP是虚拟私有拨号网VPDN&…...

【Rust自学】4.4. 引用与借用

4.4.0 写在正文之前 这一节的内容其实就相当于C的智能指针移动语义在编译器层面做了一些约束。Rust中引用的写法通过编译器的约束写成了C中最理想、最规范的指针写法。所以学过C的人对这一章肯定会非常熟悉。 喜欢的话别忘了点赞、收藏加关注哦&#xff08;加关注即可阅读全文…...

LLaMA-Factory 单卡3080*2 deepspeed zero3 微调Qwen2.5-7B-Instruct

环境安装 git clone https://gitcode.com/gh_mirrors/ll/LLaMA-Factory.gitcd LLaMA-Factorypip install -e ".[torch,metrics]"pip install deepspeed 下载模型 pip install modelscope modelscope download --model Qwen/Qwen2.5-7B-Instruct --local_dir /roo…...

[python SQLAlchemy数据库操作入门]-12.直接执行 SQL 语句处理股票数据

哈喽,大家好,我是木头左! 1. SQLAlchemy Core 简介 SQLAlchemy Core 是 SQLAlchemy 库的一个模块,它允许用户直接执行 SQL 语句而不必使用 ORM(对象关系映射)。对于需要精细控制 SQL 查询或处理复杂数据库操作的情况,SQLAlchemy Core 提供了一种灵活而强大的方式来与数…...

【Unity3D】实现可视化链式结构数据(节点数据)

关键词&#xff1a;UnityEditor、可视化节点编辑、Unity编辑器自定义窗口工具 使用Newtonsoft.Json、UnityEditor相关接口实现 主要代码&#xff1a; Handles.DrawBezier(起点&#xff0c;终点&#xff0c;起点切线向量&#xff0c;终点切线向量&#xff0c;颜色&#xff0c;n…...

C# WinForm移除非法字符的输入框

C# WinForm移除非法字符的输入框 文章目录 namespace System.Windows.Forms {using System.ComponentModel;/// <summary>/// 支持移除 非法字符 的输入框。/// </summary>public class RemoveInvalidCharTextBox : TextBox{/// <summary>/// 测试代码&#…...

linux安装宝塔面板及git

宝塔面板安装教程&#xff1a;https://www.bt.cn/new/download.html?bt_lybaidu&sdclkidALfs15q615oG15As&bd_vid9358688624393223862 Centos/OpenCloud/Alibaba稳定版9.0.0 urlhttps://download.bt.cn/install/install_lts.sh;if [ -f /usr/bin/curl ];then curl -s…...

GoTime#34期 Pachyderm, Provenance, Data Lakes

本篇内容是根据2017年2月份#34 Pachyderm, Provenance, Data Lakes音频录制内容的整理与翻译 Joe Doliner 加入了节目&#xff0c;谈论使用 Pachyderm 管理数据湖、数据容器、溯源(provenance) 以及其他有趣的 Go 项目和新闻。 Erik St. Martin: 大家好&#xff0c;欢迎收听新…...

数据库的三范式是什么?

第一范式&#xff08;1NF&#xff09; 每列的原子性&#xff0c;表中的每一个字段都是不可分割的&#xff0c;同一列中不能有多个值。第一范式是对关系模式的基本要求&#xff0c;不满足第一范式的数据库不是关系型数据库。 ・不满足第一范式的示例&#xff1a; 学生编号 学生…...

LOS/NLOS环境建模与三维TOA定位,MATLAB仿真程序,可自定义锚点数量和轨迹点长度

本代码的主要功能是建模 LOS&#xff08;视距&#xff09;和 NLOS&#xff08;非视距&#xff09;环境下的定位系统&#xff0c;估计目标的动态位置&#xff0c;三维空间 文章目录 运行结果源代码代码介绍 总结 运行结果 10个点的轨迹定位&#xff1a; 50个点的轨迹定位&#…...

css

已经学完html了&#xff0c;继续学习前端三剑客html、css、js之一的css。&#x1f600; 1、什么是css css&#xff1a;用于网页结构的布局和修饰的一种样式脚本 层叠样式表&#xff1a;(英文全称&#xff1a;Cascading Style Sheets)&#xff0c; 简称&#xff1a;样式表&…...

探索 Bokeh:轻松创建交互式数据可视化的强大工具

探索 Bokeh&#xff1a;轻松创建交互式数据可视化的强大工具 在数据科学和数据分析领域&#xff0c;交互式数据可视化是一项不可或缺的技能。Bokeh 是一个强大的 Python 库&#xff0c;它可以帮助我们快速构建高质量的交互式图表和仪表盘&#xff0c;同时兼具高性能和灵活性。…...

光谱相机在农业的应用

一、作物生长监测1、营养状况评估 原理&#xff1a;不同的营养元素在植物体内的含量变化会导致植物叶片或其他组织的光谱反射率特性发生改变。例如&#xff0c;氮元素是植物叶绿素的重要组成部分&#xff0c;植物缺氮时&#xff0c;叶绿素含量下降&#xff0c;其在可见光波段&a…...

SYD881X RTC定时器事件在调用timeAppClockSet后会出现比较大的延迟

RTC定时器事件在调用timeAppClockSet后会出现比较大的延迟 这里RTC做了两个定时器一个是12秒,一个是185秒: #define RTCEVT_NUM ((uint8_t) 0x02)//当前定时器事件数#define RTCEVT_12S ((uint32_t) 0x0000002)//定时器1s事件 /*整分钟定时器事件&#xff0c;因为其余的…...

【Java基础面试题026】Java中的String、StringBuffer和StringBuilder的区别是什么?

回答重点 他们都是Java中处理字符串的类&#xff0c;区别主要体现在可变性、线程安全和性能上 1&#xff09;String 不可变&#xff1a;String是不可变类&#xff0c;字符串对象创建&#xff0c;存储在堆中&#xff0c;字符串内容存储在字符串常量池中&#xff0c;一旦创建内…...

Ajax中的axios

既然提到Ajax&#xff0c;那就先来说一说什么是Ajax吧 关于Ajax Ajax的定义 Asynchronous JavaScript And XML&#xff1a;异步的JavaScript和XML。 反正就是一句话总结&#xff1a; 使用XML HttpRequest 对象与服务器进行通讯。 AJAX 是一种在无需重新加载整个网页的情况下&…...

学习ASP.NET Core的身份认证(基于JwtBearer的身份认证3)

根据参考文献1中JWT Token的组成及计算方式&#xff0c;对照参考文献2中的界面&#xff0c;实现简单的JWT Token解析及验证程序&#xff0c;主要功能包括&#xff1a;   1&#xff09;拆分Token字符串&#xff0c;将前两段使用Base64UrlEncoder类解码并转为UTF8字符串&#x…...

jmeter后端监视器

一、概述 JMeter 后端监听器(Backend Listener)是 JMeter 提供的一个功能强大的插件,用于将测试执行期间收集的性能数据发送到外部系统进行监控和分析。通过后端监听器,您可以实时地将 JMeter 测试执行期间收集的数据发送到外部系统,如图形化展示、数据库、数据分析工具等…...

vue CSS 自定义宽高 翻页 剥离 效果

新增需求&#xff0c;客户需要类似PPT的剥离效果用于WEB页面翻页&#xff0c;查找资料后&#xff0c;参考下方的掘金博主的文章&#xff0c;并将HTML修改成vue的页面进行使用。其中宽度、高度改成了变量&#xff0c;样式style中的属性与宽高的关系整理成了公式进行动态计算。 …...

函数:参数与返回值类型

本文我们将深入探讨 函数的参数和返回值类型&#xff0c;这是 TypeScript 中最常用的特性之一。了解如何为函数参数和返回值添加类型&#xff0c;不仅能帮助你避免常见的错误&#xff0c;还能提高代码的可读性和可维护性。 在 JavaScript 中&#xff0c;函数的参数和返回值是没…...

【学习总结|DAY022】Java网络编程

网络编程是Java开发中非常重要的一环&#xff0c;它允许程序与网络上的其他设备进行数据交互。本文将介绍Java网络编程的基础知识&#xff0c;包括网络编程三要素、UDP和TCP通信协议&#xff0c;以及BS架构的原理。 网络编程三要素 网络通信至少需要三个要素&#xff1a;IP地…...

帝国cms同一条信息使用不同的多个内容页模板伪静态实现教程

理论上可以实现一条信息使用无数个内容页模板&#xff0c;实现过程&#xff1a; 1、/e/action目录下新建bishun.php&#xff0c;内容如下&#xff1a; <?php require(../class/connect.php); require(../class/db_sql.php); require(../class/functions.php); require(..…...

解决Linux<云服务器>访问HuggingFace的问题(操作记录)

一、准备配置文件 cache.db clash config.yaml Country.mmdb&#xff08;1&#xff09;cache.db、clash的获取 链接&#xff1a;百度网盘 提取码&#xff1a;82t0 &#xff08;2&#xff09;config.yaml、Country.mmdb的获取 启动本地已安装的clash软件→找到“配置订阅”…...

selenium 报错 invalid argument: invalid locator

环境&#xff1a; Python3.12.2 selenium4.0 报错信息&#xff1a; invalid argument: invalid locator 错误分析&#xff1a; selenium语法错误,find_element方法少写By.XPATH参数 错误语法如下&#xff1a; driver.find_element(//div[id"myid"]) 解决办…...

springboot——登录认证(包括jwt技术、拦截器过滤器)

实现登录的原理 用户名和密码都输入正确,登录成功,否则,登录失败 登录功能的本质:查询,根据用户名和密码查询员工信息 实现登录的步骤 登录需要确定用户的id、username、name、token(用于 身份校验),对此要重新定义一个类LoginInfo public class LoginInfo {priva…...

【IN、NOT、AND、OR】在 MySql 中的使用方法,使用场景、注意事项

目录 IN NOT AND OR 注意事项&#xff1a; 使用场景&#xff1a; IN 用于指定某个字段的值在一个预定义的列表中。 SELECT * FROM users WHERE age IN (20, 25, 30);查询返回 age 字段 是20、25 、30 的用户记录。 NOT 用于对条件进行否定。 查询将返回与指定 条件相…...

html <a>设置发送邮件链接、打电话链接 <a href=“mailto:></a> <a href=“tel:></a>

1.代码 <ul><li>电话&#xff1a;<a href"tel:18888888888">188-8888-8888</a></li><li>邮箱&#xff1a;<a href"mailto:10000qq.com">10000qq.com</a></li><li>邮箱&#xff1a;<a hre…...

Mac上详细配置java开发环境和软件(更新中)

文章目录 概要JDK的配置JDK下载安装配置JDK环境变量文件 Idea的安装Mysql安装和配置Navicat Premium16.1安装安装Vscode安装和配置Maven配置本地仓库配置阿里云私服Idea集成Maven Cpolar快速入门 概要 这里使用的是M3型片 14.6版本的Mac 用到的资源放在网盘 链接: https://pan…...

游戏渠道假量解决方案

某推广公司在推广过程中被查出“短期内点击量激增”“存在同一地址多次访问”“已注册用户重复注册”等数据作弊行为&#xff0c;法院判罚退还服务费200余万元&#xff0c;并赔偿违约金约350万元。 某公司为提升其游戏在应用商店榜单排名&#xff0c;委托某网络公司进行下载、注…...

Java重要面试名词整理(二):SpringMyBatis

文章目录 Spring篇Spring核心推断构造方法AOP动态代理Advice的分类Advisor的理解AOP相关的概念 定义BeanASM技术JFR依赖注入循环依赖LifecycleSpring AOT Spring事务Spring事务传播机制Spring事务传播机制是如何实现的呢?Spring事务传播机制分类 SpringMVCHandlerHandlerMappi…...

powershell美化

powershell美化 写在前面 除了安装命令&#xff0c;其他都是测试命令&#xff0c;后续再写进配置文件 安装主题控件 安装主题oh-my-posh&#xff0c;powershell中执行 winget install JanDeDobbeleer.OhMyPosh -s winget oh-my-posh init pwsh | Invoke-Expression # 查看…...

D102【python 接口自动化学习】- pytest进阶之fixture用法

day102 pytest的usefixtures方法 学习日期&#xff1a;20241219 学习目标&#xff1a;pytest基础用法 -- pytest的usefixtures方法 学习笔记&#xff1a; fixture调用方法 实际应用 总结 pytest.mark.usefixtures(func)&#xff0c;pytest的usefixtures方法&#xff0c;无…...

Excel生成DBC脚本源文件

Excel制作 新建一个Excel&#xff0c;后缀为“.xls” 工作本名称改为“CAN_Matrix” 在首行按照列来起名字&#xff0c;在里面只需要填写必须的内容即可。 列数名称第0列Message Name第1列Message Format第2列Message ID第3列Message Length (byte)第4列Message Transmitte…...

【Leetcode 每日一题】2545. 根据第 K 场考试的分数排序

问题背景 班里有 m m m 位学生&#xff0c;共计划组织 n n n 场考试。给你一个下标从 0 0 0 开始、大小为 m n m \times n mn 的整数矩阵 s c o r e score score&#xff0c;其中每一行对应一位学生&#xff0c;而 s c o r e [ i ] [ j ] score[i][j] score[i][j] 表示…...

Spring MVC(上)

上一篇博客的补充: 一般出现这种问题,我们就要检查版本了 我们需要查看这几个地方是否版本是对的 注意: jdk版本运行取决于什么? 1.通过cmd运行,jdk版本就是你设置的环境变量 2.通过Idea运行,取决于该项目设置的JDK版本 创建项目的方式: 1> 我们上个博客用idea进行创建 2…...