Skip to content

Commit a7fba9d

Browse files
committed
doc: add tcpdump blog.
1 parent 0e97e97 commit a7fba9d

File tree

2 files changed

+168
-0
lines changed

2 files changed

+168
-0
lines changed

docs/zh/_sidebar.md

+1
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@
107107
- [蚂蚁云原生应用运行时的探索和实践 - ArchSummit 上海](zh/blog/exploration-and-practice-of-antcloud-native-application-runtime-archsummit-shanghai.md)
108108
- [MOSN子项目Layotto:开启服务网格+应用运行时新篇章](zh/blog/mosn-subproject-layotto-opening-a-new-chapter-in-service-grid-application-runtime/index.md)
109109
- [源码解析 7层流量治理,接口限流](zh/blog/flowcontrol_code_analyze.md)
110+
- [源码解析 4层流量治理,tcp流量dump](zh/blog/tcpcopy_code_analyze.md)
110111
- 演讲视频
111112
- [Service Mesh落地之后:为 sidecar 注入灵魂](zh/video/inject-soul-into-sidecar.md)
112113
- [MOSN子项目Layotto:开启服务网格+应用运行时新篇章](zh/video/a-new-chapter-in-service-mesh-application-runtime.md)

docs/zh/blog/tcpcopy_code_analyze.md

