Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

420
Vistas
Respuesta lenta de E/S de socket al usar Docker

Tengo una aplicación web integrada en Flask donde se capturan los tweets (usando la biblioteca Tweepy) y se muestran en el front-end. Usé Socket IO para mostrar los tweets en vivo en el front-end.

Mi código funciona bien cuando ejecuto esto localmente. Los tweets aparecen al instante.

Sin embargo, cuando dockericé la aplicación web, el front-end no se actualiza inmediatamente. Se tarda un poco en mostrar los cambios (a veces creo que los tweets se pierden por la lentitud)

A continuación se muestran extractos de código de mi sitio web:

fortsocket.js

 $(document).ready(function () { /************************************/ /*********** My Functions ***********/ /************************************/ function stream_active_setup() { $("#favicon").attr("href", "/static/icons/fortnite-active.png"); $("#stream-status-ic").attr("src", "/static/icons/stream-active.png"); $("#stream-status-text").text("Live stream active"); } function stream_inactive_setup() { $("#favicon").attr("href", "/static/icons/fortnite-inactive.png"); $("#stream-status-ic").attr("src", "/static/icons/stream-inactive.png"); $("#stream-status-text").text("Live stream inactive"); } /*********************************/ /*********** My Events ***********/ /*********************************/ // Socket connection to server // Prometheus //var socket = io.connect('http://104.131.173.145:8083'); // Local var socket = io.connect(window.location.protocol + '//' + document.domain + ':' + location.port); // Heroku //var socket = io.connect('https://fortweet.herokuapp.com/'); // Send a hello to know // if a stream is already active socket.on('connect', () => { socket.emit('hello-stream', 'hello-stream'); }); // Listene for reply from hello socket.on('hello-reply', function (bool) { if (bool == true) { stream_active_setup() } else { stream_inactive_setup() } }); // Listens for tweets socket.on('stream-results', function (results) { // Insert tweets in divs $('#live-tweet-container').prepend(` <div class="row justify-content-md-center mt-3"> <div class="col-md-2"> <img width="56px" height="56px" src="${results.profile_pic !== "" ? results.profile_pic : "/static/icons/profile-pic.png"}" class="mx-auto d-block rounded" alt=""> </div> <div class="col-md-8 my-auto"> <div><b>${results.author}</b></div> <div>${results.message}</div> </div> </div> `); }); // Listener for when a stream of tweets starts socket.on('stream-started', function (bool) { if (bool == true) { stream_active_setup() } }); // Listener for when a stream of tweets ends socket.on('stream-ended', function (bool) { if (bool == true) { stream_inactive_setup() } }); });

iniciar .py

 # Create the app app = create_app() # JWT Configurations jwt = JWTManager(app) # Socket IO socketio = SocketIO(app, cors_allowed_origins="*") # CORS CORS(app) app.config["CORS_HEADERS"] = "Content-Type" # Creates default admins and insert in db create_default_admin() # Main error handlers @app.errorhandler(404) # Handling HTTP 404 NOT FOUND def page_not_found(e): return Err.ERROR_NOT_FOUND # Listen for hello emit data # from client @socketio.on("hello-stream") def is_stream_active(hello_stream): emit("hello-reply", streamer.StreamerInit.is_stream_active(), broadcast=True)

streamer.py

 import time import tweepy import threading as Coroutine import app.messages.constants as Const import app.setup.settings as settings_mod import app.models.tweet as tweet_mod import app.services.logger as logger import app class FStreamListener(tweepy.StreamListener): def __init__(self): self.start_time = time.time() self.limit = settings_mod.TwitterSettings.get_instance().stream_time logger.get_logger().debug("Live capture has started") # Notify client that a live capture will start app.socketio.emit( "stream-started", True, broadcast=True, ) super(FStreamListener, self).__init__() def on_status(self, status): if (time.time() - self.start_time) < self.limit: # Create tweet object forttweet = tweet_mod.TweetModel( status.source, status.user.name, status.user.profile_background_image_url_https, status.text, status.created_at, status.user.location, ) # Emit to socket app.socketio.emit( "stream-results", { "profile_pic": forttweet.profile_pic, "author": forttweet.author, "message": forttweet.message, }, broadcast=True, ) # Add to database forttweet.insert() return True else: logger.get_logger().debug("Live capture has ended") # Notify client that a live capture has ended app.socketio.emit( "stream-ended", True, broadcast=True, ) # Stop the loop of streaming return False def on_error(self, status): logger.get_logger().debug(f"An error occurred while fetching tweets: {status}") raise Exception(f"An error occurred while fetching tweets: {status}") class StreamerInit: # [Private] Twitter configurations def __twitterInstantiation(self): # Get settings instance settings = settings_mod.TwitterSettings.get_instance() # Auths auth = tweepy.OAuthHandler(settings.consumer_key, settings.consumer_secret,) auth.set_access_token( settings.access_token, settings.access_token_secret, ) # Get API api = tweepy.API(auth) # Live Tweets Streaming myStreamListener = FStreamListener() myStream = tweepy.Stream(auth=api.auth, listener=myStreamListener) myStream.filter(track=settings.filters) def start(self): for coro in Coroutine.enumerate(): if coro.name == Const.FLAG_TWEETS_LIVE_CAPTURE: return False stream = Coroutine.Thread(target=self.__twitterInstantiation) stream.setName(Const.FLAG_TWEETS_LIVE_CAPTURE) stream.start() return True @staticmethod def is_stream_active(): for coro in Coroutine.enumerate(): if coro.name == Const.FLAG_TWEETS_LIVE_CAPTURE: return True return False

El streamer.py se llama al hacer clic en un botón

Dockerfile

 # Using python 3.7 in Alpine FROM python:3.6.5-stretch # Set the working directory to /app WORKDIR /app # Copy the current directory contents into the container at /app ADD . /app RUN apt-get update -y && apt-get upgrade -y && pip install -r requirements.txt # Run the command ENTRYPOINT ["uwsgi", "app.ini"] #ENTRYPOINT ["./entry.sh"]

docker-compose.yml

 version: "3.8" services: fortweet: container_name: fortweet image: mervin16/fortweet:dev build: ./ env_file: - secret.env networks: plutusnet: ipv4_address: 172.16.0.10 expose: - 8083 restart: always nginx_fortweet: image: nginx container_name: nginx_fortweet ports: - "8083:80" networks: plutusnet: ipv4_address: 172.16.0.100 volumes: - ./nginx/nginx.conf:/etc/nginx/conf.d/default.conf depends_on: - fortweet restart: always networks: plutusnet: name: plutus_network driver: bridge ipam: driver: default config: - subnet: 172.16.0.0/24 gateway: 172.16.0.1

app.ini

 [uwsgi] module = run:app master = true processes = 5 # Local & Prometheus http-socket = 0.0.0.0:8083 http-websockets = true chmod-socket = 660 vacuum = true die-on-term = true

Para obtener un código completo y actualizado, puede encontrarlo aquí en la rama dev/mervin

Cualquier ayuda es apreciada.

over 4 years ago · Santiago Trujillo
2 Respuestas
Responde la pregunta

0

Lamentablemente, no puedo reproducir el problema sin la configuración, por lo que no puedo verificar mi respuesta.

Pude encontrar un problema similar en el blog de JP: problemas de rendimiento con Flask y Docker

En resumen, es posible que tener configuraciones de IPv6 e IPv4 en el contenedor esté causando el problema. Para verificar el problema:

  1. Ejecutar la ventana acoplable
  2. Vaya dentro del contenedor en ejecución y cambie el archivo de hosts para que no asigne IPv6 a localhost
  3. Ejecute la aplicación nuevamente dentro del contenedor

Si la aplicación funciona sin problemas, entonces ha identificado su problema. La solución sería modificar los parámetros de uwsgi.

Lo que hizo el autor en la publicación del blog:

CMD uwsgi -s /tmp/uwsgi.sock -w project:app --chown-socket=www-data:www-data --enable-threads & nginx -g 'daemon off;'

over 4 years ago · Santiago Trujillo Denunciar

0

para ver si ipv6 es responsable, le sugiero que apague todo

abra /etc/sysctl.conf y agregue las siguientes líneas para deshabilitar ipv6

 net.ipv6.conf.all.disable_ipv6=1 net.ipv6.conf.default.disable_ipv6=1 net.ipv6.conf.lo.disable_ipv6=1

ejecute sudo sysctl -p para que los cambios surtan efecto

inicia nginx y la ventana acoplable de nuevo

si no ve ninguna diferencia, simplemente puede cambiar la configuración a 0 y volver a ejecutar sysctl -p y hágamelo saber

over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda