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

40分钟学 Go 语言高并发:Context包与并发控制

Context包与并发控制

学习目标

知识点掌握程度应用场景
context原理深入理解实现机制并发控制和请求链路追踪
超时控制掌握超时设置和处理API请求超时、任务限时控制
取消信号传播理解取消机制和传播链优雅退出、资源释放
context最佳实践掌握使用规范和技巧工程实践中的常见场景

1. Context原理

1.1 Context基本结构和实现

让我们先看一个完整的Context使用示例:

package mainimport ("context""fmt""log""time"
)// 请求追踪信息
type RequestInfo struct {TraceID    stringSessionID  stringStartTime  time.Time
}// 服务接口
type Service interface {HandleRequest(ctx context.Context, req string) (string, error)
}// 业务服务实现
type BusinessService struct {name string
}func NewBusinessService(name string) *BusinessService {return &BusinessService{name: name}
}// 处理请求
func (s *BusinessService) HandleRequest(ctx context.Context, req string) (string, error) {// 获取请求追踪信息info, ok := ctx.Value("request-info").(*RequestInfo)if !ok {return "", fmt.Errorf("request info not found in context")}log.Printf("[%s] Processing request: %s, TraceID: %s, Session: %s\n",s.name, req, info.TraceID, info.SessionID)// 模拟处理过程select {case <-time.After(2 * time.Second):return fmt.Sprintf("Result for %s", req), nilcase <-ctx.Done():return "", ctx.Err()}
}// 请求中间件
func requestMiddleware(next Service) Service {return &middlewareService{next: next}
}type middlewareService struct {next Service
}func (m *middlewareService) HandleRequest(ctx context.Context, req string) (string, error) {// 开始时间startTime := time.Now()// 添加请求信息到contextinfo := &RequestInfo{TraceID:   fmt.Sprintf("trace-%d", time.Now().UnixNano()),SessionID: fmt.Sprintf("session-%d", time.Now().Unix()),StartTime: startTime,}ctx = context.WithValue(ctx, "request-info", info)// 调用下一个处理器result, err := m.next.HandleRequest(ctx, req)// 记录处理时间duration := time.Since(startTime)log.Printf("Request completed in %v, TraceID: %s\n", duration, info.TraceID)return result, err
}func main() {// 创建服务service := requestMiddleware(NewBusinessService("UserService"))// 创建基础contextctx := context.Background()// 添加超时控制ctx, cancel := context.WithTimeout(ctx, 3*time.Second)defer cancel()// 处理请求result, err := service.HandleRequest(ctx, "get user profile")if err != nil {log.Printf("Request failed: %v\n", err)return}log.Printf("Request succeeded: %s\n", result)// 模拟超时场景ctx, cancel = context.WithTimeout(context.Background(), 1*time.Second)defer cancel()result, err = service.HandleRequest(ctx, "get user settings")if err != nil {log.Printf("Request failed: %v\n", err)return}
}

2. 超时控制

让我们实现一个带有超时控制的HTTP服务:

