百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

从零开始开发一个实时博客(开发一个博客需要什么技术)

cac55 2024-09-21 13:27 19 浏览 0 评论

后台回复【入门资料】

送你十本Python电子书

本文作者为何世友,科技媒体【爱范儿】的CTO。这是他在前年写的一篇介绍Django Channels 使用的教程,基本思路值得大家参考,但是要注意接口可能有变化,请以最新文档为准。

最终效果

ASGI 、Django Channels 简介

ASGI 的完整说明我在去年做了一个翻译。ASGI 由 Django 团队提出,为了解决在一个网络框架里(如 Django)同时处理 HTTPHTTP2、WebSocket 协议。为此,Django 团队开发了 Django Channels 插件,为 Django 带来了 ASGI 能力。

在 ASGI 中,将一个网络请求划分成三个处理层面,最前面的一层,interface server(协议处理服务器),负责对请求协议进行解析,并将不同的协议分发到不同的 Channel(频道);频道属于第二层,通常可以是一个队列系统。频道绑定了第三层的 Consumer(消费者)。

比如说,HTTP 协议的频道绑定了 HTTP 的消费者,当有新的 HTTP 请求过来时,interface server 将该请求分发到 HTTP 频道,HTTP 频道绑定的 HTTP 消费者对该请求进行处理,将处理结果返回给 HTTP 频道,最终传回给客户端。

下面,我们用一个实例演示下这种能力。完整源码在 Github-heshiyou/livelog: A Django Channels example project to demonstrate the ASGI use case.。

实时博客的实现

第一步:跑起来

本例基于 Python 3.5.1、macOS 10.12.4 beta 5,理论上 Python 2.7、Linux 可以跑起来(测试工作请自行认领)。

安装依赖:pip install-r requirements.txt

requirements.txt 如下:

  1. django

  2. channels

  3. asgi_redis

  4. feedparser

新建 Django 项目:django-admin startproject livelog。在 settings.py 里面,将channels添加到 INSTALLED_APPS,再加上基础的 channels 相关配置:

  1. ...

  2. INSTALLED_APPS = (

  3. ...

  4. 'channels',

  5. )

  6. ...

  7. # Redis

  8. REDIS_OPTIONS = {

  9. 'HOST': '127.0.0.1',

  10. 'PORT': 6379,

  11. 'DB': 0

  12. }

  13. USE_REDIS = True

  14. # Channel settings

  15. CHANNEL_LAYERS = {

  16. "default": {

  17. "BACKEND": "asgi_redis.RedisChannelLayer",

  18. "CONFIG": {

  19. "hosts": ['redis://{}:{}'.format(REDIS_OPTIONS['HOST'],

  20. REDIS_OPTIONS['PORT'])]

  21. },

  22. "ROUTING": "livelog.routing.channel_routing"

  23. }

  24. }

注意到使用了 Redis 来做为 Channels 的 Backend。使用 Redis 是为了跨进程的消息处理,为了简便(不需要跨进程),也可以使用 In Memory Channel Layer。接着,我们在 livelog app 目录下添加一个 routing.py 文件,用以配置 channel 路由,现在可以留空:

  1. channel_routing =

现在,通过以下命令即可跑起来我们的第一个 ASGI Server。

  1. # run following commands in command line separately

  2. redis-server /usr/local/etc/redis.conf

  3. python manage.py runserver

可以看到和普通的 Django app server 的启动方式没什么两样,这归功于 Django Channels 封装。实际工作中,要拆解为三个单独的启动步骤:

  1. daphne livelog.asgi:channel_layer --port 8080//daphne 是 asgi interface sever 的一种实现

  2. python manage.py runworker // 启动 ASGI consumer worker

  3. python manage.py runserver --noasgi --noworker // 启动原始的 WSGI server,不运行 ASGI interface server、worker

第二步:处理 WebSocket

Channels 将 WebSocket 连接映射到三个不同到频道:

  • 当一个新的客户端通过 WebSocket 连接时, websocket.connect频道将收到一条消息,在本例中,将在此频道将新用户添加到实时博客订阅组里。

  • 当一个客户端断开连接, websocket.disconnect频道将收到一条消息。

  • 每一条消息都将被发往 websocket.receive频道,在这个频道里。

首先,我们需要将我们的处理逻辑绑定到这三个频道。

在 livelog app 目录中,添加 comsumers.py 文件:

  1. ...

  2. defws_connect(message):

  3. message.reply_channel.send({'accept': True})

  4. Group(const.GROUP_NAME).add(message.reply_channel)


  5. defws_disconnect(message):

  6. Group(const.GROUP_NAME).discard(message.reply_channel)


  7. defws_receive(message):

  8. pass

在本例中,使用 WSGI 也即原生 Django 提供 http 服务。在 routing.py 文件中,将逻辑绑定到路由:

  1. ...

  2. channel_routing = [

  3. route('websocket.connect', ws_connect),

  4. route('websocket.disconnect', ws_disconnect),

  5. route('websocket.receive', ws_receive)

  6. ]

