Go语言并发模式视角思考
作者:mmseoamin日期:2024-02-04

Go语言并发模式视角思考,在这里插入图片描述,第1张

犹记得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:网络流量抓包和重放工具

            码云上项目

            • 1、项目名称:基于 Go 实现的高性能代理服务器,项目地址:https://gitee.com/snail/proxy
            • 2、项目名称:基于 Go 实现的 Git 服务,项目地址:https://gitee.com/Unknown/gogs
            • 3、项目名称:基于 Go 开发的开源文库系统,项目地址:https://gitee.com/truthhun/DocHub
            • 4、项目名称:基于 Go 实现的内网穿透 ,项目地址:https://gitee.com/wapai/chuantou
            • 5、项目名称:基于 Go 实现的 Web 开发框架,项目地址:https://gitee.com/johng/gf
            • 6、项目名称:基于 Go 实现的高性能爬虫,基于go_spider开发

              接下来介绍下关于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,如此反复。