惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

SecWiki News
SecWiki News
I
InfoQ
The Cloudflare Blog
人人都是产品经理
人人都是产品经理
博客园 - Franky
T
Tailwind CSS Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
量子位
博客园_首页
罗磊的独立博客
V
V2EX
李成银的技术随笔
大猫的无限游戏
大猫的无限游戏
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
T
True Tiger Recordings
Vercel News
Vercel News
Cyberwarzone
Cyberwarzone
Cisco Talos Blog
Cisco Talos Blog
F
Fox-IT International blog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
M
Microsoft Research Blog - Microsoft Research
Know Your Adversary
Know Your Adversary
爱范儿
爱范儿
The Register - Security
The Register - Security
G
Google Developers Blog
The Hacker News
The Hacker News
Malwarebytes
Malwarebytes
S
Securelist
博客园 - 三生石上(FineUI控件)
Jina AI
Jina AI
T
Threat Research - Cisco Blogs
T
The Exploit Database - CXSecurity.com
S
SegmentFault 最新的问题
博客园 - 叶小钗
F
Fortinet All Blogs
Apple Machine Learning Research
Apple Machine Learning Research
宝玉的分享
宝玉的分享
博客园 - 聂微东
T
Threatpost
博客园 - 【当耐特】
D
Docker
P
Privacy & Cybersecurity Law Blog
www.infosecurity-magazine.com
www.infosecurity-magazine.com
G
GRAHAM CLULEY
V
Visual Studio Blog
C
Cisco Blogs
IT之家
IT之家
S
Security Archives - TechRepublic
Latest news
Latest news
阮一峰的网络日志
阮一峰的网络日志

蛮荆

如何获取更多的免费服务器 Kubernetes 调度器队列 - 设计与实现 Kubernetes 调度器 - 核心流程 Kubernetes Networking Model & CNI Kubernetes 控制器管理总结 Kubernetes CronJob 设计与实现 Kubernetes Job 设计与实现 Kubernetes HPA 设计与实现 Kubernetes Deployment 滚动更新实现原理 Kubernetes GC 设计与实现 Kubernetes Pod 驱逐 - 设计与实现 Kubernetes Daemonset 设计与实现 Kubernetes ReplicaSet 设计与实现 Kubernetes EndPoint 设计与实现 Kubernetes Informer 设计与实现 降本增效之应用优化 (三) 日志存储与检索 Kubernetes Pod 设计与实现 - 创建流程 Kubernetes 探针设计与实现 Unix 编程艺术名句摘录 Kubernetes - CRI 概述 Golang 编译速度为什么这么快? Kubernetes Pod 设计与实现 - Pause 容器 Kubernetes - kube-proxy 代理模式工程优化 Kubernetes 应用最佳实践 - 优雅关闭长连接 Kubernetes Service 类型和会话亲和性 Kubernetes 为什么需要 Ingress Kubernetes 架构 - 控制平面和数据平面 降本增效之应用优化 (二) 大报表 Go 语言如何获取 CPU 利用率 降本增效之应用优化 (一) Redis 业务规则引擎演变过程简述 微服务中的熔断算法 漏桶算法和令牌桶算法 jsonparser 为什么比标准库的 encoding/json 快 10 倍 ? zap 高性能设计与实现 HTTP Router 算法演进 布谷鸟过滤器 fastcache 高性能设计与实现 Web 常见的三个安全问题 ants Code Reading 布谷鸟过滤器 Go 线程安全 map 方案选型 布隆过滤器 死锁、活锁、饥饿、自旋锁 sync.Pool Code Reading Go 内存管理概述 Go netpoll Code Reading goroutine 泄漏与检测 time/Timer Code Reading GMP Scheduler Code Reading Go channel 的 15 条规则和底层实现 为什么 Linux “一切皆文件” context.Context Code Reading runtime/HACKING.md Goland 最佳实践 互联网开发与金庸武学 为什么 Redis 6.0 引入多线程模型? Kubernetes 应用最佳实践 - 金丝雀发布 容器中如何正确配置 GOMAXPROCS ? singleflight Code Reading sync.Map Code Reading sync.Cond Code Reading sync.WaitGroup Code Reading sync.RWMutex Code Reading sync.Mutex Code Reading sync.Once Code Reading Go 无锁编程 sync/atomic Code Reading goroutine 交替打印奇偶数 GODEBUG Go 并发模式 Go 汇编 UUID 通用技术选型 Kubernetes 应用最佳实践 - 水平自动伸缩 Go 高性能 Tips fasthttp 为什么比标准库 net/http 快 10 倍 ? 技术文章配图指南 ChatGPT 初体验 Docker 网络原理概览 iptables 的五表五链 Kubernetes 应用最佳实践 - 亲和性和污点容忍度 Go 的反射与三大定律 Docker 官方提供的最佳实践 Go 语言内置的设计模式 HTTP1 到 HTTP3 的工程优化 Kubernetes 应用最佳实践 - Sidecar 模式 Kubernetes 应用最佳实践 - init 容器和钩子函数 为什么 recover 必须在 defer 中调用? 为什么 defer 的执行顺序和注册顺序不同? Go map 设计与实现 Go 切片扩容底层实现 Go 语言中的零拷贝 Go Delve 云原生和边缘计算简介 Kubernetes Pod 服务质量等级 Kubernetes 应用最佳实践 - 探针 Kubernetes 应用最佳实践 - 资源请求和限制 CDN 原理 Kubernetes 应用最佳实践 - 开篇 缓存策略和模式
计算机网络中的设计模式
2022-07-25 · via 蛮荆