ws_connect频道中,做了两件事:

  1. 建立 WebSocket 连接;

  2. 将新用户添加到群组里,后面我们将该群组作为实时博客的订阅组,对它发送新的消息。

ws_disconnect频道中,将断开连接的用户移出群组。在ws_receive频道中,暂时什么也不做,因为本例中,我们不通过被动接受新消息的方式来更新博客。为了较为全面地展示 ASGI 的能力,本例中,我们使用 Background worker(后台进程)来主动更新博客,并给群组用户推送新消息。

第三步:推送消息

更新实时博客的方式有很多种,在这里我们使用一个 RSS Feed 作为内容源,对该内容源定时抓取,将新内容更新到博客中,以此来做一个演示。在此之前,介绍一个 Django 的小特性,这个特性将允许我们这么运行我们自己的后台进程:

python manage.py bloggingworker // bloggingworker 是我们自定义的命令

这个特新就是 Django 的自定义命令

具体做法在此不赘述,看文档或看本例完整源码即可得知。下面我们回到正事儿上:

blogging_worker.py

  1. # -*- coding: utf-8 -*-

  2. ...

  3. classCommand(BaseCommand):

  4. """

  5. Command to start blogging worker from command line.

  6. """

  7. help = 'Fetch and parse RSS feed and send over channel'


  8. defhandle(self, *args, **options):

  9. rc = redis.Redis(host=settings.REDIS_OPTIONS['HOST'],

  10. port=settings.REDIS_OPTIONS['PORT'],

  11. db=settings.REDIS_OPTIONS['DB'])

  12. rc.delete(const.GROUP_NAME) # flush live blogs

  13. whileTrue:

  14. feed = feedparser.parse(const.IFANR_FEED_URL)

  15. forentryinfeed.get('entries')[::-1]:

  16. ifnotrc.hexists(const.GROUP_NAME, entry.get('id')):

  17. Group(const.GROUP_NAME).send({'text': json.dumps(entry)})

  18. rc.hset(const.GROUP_NAME, entry.get('id'), json.dumps(entry))

  19. logger.debug('send a message %s ' % entry.get('title'))

  20. time.sleep(5)

这个文件里的大量写法都是 Django 约束的,所以不必过分追究,我们看 handle 方法,在这里,我们做这么几件事:

  1. 从爱范儿的 RSS Feed 获取最新的文章,对每一文章,检查这篇文章是否已经发送过,如果没有发送过,则将该文章发送给群组;

  2. 在 redis 中,新建一个名为 liveblog(这个常量存储在 const.GROUP_NAME) 的哈希表,将每篇未被发送过的新文章添加到该哈希表中,这样就可以判断一篇文章是否曾经被发送过;

  3. Group(const.GROUP_NAME).send({'text':json.dumps(entry)})对群组进行新消息的发送;

  4. 每次发送之后,休息 5 秒钟。

第四步:接收新消息并渲染

我们已经有了一个永不停歇的博客更新服务在运行着,一旦有新的内容,这个服务将为用户推送。现在,我们需要一个页面来渲染呈现新消息。

在 templates 目录下,新建 blog.html 文件:

  1. <!DOCTYPE html>

  2. <htmllang="en">

  3. ...

  4. <divid="container">

  5. <h2>Live Blog</h2>

  6. <ulid="log">


  7. </ul>

  8. </div>


  9. <scripttype="application/javascript">

  10. varws_scheme = window.location.protocol == "https:" ? "wss" : "ws";

  11. varws =newWebSocket(ws_scheme + '://' + window.location.host + window.location.pathname);

  12. console.log(ws);

  13. ws.onmessage = function(message) {

  14. vardata = JSON.parse(message.data);

  15. varlogList = document.querySelector('#log');

  16. varlogItem = document.createElement('li');


  17. varitemTmp = `

  18. <h3>${data.title}</h3>

  19. <p>

  20. <date>${newDate(data.published).toLocaleString}</date>

  21. <span>${data.source.title}</span>

  22. </p>

  23. `;

  24. logItem.innerHTML = itemTmp;

  25. logList.insertBefore(logItem, logList.firstChild);

  26. }


  27. </script>

  28. </body>

  29. </html>

