在负载均衡器后面运行多个 daphne 实例:django-channels

Posted

技术标签:

【中文标题】在负载均衡器后面运行多个 daphne 实例:django-channels【英文标题】:Running multiple instances of daphne behind a load balancer: django-channels 【发布时间】:2018-03-27 15:15:35 【问题描述】:

我正在使用django-channels 为我的应用程序添加HTTP2WebSocket 支持。我找不到很多关于如何扩展频道的文档。下面是我的nginx 配置,它对在同一台机器上运行但端口不同的多个daphne 实例进行负载平衡。这是正确的做法吗?

upstream socket 
    least_conn;
    server 127.0.0.1:9000;
    server 127.0.0.1:9001;
    server 127.0.0.1:9002;
    server 127.0.0.1:9003;


server 
    listen 80;
    server_name 127.0.0.1;

    location = /favicon.ico  access_log off; log_not_found off; 

    location /static/ 
        root /home/niscp/home-screen;
    

    location /nicons/ 
        root /home/niscp/home-screen;
    

    location / 
        include uwsgi_params;
        uwsgi_pass unix:/home/niscp/home-screen/home-screen.sock;
    

    location /ws/ 
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_pass http://socket;
    

除此之外,我还运行workers 的各个实例以通过以下方式收听各个频道:

python manage.py runworker --only-channels=websocket.connect
python manage.py runworker --only-channels=websocket.receive
python manage.py runworker --only-channels=websocket.disconnect

我让uwsgidjango 通常处理它们的方式处理所有http 请求。所有daphneworkers 所做的都是处理WebSocket 请求。 这是扩展django-channels 的可行方法,还是我可以做得更好?

【问题讨论】:

【参考方案1】:

这里有几件事。首先,我认为在不同进程中运行不同类型的请求不会有太大收获。您的断开连接处理程序可能会非常轻松 - 除了清理之外没有做太多事情。 Connect 也可能不会做太多事情,接收将获得大部分负载。

您赌的是使用 --threads 参数并启动多个线程。您当前的设置只会为每种类型的处理程序运行一个线程。

runworker 的工作方式是通过您的通道层(例如 Redis)与 Daphne 进行通信。所有的工人都在听一个队列。当一个请求进来时,一个工作人员会处理它。当该工作人员正在处理请求时,其他工作人员将等待后续请求并处理它们。一旦他们发送了他们的响应,他们就会回去听队列。如果没有指定 --only-channels,每个进程都会拉出请求并尽可能快地处理它们,并且它们都不会等待。

您可以通过运行多个进程和 --threads 参数来找到线程/工作者的最佳平衡。您还可以为繁重的频道预留工作人员,以免他们影响您的网站。

拥有多个 Daphne 实例会有所帮助。但由于他们所做的只是在您的服务器和工作人员之间发送消息,您可能看不到运行 4 个工作人员的好处。

此处所述的所有内容均不适用于 Channels 2。这是针对旧版本的 Django Channels。

【讨论】:

我们正在部署至少 50k 个打开和通信的套接字。所以,我想我们会增加收听更多流量的频道的工人数量。谢谢:) @PiyushDas 你能告诉我你是如何获得 50k 开放和沟通渠道的吗?我们已经有多个 daphnes 和许多 (20-80) 工作人员,但我们的应用程序仍然存在很多扩展问题。你需要优化一些linux内核参数吗?你用 nginx 作为反向代理吗? @AmirHadi 你最好的选择是离开频道 1。频道 2 使用 asyncio。如果您异步编写所有代码并且不编写阻塞事件循环的代码,您应该能够处理数千个连接。您需要小心,因为 Django 中的任何默认缓存或数据库方法都会阻塞事件循环并使您的站点运行速度比运行 Channels 1 时慢。您需要确保使用所有库的异步版本IO 或者将做 IO 的方法包装在 @sync_to_async 装饰器中。 @AmirHadi 是的,我们调整了一些 linux 参数,例如 ulimit 以启用分配文件描述符以打开套接字。除此之外,我们还调整了 2 个我不记得的内核参数。

以上是关于在负载均衡器后面运行多个 daphne 实例:django-channels的主要内容,如果未能解决你的问题,请参考以下文章

KONG API 网关中的负载均衡

如何使 HTTP 调用到达 App Engine 负载平衡器后面的所有实例?

多个 Zuul Gate-gateway 以减少流量

可以将 ip 列入白名单以与 aws 负载均衡器后面的 ec2 实例进行入站通信吗?

Django 频道 daphne 返回 200 状态码

nginx的反向代理功能和负载均衡