Go语言并发模式视角思考

犹记得2019年中旬进行知识点的学习和demo的练习,熟悉各种语法和并发调度的场景,

在2019年末开始参与项目实战开发和逻辑梳理

Go语言的接触也是更多探索和业务的拆件,做一些雏形工具,来慢慢的孵化业务生态

后来陆陆续续,在主营业务是PHP的情况下,尽量在业务脚本的倾向上使用Go语言,虽然前期两种语言的混合使用,总会导致写法冲突,但好在这个磨合期平稳度过。

后来也会将公司更多的业务倾向于Go来进行处理,比如新项目,或者老项目对并发要求高的项目会优先考虑。

罗列下Go语言的特点:

Go主要有静态语言、天生并发、内置GC、安全性高、语法简单、交叉编译和编译快速这几个方面的特性。

这些特性决定了Go的三个高富帅特性:运行快、开发快和部署快,而这些特性都是针对Google遇到的一些痛点来设计的。

优势

  • Go天生的自带并发调度,如协程和通道,且协程内存占用少,一个Goroutine栈空间最小2K
  • Go自带的格式统一,gofmt工具
  • Go语法的简洁,可读性强,严格语言规范
  • Go作为静态语言,编译效率高,性能相对高
  • Go跨平台的编译使用,跟操作shell命令一样的调用,部署方便,目前很多脚本都是这么来做的。
  • 丰富的内置类型,内置强大的工具
  • 内置runtime,自动垃圾回收机制

不足

  • 错误处理,会有错误难获取
  • 基于github获取代码库,会存在有代码库下架问题

Go适合做什么

  • 服务器编程,如:处理日志,数据打包,虚拟机处理,文件系统
  • 分布式系统,数据库代理器
  • 网络编程,如:Web应用、API应用、下载应用
  • 内存数据库
  • 云平台,Docker,Kubernetes等应用开发

GO语言的关键特性主要包括以下几方面:

  • 并发与协程
  • 基于消息传递的通信方式
  • 丰富实用的内置数据类型
  • 函数多返回值
  • defer机制
  • 反射(reflect)
  • 高性能HTTP Server
  • 工程管理
  • 编程规范

Go成功的项目

  • Go成功的项目nsq:bitly开源的消息队列系统,性能非常高,目前他们每天处理数十亿条的消息
  • docker:基于lxc的一个虚拟打包工具,能够实现PAAS平台的组建。
  • packer:用来生成不同平台的镜像文件,例如VM、vbox、AWS等,作者是vagrant的作者
  • skynet:分布式调度框架
  • Doozer:分布式同步工具,类似ZooKeeper
  • Heka:mazila开源的日志处理系统
  • cbfs:couchbase开源的分布式文件系统
  • tsuru:开源的PAAS平台,和SAE实现的功能一模一样
  • groupcache:memcahe作者写的用于Google下载系统的缓存系统
  • god:类似redis的缓存系统,但是支持分布式和扩展性
  • gor:网络流量抓包和重放工具

码云上项目

接下来介绍下关于Go的并发相关的内容

Go 调度器实现机制

Go 调度器模型我们通常叫做G-P-M 模型,他包括 4 个重要结构,分别是G、P、M、Sched:

G:Goroutine,每个 Goroutine 对应一个 G 结构体,G 存储 Goroutine 的运行堆栈、状态以及任务函数,可重用。

G 并非执行体,每个 G 需要绑定到 P 才能被调度执行。

P: Processor,表示逻辑处理器,对 G 来说,P 相当于 CPU 核,G 只有绑定到 P 才能被调度。

对 M 来说,P 提供了相关的执行环境(Context),如内存分配状态(mcache),任务队列(G)等。

P 的数量决定了系统内最大可并行的 G 的数量(前提:物理 CPU 核数 >= P 的数量)。

P 的数量由用户设置的 GoMAXPROCS 决定,但是不论 GoMAXPROCS 设置为多大,P 的数量最大为 256。

M: Machine,OS 内核线程抽象,代表着真正执行计算的资源,在绑定有效的 P 后,进入 schedule 循环;

而 schedule 循环的机制大致是从 Global 队列、P 的 Local 队列以及 wait 队列中获取。

M 的数量是不定的,由 Go Runtime 调整,为了防止创建过多 OS 线程导致系统调度不过来,目前默认最大限制为 10000 个。

M 并不保留 G 状态,这是 G 可以跨 M 调度的基础。

Sched:Go 调度器,它维护有存储 M 和 G 的队列以及调度器的一些状态信息等。

调度器循环的机制大致是从各种队列、P 的本地队列中获取 G,切换到 G 的执行栈上并执行 G 的函数,调用 Goexit 做清理工作并回到 M,如此反复。

相关推荐
呼Lu噜20 分钟前
WPF-遵循MVVM框架创建图表的显示【保姆级】
前端·后端·wpf
bing_15825 分钟前
为什么选择 Spring Boot? 它是如何简化单个微服务的创建、配置和部署的?
spring boot·后端·微服务
小臭希27 分钟前
Java——琐碎知识点一
java·开发语言
张帅涛_66627 分钟前
golang goroutine(协程)和 channel(管道) 案例解析
jvm·golang·go
学c真好玩38 分钟前
Django创建的应用目录详细解释以及如何操作数据库自动创建表
后端·python·django
Asthenia041238 分钟前
GenericObjectPool——重用你的对象
后端
Piper蛋窝1 小时前
Go 1.18 相比 Go 1.17 有哪些值得注意的改动?
后端
excel1 小时前
招幕技术人员
前端·javascript·后端
盖世英雄酱581361 小时前
什么是MCP
后端·程序员
淋一遍下雨天1 小时前
Spark Streaming核心编程总结(四)
java·开发语言·数据库