Я использую сервер сокетов, который использует ThreadingMixIn
, чтобы сделать его неблокирующим. Сервер работает хорошо, он может обрабатывать сотни соединений одновременно без каких-либо проблем. Моя проблема начинается с SqlAlchemy
, который помогает запрашивать и обновлять мою базу данных. После того, как клиент отправляет сообщение (каждую секунду) на мой сервер, я должен сделать два запроса и одно обновление в моей базе данных. Два запроса очень просты, а таблица небольшая, обновление более проблематично c, здесь я должен обновить по Id (Id таблицы проиндексирован в моей базе данных), и таблица содержит тысячи строк. Проблема возникает, когда 200 клиентов подключаются к моему серверу, хотя мой сценарий может обрабатывать как чтение, так и запись, но после 200 подключений простаивает и время отклика начинает замедляться. Я отслеживаю его с помощью tcptrack
и вижу, что среднее время простоя увеличивается с 0-1 с до 2-3 с. Мои запросы и обновления выполняются быстро, но после 200 соединений эти запросы замедляются . Я также измеряю время выполнения в коде, и я заметил, что t1
увеличивается до 2 с пару раз от среднего 0,005 с. Я прилагаю свой упрощенный код.
Пример моего краткого кода:
from config_file import *
import os
import sys
from http.server import BaseHTTPRequestHandler, HTTPServer
import socketserver
import select
from models import Users, Model1, Model2
from base_db import Session, engine, Base, conn
class MyHandler(BaseHTTPRequestHandler):
def __init__(self, request, address, server):
BaseHTTPRequestHandler.__init__(self, request, address, server)
def do_GET(self):
while True:
readable, writable, exceptional = select.select([self.rfile], [self.wfile], [self.rfile, self.wfile])
try:
for s in readable:
s.readline()
try:
t0 = time.time()
session = Session()
model_data_1 = session.query(Model1).filter_by(id=1)
model_data_2 = session.query(Model2).filter_by(foo=False).all()
session.query(Users).filter_by(id=111).update({'test1' : 21, 'test2': 0, 'test3': "FIX", "timstamp": datetime.datetime.utcnow() })
t1 = time.time() - t0
except:
session.rollback()
finally:
session.close()
for s in writable:
session = Session()
try:
self.model_data_2 = session.query(Model2).filter_by(type="test").first()
except:
session.rollback()
finally:
session.close()
if self.model_data_2:
time.sleep(1)
s.write(self.model_data_2.data)
except Exception as e:
print (e)
class MyServer(socketserver.ThreadingMixIn, HTTPServer):
pass
if __name__ == '__main__':
httpd = MyServer((HOST, PORT), MyHandler)
try:
httpd.allow_reuse_address = True
httpd.serve_forever()
except KeyboardInterrupt:
pass
httpd.server_close()
conn.close()
По конфигурации базы данных:
import sqlalchemy as db
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, scoped_session
from config_file import *
engine = db.create_engine("postgresql://" + DB_AUTH_USER +
":" + DB_AUTH_PASSWD + "@" + DB_HOST_PORT + "/" + DB_NAME)
conn = engine.connect()
session_factory = sessionmaker(bind=engine)
Session = scoped_session(session_factory)
Base = declarative_base()
Мой вопрос почему замедляется среднее время выполнения после 200 соединений? Мои запросы быстрые, но по какой-то причине они начинают замедляться, или мои потоки делают это замедление? Заранее большое спасибо!