Linux下几种并发服务器的实现模式(详解)
在Linux系统中,实现高并发服务器是非常常见的任务。本文将详细讲解几种常见的实现模式。
多进程模式
多进程模式是最基本的并发服务器实现方式之一。其中,服务器主进程负责监听并接收客户端连接,客户端请求被分配给一个新的子进程进行处理。
优点:
- 相对于单进程模式,能够更好地利用多核CPU。
- 子进程之间互相独立,不容易相互影响。
缺点:
- 内存使用量比较大,需要为每个子进程申请独立的内存空间。
- 每个子进程的创建和销毁都需要一定的时间,不够灵活。
示例代码:
import socket
import os
SERVER_ADDRESS = ('localhost', 8888)
def server_forever():
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
server_socket.bind(SERVER_ADDRESS)
server_socket.listen(128)
while True:
client_socket, client_address = server_socket.accept()
pid = os.fork()
if pid == 0: # 子进程
server_socket.close()
handle_request(client_socket)
client_socket.close()
os._exit(0) # 无需通过sys.exit()方法退出
client_socket.close() # 父进程不需要与客户端通信,关闭客户端套接字
def handle_request(client_socket):
"""处理客户端请求"""
data = client_socket.recv(1024)
response = b'HTTP/1.1 200 OK\r\nConnection: close\r\n\r\nHello, world!'
client_socket.sendall(response)
多线程模式
多线程模式是目前较为流行的并发服务器实现方式之一。其中,服务器主线程负责监听并接收客户端连接,将客户端请求分配给一个新的子线程进行处理。
优点:
- 相对于多进程模式,线程用的内存空间更少。
- 子线程的创建和销毁速度更快,更灵活。
缺点:
- Python中的全局解释器锁(GIL)可能会导致并发度不高。
示例代码:
import socket
import threading
SERVER_ADDRESS = ('localhost', 8888)
def server_forever():
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
server_socket.bind(SERVER_ADDRESS)
server_socket.listen(128)
while True:
client_socket, client_address = server_socket.accept()
t = threading.Thread(target=handle_request, args=(client_socket,))
t.start()
def handle_request(client_socket):
"""处理客户端请求"""
data = client_socket.recv(1024)
response = b'HTTP/1.1 200 OK\r\nConnection: close\r\n\r\nHello, world!'
client_socket.sendall(response)
client_socket.close()
事件驱动模式
事件驱动模式是一种高效的并发服务器实现方式,它通过使用事件循环来处理并发请求,同时避免了多进程和多线程模式中创建和销毁子进程或子线程的开销。
优点:
- 能够处理大量的并发请求,同时避免了多进程和多线程模式中的开销。
- 对于I/O密集型的任务表现良好。
缺点:
- 对于CPU密集型任务表现不佳。
示例代码:
import socket
import select
SERVER_ADDRESS = ('localhost', 8888)
def server_forever():
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
server_socket.bind(SERVER_ADDRESS)
server_socket.listen(128)
inputs = [server_socket] # 用于select的输入对象
outputs = [] # 用于select的输出对象
message_queues = {} # 存储每个连接上待发送的消息队列
while inputs:
readable, writable, exceptional = select.select(inputs, outputs, inputs)
for sock in readable:
if sock is server_socket:
# 新的客户端连接
client_socket, client_address = server_socket.accept()
inputs.append(client_socket)
message_queues[client_socket] = []
else:
# 从已经连接的客户端读取输入
data = sock.recv(1024)
if data:
message_queues[sock].append(data)
if sock not in outputs:
outputs.append(sock)
else:
# 客户端连接关闭
if sock in outputs:
outputs.remove(sock)
inputs.remove(sock)
sock.close()
del message_queues[sock]
for sock in writable:
# 将待发送的消息发送给已连接的客户端
try:
data = message_queues[sock].pop(0)
except IndexError:
outputs.remove(sock)
else:
sock.send(data)
for sock in exceptional:
# 处理错误的连接
inputs.remove(sock)
if sock in outputs:
outputs.remove(sock)
sock.close()
del message_queues[sock]
总之,在Linux下实现高并发服务器有许多不同的方式。通过选择适当的实现模式,您可以实现出性能良好、可靠且易于维护的高并发服务器。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Linux下几种并发服务器的实现模式(详解) - Python技术站