+167
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
# 源码解析 4层流量治理,tcp流量dump
2+
3+
>作者简介:
4+
>龚中强,是开源社区的爱好者,致力于拥抱开源。
5+
>
6+
>写作时间: 2022年4月26日
7+
8+
9+
## Overview
10+
此文档的目的在于分析 tcp 流量 dump 的实现
11+
12+
## 前提:
13+
文档内容所涉及代码版本如下
14+
15+
[https://github.com/mosn/layotto](https://github.com/mosn/layotto)
16+
17+
Layotto 0e97e970dc504e0298017bd956d2841c44c0810b(main分支)
18+
19+
## 源码分析
20+
21+
### 代码均在: [tcpcopy代码](https://github.com/mosn/layotto/tree/main/pkg/filter/network/tcpcopy)
22+
23+
### model.go分析
24+
此类是 tcpcopy 的配置对象的核心类
25+
26+
```go
27+
type DumpConfig struct {
28+
Switch string `json:"switch"` // dump 开关.配置值:'ON' 或 'OFF'
29+
Interval int `json:"interval"` // dump 采样间隔, 单位: 秒
30+
Duration int `json:"duration"` // 单个采样周期, 单位: 秒
31+
CpuMaxRate float64 `json:"cpu_max_rate"` // cpu 最大使用率。当超过此阈值,dump 功能将停止
32+
MemMaxRate float64 `json:"mem_max_rate"` // mem 最大使用率。当超过此阈值,dump 功能将停止
33+
}
34+
35+
type DumpUploadDynamicConfig struct {
36+
Unique_sample_window string // 指定采样窗口
37+
BusinessType _type.BusinessType // 业务类型
38+
Port string // 端口
39+
Binary_flow_data []byte // 二进制数据
40+
Portrait_data string // 用户上传的数据
41+
}
42+
```
43+
44+
### persistence.go分析
45+
此类是 tcpcopy 的 dump 持久化核心处理类
46+
47+
```go
48+
// 该方法在 tcpcopy.go 中 OnData 中调用
49+
func IsPersistence() bool {
50+
// 判断 dump 开关是否开启
51+
if !strategy.DumpSwitch {
52+
if log.DefaultLogger.GetLogLevel() >= log.DEBUG {
53+
log.DefaultLogger.Debugf("%s the dump switch is %t", model.LogDumpKey, strategy.DumpSwitch)
54+
}
55+
return false
56+
}
57+
58+
// 判断是否在采样窗口中
59+
if atomic.LoadInt32(&strategy.DumpSampleFlag) == 0 {
60+
if log.DefaultLogger.GetLogLevel() >= log.DEBUG {
61+
log.DefaultLogger.Debugf("%s the dump sample flag is %d", model.LogDumpKey, strategy.DumpSampleFlag)
62+
}
63+
return false
64+
}
65+
66+
// 判断是否 dump 功能停止(获取系统负载判断处理器和内存是否超过 tcpcopy 的阈值,如果超过则停止)
67+
if !strategy.IsAvaliable() {
68+
if log.DefaultLogger.GetLogLevel() >= log.DEBUG {
69+
log.DefaultLogger.Debugf("%s the system usages are beyond max rate.", model.LogDumpKey)
70+
}
71+
return false
72+
}
73+
74+
return true
75+
}
76+
77+
// 根据配置信息持久化数据
78+
func persistence(config *model.DumpUploadDynamicConfig) {
79+
// 1.持久化二进制数据
80+
if config.Binary_flow_data != nil && config.Port != "" {
81+
if GetTcpcopyLogger().GetLogLevel() >= log.INFO {
82+
GetTcpcopyLogger().Infof("[%s][%s]% x", config.Unique_sample_window, config.Port, config.Binary_flow_data)
83+
}
84+
}
85+
if config.Portrait_data != "" && config.BusinessType != "" {
86+
// 2. 持久化用户定义的数据
87+
if GetPortraitDataLogger().GetLogLevel() >= log.INFO {
88+
GetPortraitDataLogger().Infof("[%s][%s][%s]%s", config.Unique_sample_window, config.BusinessType, config.Port, config.Portrait_data)
89+
}
90+
91+
// 3. 增量持久化内存中的配置信息的变动内容
92+
buf, err := configmanager.DumpJSON()
93+
if err != nil {
94+
if log.DefaultLogger.GetLogLevel() >= log.DEBUG {
95+
log.DefaultLogger.Debugf("[dump] Failed to load mosn config mem.")
96+
}
97+
return
98+
}
99+
// 3.1. 如果数据变化则 dump
100+
tmpMd5ValueOfMemDump := common.CalculateMd5ForBytes(buf)
101+
memLogger := GetMemLogger()
102+
if tmpMd5ValueOfMemDump != md5ValueOfMemDump ||
103+
(tmpMd5ValueOfMemDump == md5ValueOfMemDump && common.GetFileSize(getMemConfDumpFilePath()) <= 0) {
104+
md5ValueOfMemDump = tmpMd5ValueOfMemDump
105+
if memLogger.GetLogLevel() >= log.INFO {
106+
memLogger.Infof("[%s]%s", config.Unique_sample_window, buf)
107+
}
108+
} else {
109+
if memLogger.GetLogLevel() >= log.INFO {
110+
memLogger.Infof("[%s]%+v", config.Unique_sample_window, incrementLog)
111+
}
112+
}
113+
}
114+
}
115+
```
116+
117+
### tcpcopy.go分析
118+
此类为是 tcpcopy 的核心类。
119+
120+
```go
121+
// 向 Mosn 注册 NetWork
122+
func init() {
123+
api.RegisterNetwork("tcpcopy", CreateTcpcopyFactory)
124+
}
125+
126+
// 返回 tcpcopy 工厂
127+
func CreateTcpcopyFactory(cfg map[string]interface{}) (api.NetworkFilterChainFactory, error) {
128+
tcpConfig := &config{}
129+
// dump 策略转静态配置
130+
if stg, ok := cfg["strategy"]; ok {
131+
...
132+
}
133+
// TODO extract some other fields
134+
return &tcpcopyFactory{
135+
cfg: tcpConfig,
136+
}, nil
137+
}
138+
139+
// 供 pkg/configmanager/parser.go 调用添加或者更新Network filter factory
140+
func (f *tcpcopyFactory) Init(param interface{}) error {
141+
// 设置监听的地址和端口配置
142+
...
143+
return nil
144+
}
145+
146+
// 实现的是 ReadFilter 的 OnData 接口,每次从连接拿到数据都进方法进行处理
147+
func (f *tcpcopyFactory) OnData(data types.IoBuffer) (res api.FilterStatus) {
148+
// 判断当前请求数据是否需要采样 dump
149+
if !persistence.IsPersistence() {
150+
return api.Continue
151+
}
152+
153+
// 异步的采样 dump
154+
config := model.NewDumpUploadDynamicConfig(strategy.DumpSampleUuid, "", f.cfg.port, data.Bytes(), "")
155+
persistence.GetDumpWorkPoolInstance().Schedule(config)
156+
return api.Continue
157+
}
158+
```
159+
160+
161+
最后我们再来回顾一下整体流程走向:
162+
163+
1. 从 tcpcopy.go 的初始化函数init() 开始,程序向 CreateGRPCServerFilterFactory 传入 CreateTcpcopyFactory.
164+
165+
2. Mosn 创建出一个filter chain(代码位置[factory.go](https://github.com/mosn/mosn/tree/master/pkg/filter/network/proxy/factory.go)) ,通过循环调用CreateFilterChain将所有的filter加入到链路结构包括本文的 tcpcopy.
166+
167+
3. 当流量通过 mosn 将会进入到 tcpcopy.go 的 OnData 方法进行 tcpdump 的逻辑处理.

0 commit comments

Comments
 (0)