计算机网络中的设计模式

2022-07-25 计算机网络 设计模式

代理模式

代理模式可以在不改变客户端代码的情况下,通过代理对象来控制对实际对象的访问。

网络中最高频出现的设计模式之一,在传输层之上的应用层使用非常广泛。

  • HTTP 代理
  • DNS 代理
  • 防火墙

伪代码

// 代理处理器伪代码实现
func proxyHandler(w http.ResponseWriter, r *http.Request) {
    // 解析目标服务器 URL
    target, err := url.Parse("https://dbwu.tech/")

    ...

    // 将客户端的请求转发给目标服务器
    proxyReq, err := http.NewRequest(r.Method, ...)

    ...

    // 发送请求到目标服务器
    client := &http.Client{}
    resp, err := client.Do(proxyReq)

    ...

    // 复制目标服务器的响应头
    for key, values := range resp.Header {
        for _, value := range values {
            w.Header().Add(key, value)
        }
    }

    // 设置响应状态码
    w.WriteHeader(resp.StatusCode)

    // 将目标服务器的响应内容复制到客户端响应
    io.Copy(w, resp.Body)
}

func main() {
    // 将代理处理器注册到根路径
    http.HandleFunc("/", proxyHandler)

    // 启动 HTTP 服务器
    log.Fatal(http.ListenAndServe(":8080", nil))
}

装饰者模式

最经典的就是发送方从应用层到物理层的各类协议头部格式,层层包装,接收方从物理层到应用层,反过来,层层解包装。

伪代码

采用 Golang Functional Options 风格来实现。

package main

// 所有协议和装饰器都要实现这个 Packet 接口
type Packet interface {
	GetContent() string
}

// PacketDecorator 装饰器
type PacketDecorator struct {
	packet Packet
	header string
}

func (d *PacketDecorator) GetContent() string {
	return d.header + d.packet.GetContent()
}

// Option 设置 PacketDecorator 的属性
// Functional Options 模式
type Option func(*PacketDecorator)

// WithHeader 负责装饰,也就是各类协议的头部格式包装
func WithHeader(header string) Option {
	return func(d *PacketDecorator) {
		d.header = header
	}
}

// ApplicationLayer 应用层
type ApplicationLayer struct {
	data string
}

func (a *ApplicationLayer) GetContent() string {
	return a.data
}

// TransportLayer 传输层装饰器
func TransportLayer(packet Packet, opts ...Option) Packet {
	decorator := &PacketDecorator{packet: packet}
	for _, opt := range opts {
		opt(decorator)
	}
	return decorator
}

// NetworkLayer 网络层装饰器
func NetworkLayer(packet Packet, opts ...Option) Packet {
	decorator := &PacketDecorator{packet: packet}
	for _, opt := range opts {
		opt(decorator)
	}
	return decorator
}

// DataLinkLayer 数据链路层装饰器
func DataLinkLayer(packet Packet, opts ...Option) Packet {
	decorator := &PacketDecorator{packet: packet}
	for _, opt := range opts {
		opt(decorator)
	}
	return decorator
}

// PhysicalLayer 物理层装饰器
func PhysicalLayer(packet Packet, opts ...Option) Packet {
	decorator := &PacketDecorator{packet: packet}
	for _, opt := range opts {
		opt(decorator)
	}
	return decorator
}

func main() {
	// 创建应用层的数据
	appData := &ApplicationLayer{data: "Hello, World!"}

	// 逐层包装
	transportPkt := TransportLayer(appData, WithHeader("[TCP Header]"))
	networkPkt := NetworkLayer(transportPkt, WithHeader("[IP Header]"))
	dataLinkPkt := DataLinkLayer(networkPkt, WithHeader("[Ethernet Header]"))
	physicalPkt := PhysicalLayer(dataLinkPkt, WithHeader("[Physical Layer Header]"))

	// 打印物理层数据
	println(physicalPkt.GetContent())
}

运行上面的代码,输出如下:

[Physical Layer Header][Ethernet Header][IP Header][TCP Header]Hello, World!

状态模式

典型的例子就是 TCP 协议的实现 (一个复杂的状态机),使用状态模式可以简单地模拟 TCP 的状态机的工作机制,每个状态都可以表示为一个类,并且每个类都有相应的状态转换逻辑。

伪代码

一个完整的 TCP 状态机实现比较复杂,这里以 TCP 三次握手来演示状态模式。

为了节省篇幅,这里只演示 SYN_SENT, SYN_RECEIVED, Established, Closed 4 种 TCP 连接状态。

package main

import (
	"fmt"
)

// TCPState 定义状态行为接口
type TCPState interface {
	Handle(context *TCPConnection)
	String() string
}

// TCPConnection 是状态机上下文
// 包含当前状态机器所处状态
type TCPConnection struct {
	state TCPState
}

func (c *TCPConnection) SetState(state TCPState) {
	c.state = state
}

func (c *TCPConnection) Handle() {
	c.state.Handle(c)
}

func (c *TCPConnection) String() string {
	return c.state.String()
}

// 下面是具体的状态转移和变化过程

// SYN_SENT 代表 TCP SYN_SENT 状态
type SYN_SENT struct{}

// SYN_RECEIVED 代表 TCP SYN_RECEIVED 状态
type SYN_RECEIVED struct{}

// Established 代表 TCP ESTABLISHED 状态
type Established struct{}

// Closed 表示 TCP 连接已关闭状态
type Closed struct{}

func (s *Closed) Handle(context *TCPConnection) {
	fmt.Println("Received SYN, transitioning to SYN_SENT")
	context.SetState(&SYN_SENT{})
}

func (s *Closed) String() string {
	return "CLOSED"
}

func (s *SYN_SENT) Handle(context *TCPConnection) {
	fmt.Println("Received SYN-ACK, transitioning to SYN_RECEIVED")
	context.SetState(&SYN_RECEIVED{})
}

func (s *SYN_SENT) String() string {
	return "SYN_SENT"
}

func (s *SYN_RECEIVED) Handle(context *TCPConnection) {
	fmt.Println("Received ACK, transitioning to ESTABLISHED")
	context.SetState(&Established{})
}

func (s *SYN_RECEIVED) String() string {
	return "SYN_RECEIVED"
}

func (s *Established) Handle(context *TCPConnection) {
	fmt.Println("Connection is already ESTABLISHED")
}

func (s *Established) String() string {
	return "ESTABLISHED"
}

func main() {
	// 默认情况下,连接处于关闭状态
	connection := &TCPConnection{state: &Closed{}}
	fmt.Println("Current State:", connection)
	fmt.Println("--------------------------")

	// 客户端发起建立连接请求,状态转移到 SYN_SENT
	connection.Handle()
	fmt.Println("Current State:", connection)
	fmt.Println("--------------------------")

	// 服务端接收到建立连接请求,状态转移到 SYN_RECEIVED
	connection.Handle()
	fmt.Println("Current State:", connection)
	fmt.Println("--------------------------")

	// 客户端接收到服务端的 ACK,状态转移到 ESTABLISHED
	connection.Handle()
	fmt.Println("Current State:", connection)
	fmt.Println("--------------------------")

	connection.Handle()
}

运行上面的代码,输出如下:

Current State: CLOSED
--------------------------
Received SYN, transitioning to SYN_SENT
Current State: SYN_SENT
--------------------------
Received SYN-ACK, transitioning to SYN_RECEIVED
Current State: SYN_RECEIVED
--------------------------
Received ACK, transitioning to ESTABLISHED
Current State: ESTABLISHED
--------------------------
Connection is already ESTABLISHED

策略模式

策略模式可以将请求的处理逻辑封装到不同的策略类中,并在运行时选择合适的策略来处理请求,使具体的算法处理逻辑可以灵活地扩展和修改。

TCP 协议中的拥塞控制算法、路由选择算法等都可以使用策略模式来确定具体使用哪种算法。

伪代码

package main

import "fmt"

// CongestionControl 定义拥塞控制算法接口
type CongestionControl interface {
	Execute()
}

// Reno 拥塞控制算法实现
type Reno struct{}

func (r *Reno) Execute() {
	fmt.Println("Using Reno Algorithm")
}

// Cubic 拥塞控制算法实现
type Cubic struct{}

func (c *Cubic) Execute() {
	fmt.Println("Using Cubic Algorithm")
}

// BBR 拥塞控制算法实现
type BBR struct{}

func (b *BBR) Execute() {
	fmt.Println("Using BBR Algorithm")
}

// Connection 是连接,可以选择使用具体的算法
type Connection struct {
	strategy CongestionControl
}

// SetStrategy 设置当前的算法
func (c *Connection) SetStrategy(strategy CongestionControl) {
	c.strategy = strategy
}

// Handle 执行当前的拥塞控制算法
func (c *Connection) Handle() {
	c.strategy.Execute()
}

func main() {
	connection := &Connection{}

	// 使用 Reno 拥塞控制算法
	reno := &Reno{}
	connection.SetStrategy(reno)
	connection.Handle()

	// 使用 Cubic 拥塞控制算法
	cubic := &Cubic{}
	connection.SetStrategy(cubic)
	connection.Handle()

	// 使用 BBR 拥塞控制算法
	bbr := &BBR{}
	connection.SetStrategy(bbr)
	connection.Handle()
}

运行上面的代码,输出如下:

Using Reno Algorithm
Using Cubic Algorithm
Using BBR Algorithm

扩展阅读