package mainimport ("context""encoding/json""fmt""log""net/http""time"
)// 响应结构
type Response struct {Data  interface{} `json:"data,omitempty"`Error string      `json:"error,omitempty"`
}// 服务配置
type ServiceConfig struct {Timeout        time.DurationMaxConcurrent  intRetryAttempts  intRetryDelay     time.Duration
}// HTTP客户端包装器
type HTTPClient struct {client  *http.Clientconfig  ServiceConfiglimiter chan struct{} // 并发限制器
}// 创建新的HTTP客户端
func NewHTTPClient(config ServiceConfig) *HTTPClient {return &HTTPClient{client: &http.Client{Timeout: config.Timeout,},config: config,limiter: make(chan struct{}, config.MaxConcurrent),}
}// 发送HTTP请求
func (c *HTTPClient) DoRequest(ctx context.Context, method, url string) (*Response, error) {var lastErr errorfor attempt := 0; attempt <= c.config.RetryAttempts; attempt++ {select {case <-ctx.Done():return nil, ctx.Err()case c.limiter <- struct{}{}: // 获取并发许可}// 确保释放并发许可defer func() {<-c.limiter}()// 创建请求req, err := http.NewRequestWithContext(ctx, method, url, nil)if err != nil {return nil, fmt.Errorf("create request failed: %w", err)}// 设置请求超时reqCtx, cancel := context.WithTimeout(ctx, c.config.Timeout)defer cancel()// 执行请求resp, err := c.client.Do(req.WithContext(reqCtx))if err != nil {lastErr = errlog.Printf("Request failed (attempt %d): %v\n", attempt+1, err)// 如果不是最后一次尝试,等待后重试if attempt < c.config.RetryAttempts {select {case <-ctx.Done():return nil, ctx.Err()case <-time.After(c.config.RetryDelay):continue}}continue}defer resp.Body.Close()// 解析响应var result Responseif err := json.NewDecoder(resp.Body).Decode(&result); err != nil {return nil, fmt.Errorf("decode response failed: %w", err)}return &result, nil}return nil, fmt.Errorf("all retry attempts failed, last error: %v", lastErr)
}// 处理HTTP请求的处理器
func handleRequest(w http.ResponseWriter, r *http.Request) {// 创建contextctx := r.Context()// 模拟长时间处理select {case <-time.After(2 * time.Second):response := Response{Data: "Request processed successfully",}json.NewEncoder(w).Encode(response)case <-ctx.Done():response := Response{Error: "Request timeout",}w.WriteHeader(http.StatusGatewayTimeout)json.NewEncoder(w).Encode(response)}
}func main() {// 配置HTTP客户端config := ServiceConfig{Timeout:       5 * time.Second,MaxConcurrent: 10,RetryAttempts: 3,RetryDelay:    time.Second,}client := NewHTTPClient(config)// 创建HTTP服务器http.HandleFunc("/api", handleRequest)// 启动服务器go func() {log.Println("Server starting on :8080")if err := http.ListenAndServe(":8080", nil); err != nil {log.Fatal(err)}}()// 等待服务器启动time.Sleep(time.Second)// 测试请求ctx := context.Background()// 测试正常请求resp, err := client.DoRequest(ctx, "GET", "http://localhost:8080/api")if err != nil {log.Printf("Request failed: %v\n", err)} else {log.Printf("Response: %+v\n", resp)}// 测试超时请求ctx, cancel := context.WithTimeout(ctx, time.Second)defer cancel()resp, err = client.DoRequest(ctx, "GET", "http://localhost:8080/api")if err != nil {log.Printf("Request failed (expected): %v\n", err)} else {log.Printf("Response: %+v\n", resp)}// 保持主程序运行select {}
}
package mainimport ("context""fmt""math/rand""sync""time"
)// 请求处理器
type RequestHandler struct {requests  chan Requestresponses chan Responsedone      chan struct{}wg        sync.WaitGroup
}// 请求结构
type Request struct {ID      intTimeout time.DurationData    string
}// 响应结构
type Response struct {RequestID intResult    stringError     error
}// 创建新的请求处理器
func NewRequestHandler() *RequestHandler {return &RequestHandler{requests:  make(chan Request, 100),responses: make(chan Response, 100),done:      make(chan struct{}),}
}// 启动处理器
func (h *RequestHandler) Start(workers int) {for i := 0; i < workers; i++ {h.wg.Add(1)go h.worker(i)}
}// 工作协程
func (h *RequestHandler) worker(id int) {defer h.wg.Done()for {select {case req, ok := <-h.requests:if !ok {fmt.Printf("Worker %d: request channel closed\n", id)return}// 创建context用于超时控制ctx, cancel := context.WithTimeout(context.Background(), req.Timeout)// 处理请求response := h.processRequest(ctx, req)// 发送响应select {case h.responses <- response:fmt.Printf("Worker %d: sent response for request %d\n", id, req.ID)case <-h.done:cancel()return}cancel() // 清理contextcase <-h.done:fmt.Printf("Worker %d: received stop signal\n", id)return}}
}// 处理单个请求
func (h *RequestHandler) processRequest(ctx context.Context, req Request) Response {// 模拟处理时间processTime := time.Duration(rand.Intn(int(req.Timeout))) + req.Timeout/2select {case <-time.After(processTime):return Response{RequestID: req.ID,Result:   fmt.Sprintf("Processed: %s", req.Data),}case <-ctx.Done():return Response{RequestID: req.ID,Error:    ctx.Err(),}}
}// 提交请求
func (h *RequestHandler) SubmitRequest(req Request) error {select {case h.requests <- req:return nilcase <-h.done:return fmt.Errorf("handler is stopped")}
}// 获取响应
func (h *RequestHandler) GetResponse() (Response, error) {select {case resp := <-h.responses:return resp, nilcase <-h.done:return Response{}, fmt.Errorf("handler is stopped")}
}// 停止处理器
func (h *RequestHandler) Stop() {close(h.done)h.wg.Wait()close(h.requests)close(h.responses)
}func main() {// 创建请求处理器handler := NewRequestHandler()handler.Start(3)// 发送一些测试请求requests := []Request{{ID: 1, Timeout: time.Second, Data: "Fast request"},{ID: 2, Timeout: time.Second * 2, Data: "Normal request"},{ID: 3, Timeout: time.Millisecond * 500, Data: "Quick request"},{ID: 4, Timeout: time.Second * 3, Data: "Slow request"},}// 提交请求for _, req := range requests {if err := handler.SubmitRequest(req); err != nil {fmt.Printf("Failed to submit request %d: %v\n", req.ID, err)continue}fmt.Printf("Submitted request %d\n", req.ID)}// 收集响应var wg sync.WaitGroupwg.Add(1)go func() {defer wg.Done()for i := 0; i < len(requests); i++ {resp, err := handler.GetResponse()if err != nil {fmt.Printf("Failed to get response: %v\n", err)continue}if resp.Error != nil {fmt.Printf("Request %d failed: %v\n", resp.RequestID, resp.Error)} else {fmt.Printf("Request %d succeeded: %s\n", resp.RequestID, resp.Result)}}}()// 等待所有响应处理完成wg.Wait()// 停止处理器handler.Stop()fmt.Println("Main: processing completed")
}

3. 取消信号传播

让我们继续完成取消信号传播的示例代码:

package mainimport ("context""fmt""log""sync""time"
)// 任务定义
type Task struct {ID      stringProcess func(ctx context.Context) (interface{}, error)
}// 工作池
type WorkerPool struct {workers    inttasks      chan Taskresults    chan interface{}errors     chan errordone       chan struct{}wg         sync.WaitGroup
}// 创建新的工作池
func NewWorkerPool(workers int) *WorkerPool {return &WorkerPool{workers: workers,tasks:   make(chan Task, workers*2),results: make(chan interface{}, workers*2),errors:  make(chan error, workers*2),done:    make(chan struct{}),}
}// 启动工作池
func (p *WorkerPool) Start(ctx context.Context) {// 启动workersfor i := 0; i < p.workers; i++ {p.wg.Add(1)go p.worker(ctx, i)}// 等待所有worker完成go func() {p.wg.Wait()close(p.done)close(p.results)close(p.errors)}()
}// worker处理任务
func (p *WorkerPool) worker(ctx context.Context, id int) {defer p.wg.Done()log.Printf("Worker %d started\n", id)for {select {case <-ctx.Done():log.Printf("Worker %d stopped: %v\n", id, ctx.Err())returncase task, ok := <-p.tasks:if !ok {log.Printf("Worker %d: task channel closed\n", id)return}log.Printf("Worker %d processing task %s\n", id, task.ID)// 创建任务专用的contexttaskCtx, cancel := context.WithTimeout(ctx, 5*time.Second)// 执行任务result, err := task.Process(taskCtx)cancel() // 释放任务context资源if err != nil {select {case p.errors <- fmt.Errorf("task %s failed: %w", task.ID, err):case <-ctx.Done():return}} else {select {case p.results <- result:case <-ctx.Done():return}}}}
}// 提交任务
func (p *WorkerPool) Submit(task Task) error {select {case p.tasks <- task:return nilcase <-p.done:return fmt.Errorf("worker pool is closed")}
}// 关闭工作池
func (p *WorkerPool) Close() {close(p.tasks)
}// 获取结果通道
func (p *WorkerPool) Results() <-chan interface{} {return p.results
}// 获取错误通道
func (p *WorkerPool) Errors() <-chan error {return p.errors
}func main() {// 创建根contextctx, cancel := context.WithCancel(context.Background())defer cancel()// 创建工作池pool := NewWorkerPool(3)pool.Start(ctx)// 创建模拟任务tasks := []Task{{ID: "task-1",Process: func(ctx context.Context) (interface{}, error) {select {case <-time.After(2 * time.Second):return "Task 1 completed", nilcase <-ctx.Done():return nil, ctx.Err()}},},{ID: "task-2",Process: func(ctx context.Context) (interface{}, error) {select {case <-time.After(3 * time.Second):return "Task 2 completed", nilcase <-ctx.Done():return nil, ctx.Err()}},},{ID: "task-3",Process: func(ctx context.Context) (interface{}, error) {select {case <-time.After(1 * time.Second):return nil, fmt.Errorf("task 3 failed")case <-ctx.Done():return nil, ctx.Err()}},},}// 提交任务for _, task := range tasks {if err := pool.Submit(task); err != nil {log.Printf("Failed to submit task %s: %v\n", task.ID, err)}}// 等待3秒后取消所有任务go func() {time.Sleep(3 * time.Second)log.Println("Cancelling all tasks...")cancel()}()// 收集结果和错误completed := 0expected := len(tasks)for completed < expected {select {case result, ok := <-pool.Results():if !ok {continue}log.Printf("Got result: %v\n", result)completed++case err, ok := <-pool.Errors():if !ok {continue}log.Printf("Got error: %v\n", err)completed++case <-ctx.Done():log.Printf("Main: context cancelled: %v\n", ctx.Err())completed = expected // 强制退出循环}}// 关闭工作池pool.Close()// 等待工作池完全关闭<-pool.donelog.Println("All workers stopped")
}

3.1 取消信号传播流程图

在这里插入图片描述

4. Context最佳实践

4.1 Context使用规范

  1. 函数调用链传递
// 推荐
func HandleRequest(ctx context.Context, req *Request) error// 不推荐
func HandleRequest(timeout time.Duration, req *Request) error
  1. Context应作为第一个参数
// 推荐
func ProcessTask(ctx context.Context, task *Task) error// 不推荐
func ProcessTask(task *Task, ctx context.Context) error
  1. 不要储存Context在结构体中
// 不推荐
type Service struct {ctx context.Context
}// 推荐
type Service struct {// 其他字段
}func (s *Service) DoWork(ctx context.Context) error

4.2 Context使用注意事项

  1. 不要将nil传递给context参数
// 推荐
ctx := context.Background()
ProcessTask(ctx, task)// 不推荐
ProcessTask(nil, task)
  1. context.Value应该只用于请求作用域数据
// 推荐
ctx = context.WithValue(ctx, "request-id", requestID)// 不推荐 - 配置信息应该通过其他方式传递
ctx = context.WithValue(ctx, "db-config", dbConfig)
  1. 正确处理取消信号
select {
case <-ctx.Done():return ctx.Err()
default:// 继续处理
}

4.3 实践建议

  1. 超时控制
  • 设置合理的超时时间
  • 在不同层级使用不同的超时时间
  • 确保资源正确释放
  1. 错误处理
  • 区分超时和取消错误
  • 传递有意义的错误信息
  • 实现优雅降级
  1. 性能优化
  • 避免创建过多的context
  • 合理使用context.Value
  • 及时取消不需要的操作
  1. 日志追踪
  • 记录关键操作的耗时
  • 追踪请求的完整链路
  • 记录取消原因

总结

关键点回顾

  1. Context原理
  • 继承关系
  • 值传递机制
  • 生命周期管理
  1. 超时控制
  • 设置超时时间
  • 处理超时信号
  • 资源清理
  1. 取消信号传播
  • 信号传递机制
  • 取消处理流程
  • 资源释放
  1. 最佳实践
  • 使用规范
  • 注意事项
  • 优化建议

实践建议

  1. 代码规范
  • 遵循命名约定
  • 合理组织代码结构
  • 添加必要的注释
  1. 错误处理
  • 使用有意义的错误信息
  • 实现错误恢复机制
  • 记录错误日志
  1. 性能优化
  • 减少不必要的context创建
  • 避免context.Value滥用
  • 及时释放资源

怎么样今天的内容还满意吗?再次感谢观众老爷的观看,关注GZH:凡人的AI工具箱,回复666,送您价值199的AI大礼包。最后,祝您早日实现财务自由,还请给个赞,谢谢!

相关文章:

40分钟学 Go 语言高并发:Context包与并发控制

Context包与并发控制 学习目标 知识点掌握程度应用场景context原理深入理解实现机制并发控制和请求链路追踪超时控制掌握超时设置和处理API请求超时、任务限时控制取消信号传播理解取消机制和传播链优雅退出、资源释放context最佳实践掌握使用规范和技巧工程实践中的常见场景…...

el-row el-col显示失效问题修复

el-row el-col显示失效 问题&#xff1a; 在列表显示页面&#xff0c;头部有几个搜索框和选择框&#xff0c;由于搜索条件框太多&#xff0c;写了el-row 和el-col进行分行分列展示。测试发现并没有按照行列展示。 <el-form :inline"true" :model"paramForm…...

libphone desktop编译

linphone-desktop 在ubuntu20.04 下编译 linphone 介绍 Linphone是一款遵循GPL的开源网络视频电话系统&#xff0c;支持多种平台如Windows、Linux、Android等。它基于SIP协议&#xff0c;提供语音、视频通话及即时文本消息功能。核心功能包括SIP用户代理、音频视频Codec支持、…...

实现一个可配置的TCP设备模拟器,支持交互和解析配置

前言 诸位在做IOT开发的时候是否有遇到一个问题&#xff0c;那就是模拟一个设备来联调测试&#xff0c;虽然说现在的物联网通信主要是用mqtt通信&#xff0c;但还是有很多设备使用TCP这种协议交互&#xff0c;例如充电桩&#xff0c;还有一些工业设备&#xff0c;TCP这类报文交…...

Rust环境安装乱码解决

安装rust环境open with visual studio2022操作系统乱码问题解决 打开“设置”&#xff0c;找到“时间和语言”。 进去之后依次选择“语言”->"管理语言设置"->“更改系统区域设置” 取消勾选“Beta版:使用Unicode UTF-8 提供全球语言支持”&#xff0c;然后重…...

Zookeeper实现分布式锁、Zookeeper实现配置中心

一、Zookeeper实现分布式锁 分布式锁主要用于在分布式环境中保证数据的一致性。 包括跨进程、跨机器、跨网络导致共享资源不一致的问题。 1.Zookeeper分布式锁的代码实现 新建一个maven项目ZK-Demo,然后在pom.xml里面引入相关的依赖 <dependency><groupId>com.…...

学习日记_20241126_聚类方法(自组织映射Self-Organizing Maps, SOM)

前言 提醒&#xff1a; 文章内容为方便作者自己后日复习与查阅而进行的书写与发布&#xff0c;其中引用内容都会使用链接表明出处&#xff08;如有侵权问题&#xff0c;请及时联系&#xff09;。 其中内容多为一次书写&#xff0c;缺少检查与订正&#xff0c;如有问题或其他拓展…...

【webrtc】 mediasoup中m77的IntervalBudget及其在AlrDetector的应用

IntervalBudget 用于带宽控制和流量整形 mediasoup中m77 代码的IntervalBudget ,版本比较老IntervalBudget 在特定时间间隔内的比特预算管理,从而实现带宽控制和流量整形。 一。 pacedsender 执行周期: 下一次执行的时间的动态可变的 int64_t PacedSender::TimeUntilNextPr…...

Python学习指南 + 谷歌浏览器如何安装插件

找往期文章包括但不限于本期文章中不懂的知识点&#xff1a; 个人主页&#xff1a;我要学编程(ಥ_ಥ)-CSDN博客 所属专栏&#xff1a; Python 目录 前言 Python 官方文档的使用 谷歌浏览器中如何安装插件 前言 在学习Python时&#xff0c;我们可能会出现这样的困惑&#x…...

leetcode - LRU缓存

什么是 LRU LRU (最近最少使用算法), 最早是在操作系统中接触到的, 它是一种内存数据淘汰策略, 常用于缓存系统的淘汰策略. LRU算法基于局部性原理, 即最近被访问的数据在未来被访问的概率更高, 因此应该保留最近被访问的数据. 最近最少使用的解释 LRU (最近最少使用算法), 中…...

RabbitMQ7:消息转换器

欢迎来到“雪碧聊技术”CSDN博客&#xff01; 在这里&#xff0c;您将踏入一个专注于Java开发技术的知识殿堂。无论您是Java编程的初学者&#xff0c;还是具有一定经验的开发者&#xff0c;相信我的博客都能为您提供宝贵的学习资源和实用技巧。作为您的技术向导&#xff0c;我将…...

C#(14)七大原则

前言 其实在面向对象设计里&#xff0c;程序猿们互相约定好一些原则&#xff0c;即七大原则。 面向对象的七大原则是一组指导软件设计的原则&#xff0c;旨在帮助开发人员实现松耦合、可维护和可扩展的软件系统。这些原则的设计过程和发展历史可以追溯到20世纪80年代。 单一职…...

JDBC使用连接池druid操作数据库mysql

// 创建DruidDataSource实例DruidDataSource dataSource = new DruidDataSource();String url = "jdbc:mysql://localhost:3306/demo_base?useUnicode=true&characterEncoding=utf8&useSSL=true";String username...

零碎04 MybatisPlus自定义模版生成代码

目录 背景 动手开干 需要的依赖包&#xff0c;需要注意mybatis-plus-generator的3.5版本是没有兼容历史版本的。 定义一个CodeGenerator类&#xff0c;负责生成代码和配置属性 Entity模版 背景 MybatisPlus代码生成使用默认的velocity模版解决不了定制化的需求&#xff0…...

rk3568-linux-5.10.160移植rtl8822cs wifi 模块纪要

rk3568-linux-5.10.160移植rtl8822cs wifi 模块纪要 1、将驱动添加到 kernel/drivers/net/wireless/rockchip_wlan/ 或者 kernel/drivers/net/wireless/realtek/rtlwifi/ 2、修改该目录下的makefile、kconfig 3、修改rtl8822cs/os_dep/linux/os_intfs.c&#xff0c;添加 MO…...

uniapp接入高德地图

下面代码兼容安卓APP和H5 高德地图官网&#xff1a;我的应用 | 高德控制台 &#xff0c;绑定服务选择《Web端(JS API)》 /utils/map.js 需要设置你自己的key和安全密钥 export function myAMap() {return new Promise(function(resolve, reject) {if (typeof window.onLoadM…...

如何通过高效的缓存策略无缝加速湖仓查询

引言 本文将探讨如何利用开源项目 StarRocks 的缓存策略来加速湖仓查询&#xff0c;为企业提供更快速、更灵活的数据分析能力。作为 StarRocks 社区的主要贡献者和商业化公司&#xff0c;镜舟科技深度参与 StarRocks 项目开发&#xff0c;也为企业着手构建湖仓架构提供更多参考…...

微信小程序数据请求教程:GET与POST请求详解

微信小程序数据请求教程:GET与POST请求详解 引言 在微信小程序的开发过程中,数据请求是至关重要的一部分。通过与后端服务器进行通信,小程序能够获取动态数据,实现丰富的功能。在这篇文章中,我们将深入探讨微信小程序中的数据请求,重点介绍GET和POST请求的使用方法、示…...

【Redis 】Bitmap 使用

Redis Bitmap介绍 Redis Bitmap 是一种特殊的数据类型&#xff0c;它通过字符串类型键来存储一系列连续的二进制位&#xff08;bits&#xff09;&#xff0c;每个位可以独立地表示一个布尔值&#xff08;0 或 1&#xff09;。这种数据结构非常适合用于存储和操作大量二值状态的…...

【C语言】指针与数组的例题详解:深入分析与高级用法

博客主页&#xff1a; [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: C语言 文章目录 &#x1f4af;前言&#x1f4af;题目一详细分析与解答代码逐步解析 &#x1f4af;进一步优化和拓展1. 指针与数组的关系2. 指针运算的注意事项3. 常见的错误和陷阱4. 拓展&#xff1a;指针操作的应用场…...

CTF之密码学(密码特征分析)

一.MD5,sha1,HMAC,NTLM 1.MD5:MD5一般由32/16位的数字(0-9)和字母(a-f)组成的字符串 2.sha1:这种加密的密文特征跟MD5差不多,只不过位数是40(sha256:64位;sha512:128位) 3.HMAC:这种算法就是在前两种加密的基础上引入了秘钥,而秘钥又只有传输双方才知道,所以基本上…...

docker compose 使用记录

作用 Docker Compose 是一个用于定义和运行多容器 Docker 应用程序的工具。通过一个 YAML 文件来配置应用程序的服务&#xff0c;然后使用一个命令即可创建并启动所有服务。 文档位置 Part 7: Use Docker Compose | Docker Docs 使用方法 1. 安装 Docker Compose sudo curl -…...

Python的3D可视化库 - vedo (3)visual子模块 点对象的可视化控制

文章目录 3 PointsVisual的方法3.1 对象属性3.1.1 顶点大小3.1.2 复制属性3.1.3 颜色设置3.1.4透明度设置 3.2 对象光效3.2.1 点的形状3.2.2 点的表面光效 3.3 尾随线和投影3.3.1 尾随线3.3.2 投影 3.4 给对象附加文字说明3.4.1 标注3.4.2 2D标注3.4.3 气泡说明3.4.4 旗标说明3…...

计算机网络易混淆知识点串记

文章目录 计算机网络易混淆知识点串记各层PDU首部:地址长度 计算机网络易混淆知识点串记 各层PDU首部: PUD首部长度 (B:字节)首部单位数据链路–帧帧首:14B帧尾部:4B——IPV420~60字节4B [通过4位二进制表示]IPV6固定首部40字节[可拓展]4BTCP20~60字节4BUDP8B字节 地址长度 …...

信息安全实验--密码学实验工具:CrypTool

1. CrypTool介绍&#x1f4ad; CrypTool 1的开源教育工具&#xff0c;用于密码学研究。通过CrypTool 1&#xff0c;可以实现加密和解密操作&#xff0c;数字签名。CrypTool1和2有很多区别的。 2. CrpyTool下载&#x1f527; 在做信息安全实验--密码学相关实验时&#xff0c;发…...

Leetcode 将有序数组转换为二叉搜索树

算法思想及代码解析&#xff1a; 这段代码的目的是将一个有序数组转换为 高度平衡的二叉搜索树&#xff08;Balanced Binary Search Tree, BST&#xff09;。以下是算法的详细解释&#xff1a; 1. 什么是高度平衡的二叉搜索树&#xff1f; 二叉搜索树&#xff1a;对于树中的每…...

VMware虚拟机安装Win7专业版详细教程(附镜像包)

目录 一、Win7镜像下载 二、配置虚拟机 三、安装Win7 四、常见问题 一、Win7镜像下载 镜像下载链接&#xff1a;https://pan.quark.cn/s/a8d3a2880101 此镜像为Win7专业版&#xff08;收藏级镜像 已自用几年&#xff09; 官方纯净系统没有附带任何其他第三方软件&#xf…...

IDEA算法的详细介绍及Python实现

目录 IDEA算法的详细介绍及Python实现引言第一部分:IDEA算法的原理与背景1.1 IDEA算法的来源与特点1.2 IDEA算法的核心步骤第二部分:IDEA算法的Python实现(面向对象设计)2.1 核心类设计2.2 代码实现2.3 使用示例第三部分:案例1 - 函数优化问题(策略模式)3.1 问题描述3.2…...

Spring Boot 开发环境搭建详解

下面安装spring boot的详细步骤&#xff0c;涵盖了从安装 JDK 和 Maven 到创建和运行一个 Spring Boot 项目的全过程。 文章目录 1. 安装 JDK步骤 1.1&#xff1a;下载 JDK步骤 1.2&#xff1a;安装 JDK步骤 1.3&#xff1a;配置环境变量 2. 安装 Maven步骤 2.1&#xff1a;下载…...

Element-Ui组件(icon组件)

一、前言 本篇文章主要是对官网的Icon组件进行总结归纳Icon 图标 | Element Plus 在现代Web应用开发中&#xff0c;图标是用户界面设计中不可或缺的一部分。它们不仅提升了用户体验&#xff0c;还使得信息的传达更加直观和高效。本文主要对Element Plus 官方提供的Icon组件进行…...

使用docker搭建hysteria2服务端

源链接&#xff1a;https://github.com/apernet/hysteria/discussions/1248 官网地址&#xff1a;https://v2.hysteria.network/zh/docs/getting-started/Installation/ 首选需要安装docker和docker compose 切换到合适的目录 cd /home创建文件夹 mkdir hysteria创建docke…...

Docker login 报证书存储错误的解决办法

文章目录 docker login 出现错误&#xff0c;提示&#xff1a;Error saving credentials: error storing credentials - err: exit status 1, out: Cannot autolaunch D-Bus without X11 $DISPLAY 环境 使用的是 Mint Linux &#xff0c;容器为 docker-ce 最新版 1 2 3 4 $…...

vxe-modal VxeUI 窗口组件弹窗多窗口模式

VxeUI 实现在 vue 中使用弹窗组件&#xff0c;弹窗多个窗口可叠加&#xff0c;实现多实例的窗口组件。 npm install vxe-pc-ui4.3.6// ...import VxeUI from vxe-pc-uiimport vxe-pc-ui/lib/style.css// ...createApp(App).use(VxeUI).mount(#app)// ...官网&#xff1a;https…...

华为昇腾 acl_pytorch

目录 sam部署教程&#xff1a; segment-anyghing地址&#xff1a; sam onnx地址&#xff1a; 报错&#xff1a; encode继续报错&#xff1a; sam部署教程&#xff1a; Ascend/ModelZoo-PyTorch - Gitee.com segment-anyghing地址&#xff1a; https://github.com/visher…...

Mybatis控制台打印SQL执行信息(执行方法、执行SQL、执行时间)

文章目录 前言一、基本功能介绍1.1本章功能效果预览图: 二、可执行源码2.1 yaml基础配置2.2 MybatisAnalyzeSQLInterceptor实现SQL拦截 前言 SQL性能监控是一个程序必要的功能&#xff0c;通常我们可以使用数据库自带的客户端工具进行SQL性能分析。然而对于一些专业度不高的人…...

Easyui 实现订单拆分开票功能

Easyui 实现订单拆分开票功能 需求 1、实现一个订单开具多分发票功能&#xff1b; 2、支持拆行&#xff1b; 3、支持拆数量&#xff1b; 流程设计 1、操作页面展示订订单头信息&#xff0c;订单明细信息 2、点击新增发票按钮弹出一个弹出框用于创建一张拆分发票&#xff0c;弹…...

docker-elasticsearch-kibana-logstash

一、安装 Elasticsearch 尝试直接拉取 Elasticsearch 镜像&#xff1a; 执行 docker pull docker.elastic.co/elasticsearch/elasticsearch&#xff0c;拉取失败&#xff0c;错误提示为 “Error response from daemon: manifest for docker.elastic.co/elasticsearch/elasticse…...

深入理解注意力机制(Attention Mechanism)

在深度学习中&#xff0c;“注意力机制&#xff08;Attention Mechanism&#xff09;”是近年来的一个重要突破。它最初被提出用于处理自然语言处理&#xff08;NLP&#xff09;任务&#xff0c;但如今已经广泛应用于计算机视觉、强化学习和其他领域。注意力机制赋予模型一种“…...

大数据-231 离线数仓 - DWS 层、ADS 层的创建 Hive 执行脚本

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; Java篇开始了&#xff01; 目前开始更新 MyBatis&#xff0c;一起深入浅出&#xff01; 目前已经更新到了&#xff1a; Hadoop&#xff0…...

vitess使用:基于源码运行vtctldclient工具

继续未完成的探索事业。 这篇文章《vitess使用&#xff1a;从部署到go客户端连接查询》记录了基于官方文档起的一个vitess的server。由于设置分库分表的规则&#xff0c;需要使用vtctldclient这个工具&#xff0c;这个工具的摸索费了诸多周折&#xff0c;《vitess使用记录&…...

计算机毕业设计 | SpringBoot+vue健身房管理系统(附源码+论文)

1&#xff0c;研究背景 互联网概念的产生到如今的蓬勃发展&#xff0c;用了短短的几十年时间就风靡全球&#xff0c;使得全球各个行业都进行了互联网的改造升级&#xff0c;标志着互联网浪潮的来临。在这个新的时代&#xff0c;各行各业都充分考虑互联网是否能与本行业进行结合…...

计算机网络-GRE(通用路由封装协议)简介

昨天我们学习了VPN的基本概念&#xff0c;虚拟专用网络在当前企业总部与分支间广泛使用。常用的划分方法为基于协议层次有GRE VPN、IPSec VPN、L2TP VPN、PPTP VPN、SSL VPN等。其实我有考虑该怎么讲&#xff0c;因为在IP阶段好像虚拟专用网络讲得不深&#xff0c;在IE的阶段会…...

汽车渲染领域:Blender 和 UE5 哪款更适用?两者区别?

在汽车渲染领域&#xff0c;选择合适的工具对于实现高质量的视觉效果至关重要。Blender和UE5&#xff08;Unreal Engine 5&#xff09;作为两大主流3D软件&#xff0c;各自在渲染动画方面有着显著的差异。本文将从核心定位与用途、工作流程、渲染技术和灵活性、后期处理与合成四…...

服务器数据恢复—光纤存储FC硬盘数据恢复案例

服务器存储数据恢复环境&#xff1a; 某品牌光纤存储上共有16块FC硬盘。存储上的卷映射到Linux操作系统上。Linux操作系统上运行Oracle数据库。 服务器存储故障&检测&#xff1a; 存储上2块硬盘故障灯亮起&#xff0c;存储映射到linux操作系统上的卷挂载不上&#xff0c;业…...

MySQL系列之远程管理(安全)

导览 前言Q&#xff1a;如何保障远程登录安全一、远程登录的主要方式1. 用户名/口令2. SSH3. SSL/TLS 二、使用TLS协议加密连接1. 服务端2. 客户端 结语精彩回放 前言 在我们的学习或工作过程中&#xff0c;作为开发、测试或运维人员&#xff0c;经常会通过各类客户端软件&…...

硬菜!高精度!BO-Transformer贝叶斯优化编码器多特征分类预测/故障诊断

硬菜&#xff01;高精度&#xff01;BO-Transformer贝叶斯优化编码器多特征分类预测/故障诊断 目录 硬菜&#xff01;高精度&#xff01;BO-Transformer贝叶斯优化编码器多特征分类预测/故障诊断效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.Matlab实现BO-Transform…...

idea_常用设置

相关设置 项目的JDK设置out目录取消自动更新设置主题设置菜单和窗口字体大小滚轮调节字体大小显示行号与方法分隔符代码智能提示忽略大小写自动导包配置设置项目文件编码设置控制台的字符编码修改类头的文档注释信息设置自动编译 项目的JDK设置 File -> Project Structure -…...

C# 中的异步流:高效处理序列数据

C#中的异步流&#xff08;Async Streams&#xff09;。异步流是C# 8.0引入的一个新特性&#xff0c;它允许你异步地处理序列数据&#xff0c;非常适合处理大量数据或长时间运行的任务。以下是一篇关于C#中异步流的文章。 引言 在现代应用程序开发中&#xff0c;处理大量数据或…...

Spring WebFlux SSE(服务器发送事件)的正确用法

在SpringBoot2下SSE实现是返回一个SseEmitter,然后通过SseEmitter的send方法来发送事件. 在SpringBoot3的WebFlux 下SSE实现是返回一个Flux<ServerSentEvent<?>>,但是怎么手动向客户端发送SSE事件搜遍全网也没有看到一个讲清楚的.网上的例子一般都是这样的: GetM…...

pyhton+yaml+pytest+allure框架封装-全局变量渲染

我们在日常测试中 会有一个接口中多个值的情况 比如这种 { "name": "thread", "value": "4986-MainThread", "status": "framework", "start": "pytest", …...