网络层设计
概述
本文档描述了 Garnet 服务器的网络层是如何设计的,以及它用于执行网络操作以与客户端通信的各种类。
初始化时,GarnetServer 实例化 GarnetServerTcp 对象以处理传入的网络连接。其 Start
方法在 GarnetServer 启动时调用,绑定到配置中指定的 IP 地址和端口(请参阅配置页面),并开始接受来自客户端的新连接。它还将 AcceptEventArg_Completed
注册为接收新连接时要调用的回调函数。
当接受新连接时调用的 AcceptEventArg_Completed
方法通过创建新的 ServerTcpNetworkHandler
对象并使用 HandleNewConnection
方法将其添加到 activeHandlers 字典中来处理新连接。
网络处理器
ServerTcpNetworkHandler
执行以下步骤来接收和处理传入数据。
- 实例化时,分配网络缓冲区内存以接收数据。
- 网络缓冲区是使用由
LimitedFixedBufferPool
类管理的内存池分配的。有关详细信息,请参阅LimitedFixedBufferPool。 - 分配的网络缓冲区配置为直接从网络接收数据。
- 它(通过基类 TcpNetworkHandlerBase)将
RecvEventArg_Completed
注册为从套接字接收数据的回调方法。 - 此外,根据是否启用 TLS 加密,使用
SslStream.AuthenticateAsServerAsync
方法执行客户端服务器身份验证来验证 SSL 连接。
基类 NetworkHandler
提供处理网络通信的功能,包括通过网络连接发送和接收数据。该类的主要部分
- 类的构造函数初始化各种字段和属性,包括服务器钩子、网络发送器、网络缓冲区池、TLS 相关字段和日志记录器。它还根据是否启用 TLS 设置网络和传输接收缓冲区。
Start
和StartAsync
方法用于启动网络处理器,包括如果启用 TLS 的身份验证阶段。这些方法采用可选参数,例如 TLS 选项和远程端点名称。它们内部调用 AuthenticateAsServerAsync 或 AuthenticateAsClientAsync 方法来执行身份验证。AuthenticateAsServerAsync
和AuthenticateAsClientAsync
方法处理 TLS 连接的身份验证过程。它们使用 sslStream 对象执行身份验证并建立安全连接。这些方法还处理读取身份验证后剩余的任何额外字节。- 当从网络接收到数据时,会调用
OnNetworkReceive
方法。此方法负责处理接收到的数据。它首先检查 TLS 读取器的状态,并对网络和传输接收缓冲区执行必要的转换。然后,它调用Process
方法来处理接收到的数据。 Process
方法负责处理接收到的数据。它检查传输接收缓冲区中是否有数据以及是否有可用的消息消费者。如果有,它会尝试通过调用TryProcessRequest
方法来处理请求。消息消费者负责根据线协议检索会话提供程序 - ASCII 是当前唯一支持的格式。会话提供程序在 Garnet 服务器初始化时已注册。然后使用检索到的会话提供程序创建新的会话对象(如果尚不存在)。为了处理消息,GarnetProvider
类被注册为会话提供程序,并用于创建RespServerSession
类的对象以处理 RESP 消息。- 该类还执行其他操作,例如缓冲区管理、缓冲区移动、记录安全信息和释放资源。
GarnetTcpNetworkSender
GarnetTcpNetworkSender 类是一个 TCP 网络发送器,它继承自 NetworkSenderBase
类。它负责通过 TCP 连接发送网络数据以响应消息给客户端。这作为 ServerTcpNetworkHandler
对象的创建的一部分被实例化。
- 它使用以前创建用于接受连接的套接字将响应发送回客户端。
- 该类使用
GarnetSaeaBuffer
对象堆栈来管理可重用的发送缓冲区。这些缓冲区是使用类型为LimitedFixedBufferPool
的 networkPool 字段创建的。这些缓冲区用于存储要通过网络发送的数据。 - 该类使用节流来限制并发发送的数量。它有一个 throttleCount 字段来跟踪正在进行的发送数量,以及一个 throttle 信号量来控制并发发送的最大数量。
使用 LimitedFixedBufferPool 的网络内存池
LimitedFixedBufferPool
类是一个内存池实现,它提供不同大小的内存段池。它旨在高效地管理内存分配和释放,以提高在需要频繁内存分配和释放操作的场景中的性能。它通过使用并发队列数组来实现这一点。每个并发队列代表特定大小范围的内存段。该类提供从池中分配和释放内存段的方法。
LimitedFixedBufferPool
类被设计为线程安全的,可以在多线程场景中使用。- 该池内部使用并发队列来管理内存段,确保高效的分配和释放操作。
- 该池支持大小为二的幂且大于或等于最小分配大小的内存段。
LimitedFixedBufferPool
类是可处置的,不再需要时应将其处置以释放已分配的内存段。
Get
方法从池中为请求的大小分配一个内存段。它返回一个表示已分配内存段的 PoolEntry
对象。
Return
方法将内存段返回到池中以供重用。
PoolEntry 类
LimitedFixedBufferPool 类内部使用 PoolEntry 类来表示内存段。PoolEntry 类提供重用和管理已分配内存段的方法。