在这个页面里,有一个 WebSocket Client 将被新建,并向服务器发起建立连接的请求。当有新消息,将在 #logul 中插入新的消息。接下来就是传统 Django 的工作:

  1. 在 urls.py 中配置 django view 的路由: url(r'blog/

,livelog.views.livelog,name='livelog')

  • 在 views.py 中新增一个名为 livelog 的 view: deflivelog(request):returnrender(request,'blog.html'),渲染模板,响应 http 请求。

  • 到此,一个主动更新博客内容并将新消息推送给每位在线的用户的服务就完成了。

    References

    • ASGI 异步服务网关接口规范

    • Django Channels Get Started

    • Finally, Real-Time Django Is Here: Get Started with Django Channels

    • Raspberry PI and Django Channels

    原文链接:https://blog.ernest.me/post/asgi-demonstration-realtime-blogging

    题图:pexels,CC0 授权。

    相关推荐

    终于,你可以在 iPhone 上玩《饥荒》了

    继七月登陆iPad平台后,冒险生存游戏《饥荒》(Don'tStarve)经过两个月时间终于更新并适配了iPhone,此前我已就游戏在iPad上的表现写过详尽评测和上手攻略,故本文不再对游...

    2025年最适合Macbook新手掌握的5个免费工具,效率立马飙升!

    刚入手Macbook是否觉得操作不熟?担心新手期过长难以熟练提高效率?别担心!本文精选五款国区AppStore免费可下载的官方认证工具,所有选择均基于新手核心痛点与迁移成本考量,解决「系统维护」「操作...

    苹果iOS 13.4和iPadOS 13.4正式更新,支持鼠标、键盘操作

    智东西(公众号:zhidxcom)编|王颖智东西3月25日消息,苹果今天向用户推送了iOS13.4和iPadOS13.4系统更新通知。iPadOS13.4增加了对iPad鼠标和触控板的支持,...

    苹果即将发布macOS 15 用户界面将迎来重大革新

    苹果公司计划于6月举行的全球开发者大会(WWDC)上,震撼发布全新的macOS15操作系统。据CNMO最新报道,此次更新将彻底革新“菜单和应用程序用户界面”的排列方式,为用户带来全新的使用体验。ma...

    **Bartender 5:菜单栏管理神器**(菜单栏工具)

    提供免费下载网站Mavom.cn**Bartender**让你可以隐藏、重新排列或移动菜单栏应用,保持桌面整洁。**主要功能:*****整理菜单栏应用**:随心所欲地隐藏或显示应用。***更新提醒...

    Mac用户必备!12款最实用的高效App,绝对值得收藏

    作为一名数码博主,日常的工作不仅包括写文章,还涉及到大量的内容创作、视频编辑和资料管理。随着使用Mac的时间越来越长,我发现一台强大的Mac电脑,若没有合适的App加持,效果往往大打折扣。因此,我深入...

    苹果电脑死机了按什么键(mac卡死按哪三个键)

    苹果电脑以其卓越的性能和稳定的系统而闻名,但在使用过程中,偶尔也会遇到死机或应用程序无响应的情况。这时,掌握一些有效的强制重启或关闭方法就显得尤为重要。本文将详细介绍苹果电脑在死机时可以采取的几种处理...

    怎么查看macbook硬盘是不是原装的

    要查看MacBook的硬盘是否是原装的,可以采取以下几种方法:###通过系统信息检查1.**查看设备信息**:打开苹果菜单栏中的“关于本机”选项,然后选择“存储”或“磁盘工具”。这将显示你电脑上已...

    苹果MacBook一定要进行的6个设置|新手必备省电技巧

    一、MacBook省电设置技巧1、电池偏好设置打开“系统偏好设置”,选择“电池”,选择第二项“电池”,不同的系统版本和机型在这个界面会有所差别。勾选“使用电池电源时使显示屏略暗一些”,勾选“优化电池充...

    在 Mac 菜单栏也能控制 HomeKit 家居设备

    想要控制家里的HomeKit设备,我们可以利用Apple官方的家庭App。但在Mac上,家庭App不能算得上好用,不像iOS可以从控制中心直接操作,在Mac上必须打开家庭A...

    苹果手机里这个图标是什么意思?原来这是个监听器!一直都不知道

    不知道大家最近都有没有关注iPhone的新消息呢?iPhone11出来之后,不少小伙伴都被圈粉啦!小编不得不说绿色的那款是真好看啊!当然不仅是好看,用过苹果手机的小伙伴都知道,苹果手机里有很多超好用的...

    如何解决苹果电脑弹出本地项目钥匙串提示?

    Mac电脑使用的时候,因为通过iCloud同步钥匙串,或者是修改本地账户密码,会反复弹出某项目想要登录使用“钥匙串”的提示,且无法关闭的现象。那我们该如何解决呢?快和小编一起来看看吧!具体方法如下1....

    MAC小技巧:如何快速调整Dock栏的大小

    苹果mac系统dock栏怎么缩小?想要自己调节一下dock栏的大小,该怎么调节呢?下面我们就来看看详细的苹果Mac电脑如何快速调整Dock栏的大小样式教程,需要的朋友可以参考下。1、在Dock栏右侧,...

    新买了苹果电脑不会用?给小白的使用手册,MacOS入门必备

    咱们很多小伙伴都是十几年甚至二十几年的Windows老用户了,如果换成苹果电脑,可能会一脸懵逼,一时间不知道怎么使用。毕竟苹果电脑搭载的是MacOS操作系统,除了系统界面和操作上有区别外,电脑键盘上有...

    苹果macOS 15设置界面将迎来重大更新 更智能更美观

    【CNMO科技消息】苹果计划在6月WWDC全球开发者大会上震撼发布macOS15。据CNMO了解,此次更新将彻底革新“菜单和应用程序用户界面”的排列方式。macOSVentura系统中的“系统设置...

    取消回复欢迎 发表评论: