面试题答案
一键面试架构设计
- 多线程或多进程模型:
- 多线程:为每个客户端连接分配一个线程来处理。主线程负责监听新连接,一旦有新连接到来,就创建一个新线程处理该连接的通信。优点是编程相对简单,缺点是线程上下文切换开销较大,在高并发时性能会受影响。
- 多进程:每个客户端连接由一个独立进程处理。进程间相互独立,稳定性较好,但进程创建和销毁开销大,进程间通信复杂。
- I/O多路复用模型:
- 使用
select
、poll
或epoll
(Linux系统)等I/O多路复用技术。主线程通过这些机制同时监听多个客户端连接的I/O事件。例如epoll
,它采用事件驱动方式,当有事件发生时才通知程序进行处理,相比select
和poll
,在高并发场景下性能更高,因为它避免了遍历所有文件描述符的开销。
- 使用
避免网络拥塞
- 流量控制:
- 滑动窗口协议:服务端和客户端通过协商窗口大小来控制数据发送量。发送方在未收到接收方确认信息前,最多可发送窗口大小的数据量。接收方根据自身接收能力调整窗口大小,并通过ACK包告知发送方。这样可以避免发送方发送数据过快导致接收方缓冲区溢出。
- 拥塞控制:
- 慢启动:开始时,服务端以一个较小的拥塞窗口(通常为1个MSS,即最大段大小)发送数据。每收到一个ACK,拥塞窗口就增加1个MSS。当拥塞窗口达到慢启动阈值(ssthresh)时,进入拥塞避免阶段。
- 拥塞避免:在这个阶段,每收到一个往返时间(RTT)内的所有ACK,拥塞窗口增加1。如果发生超时或收到重复ACK,就认为网络出现拥塞,调整慢启动阈值和拥塞窗口,进入慢启动或快速重传阶段。
- 快速重传:当收到3个或更多重复ACK时,认为某个数据包丢失,不等超时就重传该数据包,并调整拥塞窗口和慢启动阈值。
提高I/O性能
- 使用非阻塞I/O:
- 将Socket设置为非阻塞模式,这样在执行I/O操作(如
read
、write
)时,如果数据未准备好,函数不会阻塞当前线程或进程,而是立即返回一个错误码。通过I/O多路复用机制,程序可以在等待数据的同时处理其他连接的I/O事件,提高整体的I/O效率。
- 将Socket设置为非阻塞模式,这样在执行I/O操作(如
- 缓冲区优化:
- 接收缓冲区:合理设置接收缓冲区大小,避免过小导致数据丢失,过大则浪费内存。采用环形缓冲区可以提高数据处理的连续性,减少内存拷贝。
- 发送缓冲区:同样要设置合适大小,并且可以采用批量发送的方式,将多个小数据合并成一个大数据块发送,减少网络开销。
确保数据可靠传输
- TCP协议自身机制:
- 校验和:TCP在发送数据时会计算校验和,并将其放入TCP首部。接收方在收到数据后重新计算校验和,与首部中的校验和进行对比,若不一致则丢弃该数据包,要求发送方重传。
- 序列号和确认号:每个TCP数据包都有一个序列号,接收方通过确认号告知发送方已成功接收的数据序列号,发送方根据确认号和序列号判断哪些数据需要重传,保证数据按序到达。
- 应用层确认机制:
- 在应用层可以实现额外的确认机制。例如,客户端发送数据后,服务端处理完成后返回一个自定义的确认消息。客户端若在一定时间内未收到确认消息,则重发数据。这样可以在TCP协议之上进一步确保数据的可靠传输,尤其适用于对数据准确性要求极高的应用场景。
可能用到的技术和算法总结
- 技术:
- 多线程/多进程编程:处理并发连接。
- I/O多路复用(select、poll、epoll):高效监听多个连接的I/O事件。
- 非阻塞I/O:提高I/O操作的效率。
- 算法:
- 滑动窗口协议:实现流量控制。
- 慢启动、拥塞避免、快速重传:实现拥塞控制。