Уведомления

Группа в Telegram: @pythonsu
  • Начало
  • » Network
  • » Оцените схему работы событийно-ориентированного сервера [RSS Feed]

#1 Фев. 11, 2010 23:01:55

Danfocus
От:
Зарегистрирован: 2010-02-11
Сообщения: 6
Репутация: +  0  -
Профиль   Отправить e-mail  

Оцените схему работы событийно-ориентированного сервера

Пишу сервер на питоне 2.6 с использованием epoll
Наваял следующую конструкцию.

import select
import Queue
import socket
from threading import Thread


connections = {}
qq = Queue.Queue()
epoll = select.epoll()


class Connection(object):
def __init__(self, connection):
self.connection = connection
self.fileno = None
self.q = Queue.Queue()


class handlerThread(Thread):
def run(self):
while True:
idata, fileno = qq.get()
if idata:

odata = '\x00' # something

connections[fileno].q.put(odata)
if not connections[fileno].q.empty():
epoll.modify(fileno, select.EPOLLIN | select.EPOLLOUT)


def main():
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serversocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
serversocket.bind(('0.0.0.0', 31337))
serversocket.listen(5)
serversocket.setblocking(0)
serversocket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)

epoll.register(serversocket.fileno(), select.EPOLLIN)

try:
while True:
events = epoll.poll(1)
for fileno, event in events:
if fileno == serversocket.fileno():
connection, address = serversocket.accept()
connection.setblocking(0)
connections[connection.fileno()] = Connection(connection)
connections[connection.fileno()].fileno = connection.fileno()

odata = '\x00' # something

connections[connection.fileno()].q.put(odata)
epoll.register(connection.fileno(), select.EPOLLIN | select.EPOLLOUT)
elif event & select.EPOLLIN:
idata = connections[fileno].connection.recv(8192)
if not idata:
epoll.modify(fileno, 0)
try:
connections[fileno].connection.shutdown(socket.SHUT_RDWR)
except:
pass
else:
qq.put((idata, fileno))
elif event & select.EPOLLOUT:
if not connections[fileno].q.empty():
qsize = connections[fileno].q.qsize()
while (qsize):
odata = connections[fileno].q.get()
connections[fileno].connection.send(odata)
qsize -= 1
if connections[fileno].q.empty():
epoll.modify(fileno, select.EPOLLIN)
elif event & select.EPOLLHUP:
epoll.unregister(fileno)
connections[fileno].connection.close()
del connections[fileno]
elif event & select.EPOLLERR:
print "Error connection: ", fileno
finally:
epoll.unregister(serversocket.fileno())
epoll.close()
serversocket.close()

if __name__ == '__main__':
handlerThread().start()
main()
Все вроде работает, но не покидает ощущение, что где-то перемудрил.
Прошу оценить и дать советы(заключения).

P.S. это мой первый серьезный проект на питоне - прошу сильно не бить.



Отредактировано (Фев. 12, 2010 08:47:11)

Офлайн

#2 Фев. 12, 2010 00:04:03

Андрей Светлов
От:
Зарегистрирован: 2007-05-15
Сообщения: 3137
Репутация: +  14  -
Профиль   Адрес электронной почты  

Оцените схему работы событийно-ориентированного сервера

а зачем поток понадобился?



Офлайн

#3 Фев. 12, 2010 00:05:55

Danfocus
От:
Зарегистрирован: 2010-02-11
Сообщения: 6
Репутация: +  0  -
Профиль   Отправить e-mail  

Оцените схему работы событийно-ориентированного сервера

В поток сбрасываются полученные данные от клиента и там они разбираются и формируется ответ.
По задумке - основной цикл в это время дальше обрабатывает соединения.



Офлайн

#4 Фев. 12, 2010 00:07:22

Ferroman
От:
Зарегистрирован: 2006-11-16
Сообщения: 2759
Репутация: +  1  -
Профиль   Отправить e-mail  

Оцените схему работы событийно-ориентированного сервера

Как по мне - вроде бы нормально, код читабельный. Что ещё нужно, кроме обработчиков исключений? Но я в queue глупый.

Офлайн

#5 Фев. 12, 2010 00:16:46

Danfocus
От:
Зарегистрирован: 2010-02-11
Сообщения: 6
Репутация: +  0  -
Профиль   Отправить e-mail  

Оцените схему работы событийно-ориентированного сервера

Интересуют мнения - полезен здесь будет отдельный поток с передачей данных ему через Queue и возврат ответа через реквизит класса соединения (Connection.q) ?
И нужна в таком количестве модификация событий для epoll, а то где не посмотришь примеры - везде смотрят только select.EPOLLIN и сразу отправляют ответ без проверки select.EPOLLOUT ?



Офлайн

#6 Фев. 12, 2010 00:44:05

Lexander
От:
Зарегистрирован: 2008-09-19
Сообщения: 1139
Репутация: +  33  -
Профиль   Отправить e-mail  

Оцените схему работы событийно-ориентированного сервера

А почему не пул потоков?
Почему нет ограничения на кол-во подключаемых клиентов?

Что будет делать 1000-й клиент, если одновременно присоединится 1000 клиентов? Ждать, пока 1 поток обработает 999 клиентов?
Какова вероятность, что клиент отвалится по таймауту?
Я не спец по epoll, у вас есть в коде обработка этой ситуации (таймаут)?



Офлайн

#7 Фев. 12, 2010 00:59:58

Danfocus
От:
Зарегистрирован: 2010-02-11
Сообщения: 6
Репутация: +  0  -
Профиль   Отправить e-mail  

Оцените схему работы событийно-ориентированного сервера

Lexander
А почему не пул потоков?
Потому что - мне сначала надо понять - есть проигрыш или выигрыш этой схемы - тогда и буду расширять.

Lexander
Почему нет ограничения на кол-во подключаемых клиентов?
Это же просто схема - порезана, чтоб просто запуститься.

Lexander
Что будет делать 1000-й клиент, если одновременно присоединится 1000 клиентов? Ждать, пока 1 поток обработает 999 клиентов?
По идее - схема даже без потока обработки должна легко выдерживать 1к соединений.

Lexander
Какова вероятность, что клиент отвалится по таймауту?
Я не спец по epoll, у вас есть в коде обработка этой ситуации (таймаут)?
Вот здесь - глухо, из-за неполной реализации epoll в питоне. Но у меня из-за специфичности задачи - клиент обязан периодически посылать keep-alive, так что думаю решать это скорее всего сохранением таймстампа и проверки его отдельным потоком.

P.S. Хотя судя по всему эта ситуация должна обработаться этим кодом:
if event & select.EPOLLIN:
idata = connections[fileno].connection.recv(8192)
if not idata:
epoll.modify(fileno, 0)
connections[fileno].connection.shutdown(socket.SHUT_RDWR)



Отредактировано (Фев. 12, 2010 01:08:12)

Офлайн

#8 Фев. 12, 2010 03:54:00

Андрей Светлов
От:
Зарегистрирован: 2007-05-15
Сообщения: 3137
Репутация: +  14  -
Профиль   Адрес электронной почты  

Оцените схему работы событийно-ориентированного сервера

Глянул, как twisted это делает. Второго потока, конечно, нет. Кривость epoll решается написанием _epoll.pyx



Отредактировано (Фев. 12, 2010 03:54:23)

Офлайн

#9 Фев. 12, 2010 08:25:54

Lexander
От:
Зарегистрирован: 2008-09-19
Сообщения: 1139
Репутация: +  33  -
Профиль   Отправить e-mail  

Оцените схему работы событийно-ориентированного сервера

Danfocus
Мои вопросы - из разряда “наводящие на мысль” для самостоятельной оценки работы, не более того :)



Офлайн

  • Начало
  • » Network
  • » Оцените схему работы событийно-ориентированного сервера[RSS Feed]

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version