Go语言高并发实战案例分析

embedded/2025/1/1 12:58:23/

目录

  1. 基础案例:简单的并发下载器
  2. 进阶案例:高并发网站访问统计
  3. 实战案例:分布式任务调度系统

基础案例:简单的并发下载器

问题描述

需要同时下载多个文件,使用并发方式提高下载效率。

实现代码

package mainimport ("fmt""io""net/http""os""sync"
)func downloadFile(url string, filename string, wg *sync.WaitGroup) {defer wg.Done()// 创建HTTP请求resp, err := http.Get(url)if err != nil {fmt.Printf("下载 %s 失败: %v\n", filename, err)return}defer resp.Body.Close()// 创建文件file, err := os.Create(filename)if err != nil {fmt.Printf("创建文件 %s 失败: %v\n", filename, err)return}defer file.Close()// 写入文件_, err = io.Copy(file, resp.Body)if err != nil {fmt.Printf("写入文件 %s 失败: %v\n", filename, err)return}fmt.Printf("文件 %s 下载完成\n", filename)
}func main() {urls := []string{"https://example.com/file1.zip","https://example.com/file2.zip","https://example.com/file3.zip",}var wg sync.WaitGroupfor i, url := range urls {wg.Add(1)filename := fmt.Sprintf("file%d.zip", i+1)go downloadFile(url, filename, &wg)}wg.Wait()fmt.Println("所有文件下载完成")
}

关键点解析

  1. 使用sync.WaitGroup管理并发下载任务
  2. 每个下载任务在独立的goroutine中执行
  3. 使用defer确保资源正确释放
  4. 基本的错误处理机制

进阶案例:高并发网站访问统计

问题描述

需要统计网站的实时访问量,包括总访问次数、独立IP数等指标。

实现代码

package mainimport ("fmt""net/http""sync""time"
)type VisitStats struct {mutex       sync.RWMutextotalVisits int64uniqueIPs   map[string]boollastMinute  map[int64]int64 // 按秒记录最近一分钟的访问量
}func NewVisitStats() *VisitStats {return &VisitStats{uniqueIPs:  make(map[string]bool),lastMinute: make(map[int64]int64),}
}func (vs *VisitStats) recordVisit(ip string) {vs.mutex.Lock()defer vs.mutex.Unlock()// 更新总访问量vs.totalVisits++// 记录唯一IPvs.uniqueIPs[ip] = true// 记录当前秒的访问量now := time.Now().Unix()vs.lastMinute[now]++// 清理一分钟前的数据vs.cleanOldData(now)
}func (vs *VisitStats) cleanOldData(now int64) {for timestamp := range vs.lastMinute {if now-timestamp > 60 {delete(vs.lastMinute, timestamp)}}
}func (vs *VisitStats) getStats() (int64, int, int64) {vs.mutex.RLock()defer vs.mutex.RUnlock()// 计算最近一分钟的访问量var lastMinuteVisits int64now := time.Now().Unix()for timestamp, count := range vs.lastMinute {if now-timestamp <= 60 {lastMinuteVisits += count}}return vs.totalVisits, len(vs.uniqueIPs), lastMinuteVisits
}func main() {stats := NewVisitStats()// 处理访问请求http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {ip := r.RemoteAddrstats.recordVisit(ip)fmt.Fprintf(w, "Welcome!")})// 定期打印统计信息go func() {for {total, unique, lastMin := stats.getStats()fmt.Printf("总访问量: %d, 唯一IP数: %d, 最近一分钟访问量: %d\n",total, unique, lastMin)time.Sleep(5 * time.Second)}}()http.ListenAndServe(":8080", nil)
}

关键点解析

  1. 使用读写锁sync.RWMutex提高并发性能
  2. 通过map记录唯一IP和时间戳数据
  3. 实现了滑动窗口统计最近一分钟的访问量
  4. 定期清理过期数据

实战案例:分布式任务调度系统

问题描述

实现一个支持高并发的分布式任务调度系统,具备任务分发、执行和监控功能。

实现代码

