Go并发编程案例解析

nginx

influxdb 时序数据库 Prometheus

Grafana

实例代码

https://github.com/itsmikej/imooc_logprocess

常见的并发模型

  • 进程&线程 Apache C10K 服务器要同时支持10K的并发连接
  • 异步非阻塞 (Nginx,Libevent, NodeJs)epoll 复杂度高
  • 协程 GoLang, Erlang, Lua

Golang并发实现

  • 程序并发执行 goroutine
  • 多个goroutine间的数据同步通信channels
  • 多个channel选择数据读取或者写入select

Goroutines

Goroutines 程序并发执行

1foo() // 执行函数foo, 程序等待函数foo返回
2go foo() // 执行函数foo
3bar() // 不用等待foo返回

Channels

Channels多个goroutine间的数据通信与同步

1c := make(chan string) // 创建一个channel
2go func(){
3  time.Sleep(1*time.Second)
4  c <- "message from closure"  // 发送数据到channel 中
5}()
6
7msg:=<- c // 阻塞直到接收到数据

Select

Select 从多个Channel 中读取或写入数据

1select{
2  case v:= <-c1:
3  	fmt.Println("channel 1 sends",v)
4  case v:=<- c2:
5  	fmt.Println("channel 2 sends")
6  default: // 可选
7  	fmt.Println("neither channel was ready") 
8}

并发与并行

Rob Pike Concurrency is not Parallelism

  • 并发: 指同一时刻,系统通过调度,来回切换交替运行的多个任务,“看起来”是同时运行
  • 并行: 执行统一时刻,两个任务“真正的”同时运行

Concurrency: 单核CPU,逻辑上同时执行

Parallelism: 多核CPU,物理上同时执行

![image-20191121193911320](/Users/airren/Library/Application Support/typora-user-images/image-20191121193911320.png)

多个goroutine 并发执行

将复杂的任务拆分,通过goroutine 去并发执行

通过channel做数据通信

Golang 中的面向对象

  • struct 类型
  • inteface
  • 继承、封装、多态

封装

 1type Foo struct{
 2  baz string
 3}
 4
 5func (f *Foo) echo(){  // 接受者  成员函数
 6  fmt.Println(f.baz)
 7}
 8
 9func main(){
10  f := Foo{baz: "hello, struct"}
11  f.echo()
12}

继承

 1type Foo struct{
 2  baz string
 3}
 4
 5type Bar struct{
 6  Foo
 7}
 8
 9func (f *Foo) echo(){  // 接受者  成员函数
10  fmt.Println(f.baz)
11}
12
13func main(){
14  b := Bar{Foo{baz: "hello, struct"}}
15  b.echo()
16}

多态

非侵入式的接口 duck 接口

 1type Foo interface{
 2  qux()
 3}
 4
 5type Bar struct{}
 6type Baz struct{}
 7	
 8func (b *Bar) qux(){}
 9func (b *Baz) qux(){}
10
11func main(){
12	var f Foo
13  f = Bar{}
14  f = Baz{}
15  fmt.Println(f)
16}

2. 日志监控程序的实现

LogProcess

读取模块实现

  • 打开文件
  • 从文件末尾开始逐行读取
  • 写入read channel

解析模块的实现

提取数据中有价值的信息

  • 从Read Channel 中读取每行日志数据
  • 正则提取所需的监控数据(path, status, method 等)
  • 写入Write channel

写入模块的实现

  • 初始化influxDB client
  • 从write channel中读取监控数据
  • 构造数据并写入influxDB

InfluxDB 简介:

influxdb是一个开源的时序型的数据库,使用Go语言编写,被广泛应用于存储系统的监控数据,IoT行业的试试数据等场景。有以下特性。

  • 部署简单,无外部依赖
  • 内置http支持,使用http读写
  • 类sql的灵活查询(max, min, sum 等)

Influx db关键概念

  • database : 数据库
  • measurement:数据库中的表
  • points: 表里面的一行数据
    • tags 各种有索引的属性
    • fields 各种记录的值
    • time 数据记录的时间戳, 也是自动生成的主索引

image-20191122171646907

分析监控需求

某个协议下的某个请求在某个请求方法的 QPS& 响应时间& 流量

**Tags:**Path 、Method、Scheme、Status Fields: UpstreamTime, RequestTime,ByteSent TIme: TimeLocal

5. 绘制监控图

6. 监控模块的实现

  1. 总处理日志的行数
  2. 系统吞吐量
  3. read channel 长度
  4. write channel 长度
  5. 运行总时间
  6. 错误数量

并发的基础知识

并行和并发的区别

Golang 面向对象

并发编程的思路

模块化编程