package mainimport ("context""fmt""sync""time"
)// 任务定义
type Task struct {ID       stringPayload  interface{}Priority int
}// 工作节点
type Worker struct {ID     stringStatus stringTasks  chan Task
}// 调度器
type Scheduler struct {workers    map[string]*WorkertaskQueue  chan TaskworkerPool chan *Workermutex      sync.RWMutexctx        context.Contextcancel     context.CancelFunc
}func NewScheduler(workerCount int) *Scheduler {ctx, cancel := context.WithCancel(context.Background())s := &Scheduler{workers:    make(map[string]*Worker),taskQueue:  make(chan Task, 1000),workerPool: make(chan *Worker, workerCount),ctx:        ctx,cancel:     cancel,}// 初始化工作节点for i := 0; i < workerCount; i++ {worker := &Worker{ID:     fmt.Sprintf("worker-%d", i),Status: "idle",Tasks:  make(chan Task, 10),}s.workers[worker.ID] = workers.workerPool <- worker}return s
}func (s *Scheduler) Start() {// 任务分发go func() {for {select {case <-s.ctx.Done():returncase task := <-s.taskQueue:worker := <-s.workerPools.assignTask(worker, task)}}}()// 监控工作节点状态go s.monitorWorkers()
}func (s *Scheduler) assignTask(worker *Worker, task Task) {s.mutex.Lock()worker.Status = "busy"s.mutex.Unlock()go func() {worker.Tasks <- task// 模拟任务执行time.Sleep(time.Second * time.Duration(task.Priority))s.mutex.Lock()worker.Status = "idle"s.mutex.Unlock()s.workerPool <- worker}()
}func (s *Scheduler) monitorWorkers() {ticker := time.NewTicker(5 * time.Second)defer ticker.Stop()for {select {case <-s.ctx.Done():returncase <-ticker.C:s.mutex.RLock()for id, worker := range s.workers {fmt.Printf("Worker %s status: %s\n", id, worker.Status)}s.mutex.RUnlock()}}
}func main() {scheduler := NewScheduler(5)scheduler.Start()// 模拟提交任务go func() {for i := 0; i < 20; i++ {task := Task{ID:       fmt.Sprintf("task-%d", i),Payload:  fmt.Sprintf("payload-%d", i),Priority: i % 3 + 1,}scheduler.taskQueue <- tasktime.Sleep(time.Millisecond * 500)}}()// 运行一段时间后退出time.Sleep(time.Second * 30)scheduler.cancel()
}

关键点解析

  1. 使用context管理goroutine生命周期
  2. 实现了工作池模式提高资源利用率
  3. 使用channel实现任务队列和工作节点池
  4. 采用读写锁保护共享资源
  5. 实现了基本的监控功能
  6. 支持任务优先级

总结

通过这三个案例,我们循序渐进地展示了Go语言在并发编程中的应用:

  1. 基础案例展示了goroutine和WaitGroup的基本用法
  2. 进阶案例引入了更复杂的并发控制和数据结构
  3. 实战案例整合了多个并发特性,实现了一个完整的系统

在实际开发中,需要注意:

  • 正确使用锁机制避免竞态条件
  • 合理设计channel缓冲区大小
  • 注意goroutine的生命周期管理
  • 实现适当的错误处理和资源清理
  • 考虑系统的可扩展性和维护性

http://www.ppmy.cn/embedded/149920.html

相关文章

Redis篇--应用篇3--数据统计(排行榜,计数器)

由于 Redis 的原子操作&#xff0c;它非常适合用于计数器&#xff0c;例如统计网站的访问量、点赞数等。 如投票&#xff0c;计算评分&#xff0c;根据评分来决定如何排序和展示。 如果需要防止重复投票&#xff0c;可以使用一个SET集合存储用户id与投票用户id。 如果想要实现…

`we_chat_union_id IS NOT NULL` 和 `we_chat_union_id != ‘‘` 这两个条件之间的区别

文章目录 1、什么是空字符串&#xff1f;2、两个引号之间加上空格 好的&#xff0c;我们来详细解释一下 we_chat_union_id IS NOT NULL 和 we_chat_union_id ! 这两个条件之间的区别&#xff0c;以及它们在 SQL 查询中的作用&#xff1a; 1. we_chat_union_id IS NOT NULL 含…

Java:基于springboot妇幼健康管理系统

作者主页&#xff1a;IT 小舟 简介&#xff1a;Java领域优质创作者、Java项目、学习资料、技术互助 文中获取源码 项目介绍 本妇幼健康管理系统分为管理员、用户、医生三个权限。 管理员可以管理用户、医生的基本信息内容&#xff0c;可以管理药物信息以及患者预约信息等操作…

今天你学C++了吗?——C++中的模板

♥♥♥~~~~~~欢迎光临知星小度博客空间~~~~~~♥♥♥ ♥♥♥零星地变得优秀~也能拼凑出星河~♥♥♥ ♥♥♥我们一起努力成为更好的自己~♥♥♥ ♥♥♥如果这一篇博客对你有帮助~别忘了点赞分享哦~♥♥♥ ♥♥♥如果有什么问题可以评论区留言或者私信我哦~♥♥♥ ✨✨✨✨✨✨ 个…

NVR小程序接入平台EasyNVR视频监控技术如何助力餐饮行业实现明厨亮灶

在当今社会&#xff0c;食品安全问题日益受到公众的关注。为了提升餐饮企业的管理水平和透明度&#xff0c;确保消费者能够放心用餐&#xff0c;越来越多的餐饮企业开始采用视频监控技术来实现“明厨亮灶”。 食品安全是顾客、卫生管理部门最为关心的&#xff0c;而视频监控技术…

Kafka高性能设计

高性能设计概述 Kafka高性能是多方面协同的结果&#xff0c;包括集群架构、分布式存储、ISR数据同步及高效利用磁盘和操作系统特性等。主要体现在消息分区、顺序读写、页缓存、零拷贝、消息压缩和分批发送六个方面。 消息分区 存储不受单台服务器限制&#xff0c;能处理更多数据…

Hive其十,优化和数据倾斜

目录 Hive优化 1、开启本地模式 2、explain分析SQL语句 3、修改Fetch操作 4、开启hive的严格模式【提高了安全性】 5、JVM重用 6、分区、分桶以及压缩 7、合理设置map和reduce的数量 合理设置map数量&#xff1a; 设置合理的reducer的个数 8、设置并行执行 9、CBO优…

windows上设置svn忽略

目的 就是在windows环境下设置svn的需要忽略的文件&#xff0c;这还是挺实用的一个功能&#xff0c;不然&#xff0c;很多编译的中间文件都上传到svn上了&#xff0c;这样就不好了&#xff1b;ignore设置&#xff0c;也需要注意一下。 过程 svn服务端式忽略&#xff0c;这是常…