详解玩转直播系列之消息模块演进

目录
  • 一、背景
  • 二、直播消息业务
    • 2.1、主播与用户
    • 2.2、房间号
    • 2.3、消息类型划分
    • 2.4、消息优先级
  • 三、消息技术点
    • 3.1、消息架构模型
    • 3.2、短轮询 VS 长链接
      • 3.2.1、短轮询
      • 3.2.2、长连接
      • 3.2.3、直播间IM消息分发
    • 3.3、消息丢弃
  • 四、写在最后

一、背景

即时消息(IM)系统是直播系统重要的组成部分,一个稳定的,有容错的,灵活的,支持高并发的消息模块是影响直播系统用户体验的重要因素。IM长连接服务在直播系统有发挥着举足轻重的作用。

在目前大部分主流的直播业务中,推拉流是实现直播业务最基本的技术点,消息技术则是实现观看直播的所有用户和主播实现互动的关键技术点,通过直播IM系统模块,我们可以完成公屏互动,彩色弹幕,全网送礼广播,私信,PK等核心秀场直播的功能开发。"IM消息"作为用户和用户,用户和主播之间"沟通"的信息桥梁,如何保证"信息桥梁"的在高并发场景下保持稳定可靠,是直播系统演进过程中一个重要的话题。

二、直播消息业务

在直播业务中,有几个核心的关于消息模型的概念,我们先简单地介绍一下,方便大家对直播相关的消息模型有一个整体上的理解。

2.1、主播与用户

主播和观众,对于IM系统来说,都是一个普通用户,都会有一个唯一用户标识,也是IM分发到点对点消息的重要标识。

2.2、房间号

一个主播对应一个房间号(RoomId),主播在开播之前,进行身份信息验证之后,就会绑定唯一的房间号,房间号是IM系统进行直播间消息分发的重要标识。

2.3、消息类型划分

按照直播业务特性,IM消息划分的方式有很多方式,例如按照接收方维度进行划分,按照直播间消息业务类型进行划分,按照消息的优先级,存储方式都可以进行不同的划分等等方式。

通常,我们按照接收方维度进行划分有如下几个类型的消息:

  • 点对点消息(单播消息)
  • 直播间消息(群播消息)
  • 广播消息

按照具体的业务场景有如下几个类型的消息:

  • 礼物消息
  • 公屏消息
  • PK消息
  • 业务通知类消息

消息能够实时准确地分发到对应的群体或者单个用户终端都是非常必要的。当然好一点的IM消息模型也能够赋能业务一些新的能力,例如如下的能力:

统计每个直播间的实时在线人数

捕获用户进出直播间的事件

统计每个用户实时进入直播间的时间

2.4、消息优先级

直播的消息是有优先级的,这一点是很重要的,与微信,QQ等聊天IM产品不一样的地方是直播间消息是分优先级的。

微信等聊天消息产品,不管是私聊还是群聊,每个人发送消息的优先级基本上是一样的,不存在谁的消息优先级高,谁的消息优先级低,都需要将消息准确实时地分发到各个业务终端,但是直播因为业务场景的不同,消息分发的优先级也是不一样的。

举例来说,如果一个直播间每秒只能渲染15~20个消息,如果一个热点直播间一秒钟产生的消息量大于20条或者更多,如果不做消息优先级的控制,直接实时分发消息,那么导致的结果就是直播间公屏客户端渲染卡顿,礼物弹框渲染过快,用户观看体验大幅下降,所以我们要针对不同业务类型的消息,给出不同的消息优先级。

举例来说,礼物消息大于公屏消息,同等业务类型的消息,大额礼物的消息优先级又大于小额礼物的消息,高等级用户的公屏消息优先级高于低等级用户或者匿名用户的公屏消息,在做业务消息分发的时候,需要根据实际的消息优先级,选择性地进行消息准确地分发。

三、消息技术点

3.1、消息架构模型

3.2、短轮询 VS 长链接

3.2.1、短轮询

短轮询的业务模型

首先我们先简单地描述一下短轮询时间的过程和基本设计思想:

客户端每隔2s轮询服务器接口,参数是roomId和timestamp,timestamp第一次传递0或者null。

服务器根据roomId和timestamp查询该房间在timestamp时间戳后产生的消息事件,返回限定条数的消息例如(例如返回10~15条,当然在这个timestamp之后产生的消息数远远大于15条,不过因为客户端渲染能力有限和过多的消息展示,会影响用户体验,所以限制返回的条数),并且同时返回这些消息中最后一条消息产生的时间戳timestamp,作为客户端下次请求服务器的基准请求时间戳。

以此反复,这样就可以每隔2s按照各个终端要求,更新每个直播间的最新消息了

整体的主体思想如上图所示,不过具体的时间可以再做精细化处理,后续再做具体的说明和细节说明。

短轮询的存储模型

短轮询的消息存储与正常的长连接的消息存储有一定的区别,不存在消息扩散的问题,我们需要做的消息存储需要达到如下的业务目标:

消息插入时间复杂度要相对比较低;

消息查询的复杂度要相对比较低;

消息的存储的结构体要相对比较小,不能占用太大的内存空间或者磁盘空间;

历史消息能够按照业务需要做磁盘持久化存储;

结合上述4点的技术要求,毕竟经过小组成员的讨论,我们决定使用Redis的SortedSet数据结构进行存储,具体实现思路:按照直播间产品业务类型,将业务消息划分为如下四大类型:礼物,公屏,PK,通知。

一个直播间的消息使用四个Redis的SortedSet数据结构进行存储,SortedSet的key分别是"live::roomId::gift","live::roomId::chat","live::roomId::notify","live::roomId::pk",score分别是消息真实产生的时间戳,value就是序列化好的json字符串,如下图所示:

客户端轮询的时候,服务端查询的逻辑如下所示:

很多同学会疑问,为什么不适用Redis的list的数据结构呢?如下图会进行详细的说明:

最后我们再对比一下Redis的SortedSet和Redis的List这两个数据结构在直播消息存储的时候,时间复杂度的相关分析。

以上,就是我们使用Redis的SortedSet数据结构进行消息存储的一些简单的设计思考,后续我们也会提到端轮询的编码时候,需要的注意点。

短轮询的时间控制

短轮询的时间控制及其重要,我们需要在直播观众观看体验QoE和服务器压力之间找到一个很好的平衡点。

轮询的间隔时间太长,用户体验就会下降很多,直播观看体验就会变差,会有"一顿一顿"的感觉。短轮询的频率过高,会导致服务器的压力过大,也会出现很多次"空轮询",所谓的"空轮询"就是无效轮询,也就是在上一秒有效轮询返回有效消息之后,间隔期直播间没有产生新的消息,就会出现无效的轮询。

vivo直播目前每日的轮询次数是10+亿次,晚观看直播高峰期的时候,服务器和Redis的CPU负载都会上升,dubbo的服务提供方的线程池一直处于高水位线上,这块需要根据机器的和Redis的实时负载的压力,做服务器的水平扩容和Redis Cluster的节点扩容,甚至让一些超高热度值的直播间负载到指定的Redis Cluster集群上,做到物理隔离,享受到"VIP"服务,确保各个直播间的消息相互不影响。

直播人数不一样的直播间,轮询的时间也是可以配置的,例如人数比较少的直播,百人以下的直播间,可以设置比较高频的轮询频率,例如1.5s左右,超过300人以上的,1000人以下可以2s左右,万人直播间可以设置2.5s左右,这些配置应该都可以通过配置中心实时下发,客户端能够实时更新轮询的时间,调整的频率可以根据实际直播间用户体验的效果,并且结合服务器的负载,找到一个轮询间隔的相对最佳值。

短轮询的注意点

1)服务端需要校验客户端传递过来的时间戳:这一点非常重要,试想一下,如果观众在观看直播的时候,将直播退出后台,客户端轮询进程暂停,当用户恢复直播观看画面进程的时候,客户端传递过来的时间就会是非常老旧甚至过期的时间,这个时间会导致服务器查询Redis时出现慢查,如果出现大量的服务器慢查的话,会导致服务器连接Redis的连接无法快速释放,也会拖慢整个服务器的性能,会出现一瞬间大量的轮询接口超时,服务质量和QoE会下降很多。

2)客户端需要校验重复消息:在极端情况下,客户端有可能收到重复的消息,产生的原因可能如下,在某一个时刻客户端发出roomId=888888&timestamp=t1的请求,因为网络不稳定或者服务器GC的原因,导致该请求处理比较慢,耗时超过2s,但是因为轮询时间到了,客户端又发出了roomId=888888&timestamp=t1的请求,服务器返回相同的数据,就会出现客户端重复渲染相同的消息进行展示,这样也会影响用户体验,所以每一个客户端有必要对重复消息进行校验。

3)海量数据无法实时返回渲染的问题:设想一下,如果一个热度极大的直播间,每秒钟产生的消息量是数千或者上万的时候,按照上面的存储和查询思路是有漏洞的,因为我们每次因为各个因素的限制,每次只返回10~20条消息,那么我们需要很长的时间才能把这热度很多的一秒钟的数据全部返回,这样就会造成最新的消息无法快速优先返回,所以轮询返回的消息也可以按照消息优先级进行选择性丢弃。

客户端轮询服务服务器查询直播间的消息的好处是显而易见的,消息的分发是非常实时和准确的,很难出现因为网络颤抖导致消息无法到达的场景,不过坏处也是非常明显的,服务器在业务高峰期的负载压力很大,如果直播间的所有消息都是通过轮询分发的,长期以往,服务器是很难通过水平扩容的方式来达到线性增长的。

3.2.2、长连接

长连接的架构模型

从流程上来说,如上图所示,整体直播长连接的流程:

  • 手机客户端首先通过http请求长连接服务器,获取TCP长连接的IP地址,长连接服务器根据路由和负载策略,返回最优的可连接的IP列表。
  • 手机客户端根据长连接服务器返回的IP列表,进行长连接的客户端的连接请求接入,长连接服务器收到连接请求,进而建立连接。
  • 手机客户端发送鉴权信息,进行通信信息的鉴权和身份信息确认,最后长连接建立完成,长连服务器需要对连接进行管理,心跳监测,断线重连等操作。

长连接服务器集群的基本架构图如下所示,按照地域进行业务划分,不同地域的终端机器按需接入;

长连接建立和管理

为了使消息即时、高效、安全地触达用户,直播客户端和IM系统建立了一条加密的全双工数据通路,收发消息均使用该通道,当大量用户在线的时候,维护这些连接、保持会话,需要用到大量内存和CPU资源。

IM接入层尽量保持功能简洁,业务逻辑下沉到后面逻辑服务中进行处理,为了防止发布的时候,重启进程会导致大量的外网设备重新建立连接,影响用户体验。接入层提供热更新的发布方案:连接维护,账号管理等不经常改动的基础逻辑放入主程序中,业务逻辑采用so插件的方式嵌入到程序的,修改业务逻辑时只需要重新加载一次插件即可,可以保证与设备的长连接不受影响。

长连接保活

长连接建立后,如果中间网络断开,服务端和客户端都无法感知,造成假在线的情况。因此维护好这个“长连接”一个关键的问题在于能够让这个“长连接”能够在中间链路出现问题时,让连接的两端能够快速得到通知,然后通过重连来建立新的可用连接,从而让我们这个长连接一直保持高可用状态。IM在服务端开启了keeplive保活探测机制和在客户端启用了智能心跳。

  • 利用keeplive保活探测功能,可以探知客户端崩溃、中间网络端开和中间设备因超时删除连接相关的连接表等意外情况,从而保证在意外发生时,服务端可以释放半打开的TCP连接。
  • 客户端启动智能心跳不仅能在消耗极少的电和网络流量条件下,通知服务器客户端存活状态、定时的刷新NAT内外网IP映射表,还能在网络变更时自动重连长连接。

3.2.3、直播间IM消息分发

IM长连接分发消息的整体流程图

在整合客户端,IM长连接服务器模块和直播业务服务器模块这三个模块的时候,整体消息的分发逻辑遵循如下的基本原则:

  • 单播,群播,广播消息所有的消息都是由直播业务服务器调用IM长连接服务器的接口,将需要分发的消息分发到各个业务直播间。
  • 业务服务器对直播间产生的事件进行对应的业务类型做响应的处理,例如送礼扣减虚拟货币,发送公屏进行文本健康校验等。
  • 客户端接受直播业务服务器的信令控制,消息是通过长连接通道分发还是http短轮询分发,都是由直播业务服务器控制,客户端屏蔽底层消息获取的方式细节,客户端上层接受统一的消息数据格式,进行对应的业务类型消息处理渲染。

直播间成员管理和消息分发

直播间成员是直播间最重要的基础元数据,单个直播间的用户量实际上是无上限的,且呈现大直播若干个(大于30W同时在线)、中直播间几百个、小直播几万个这样分布,如何管理直播间成员是一个直播间系统架构中核心功能之一,常见的方式有如下两种:

1.为直播间分配固定分片,用户与具体的分片存在映射关系,每个分片中保存用户相对随机。

采用固定分片的方式算法实现简单,但是对于用户少的直播间有可能分片承载的用户数量少,对于用户大的直播间有可能分片承载用户量又比较大,固定分片存在天然伸缩性差的特点。

2.动态分片,规定分片用户数,当用户数超过阈值时,增加一个新的分片,分片数量可以随着用户数增加而变化。

动态分片可以根据直播间人数自动生成分片,满了就开辟新片,尽量使每个分片的用户数达到阈值,但已有分片的用户数量随着用户进出直播间变化,维护复杂度比较高。

直播间消息分发

直播间中有进出场消息、文本消息、礼物消息和公屏消息等多种多样消息,消息的重要程度不一样,可为每个消息设定相应的优先级。

不同优先级的消息放在不同的消息队列中,高优先级的消息优先发送给客户端,消息堆积超过限制时,丢弃最早、低优先级的消息。另外,直播间消息属于实时性消息,用户获取历史消息、离线消息的意义不大,消息采用读扩散的方式存储组织。直播间消息发送时,根据直播间成员分片通知对应的消息发送服务,再把消息分别下发给分片中对应的每一个用户,为了实时、高效地把直播间消息下发给用户,当用户有多条未接收消息时,下发服务采用批量下发的方式将多条消息发送给用户。

长连接的消息压缩

在使用TCP长连接分发直播间消息的时候,也需要注意消息体的大小,如果某一个时刻,分发消息的数量比较大,或者同一个消息在做群播场景的时候,群播的用户比较多,IM连接层的机房的出口带宽就会成为消息分发的瓶颈。所以如何有效的控制每一个消息的大小,压缩每一个消息的大小,是我们也需要思考的问题,我们目前通过两种方式来来做相关消息体结构的优化:

  • 使用protobuf协议数据交换格式
  • 相同类型的消息进行合并发送

经过我们线上测试,使用protobuf数据交换格式,平均每一个消息节省43%的字节大小,可以大大帮助我们节省机房出口带宽。

块消息

所谓块消息,也是我们借鉴其他直播平台的技术方案,也就是多个消息进行合并发送,直播业务服务器不是产生一个消息就立马调用IM长连接服务器集群直接进行消息的分发。主要思想,就是以直播间为维度,每隔1s或者2s,以匀速的时间间隔将在这个时间段业务系统产生的消息进行分发。

每秒分发1020个消息,如果每秒中,业务服务器积累到的消息大于1020个,那就按照消息的优先级进行丢弃,如果这10~20个消息的优先级都比较高,例如都是礼物类型的消息,则将消息放在后一个消息块进行发送,这样做的好处有如下三个;

  • 合并消息,可以减少传输多余的消息头,多个消息一起发送,在自定义的TCP传输协议中,可以共用消息头,进一步减少消息字节数大小;
  • 防止出现消息风暴,直播业务服务器可以很方便的控制消息分发的速度,不会无限制的分发消息到直播客户端,客户端无法处理如此多的消息;
  • 友好的用户体验,直播间的消息因为流速正常,渲染的节奏比较均匀,会带来很好的用户直播体验,整个直播效果会很流畅

3.3、消息丢弃

不管是http短轮询还是长连接,在高热度值直播间出现的时候,都会存在消息丢弃的情况,例如在游戏直播中,有出现比较精彩瞬间的时候,评论公屏数会瞬间增加,同时送低价值的礼物的消息也会瞬间增加很多,用来表示对自己选手精彩操作的支持,那么服务器通过IM长连接或者http短轮询每秒分发的消息数就会数千或者上万,一瞬间的消息突增,会导致客户端出现如下几个问题;

  • 客户端通过长连接获取的消息突增,下行带宽压力突增,其他业务可能会受到影响(例如礼物的svga无法及时下载播放);
  • 客户端无法快速处理渲染如此多的礼物和公屏消息,CPU压力突增,音视频处理也会受到影响;
  • 因消息存在积压,导致会展示过期已久消息的可能,用户体验(QoE)指标会下降。

所以,因为这些原因,消息是存在丢弃的必要的,举一个简单的例子,礼物的优先级一定是高于公屏消息的,PK进度条的消息一定是高于全网广播类消息的,高价值礼物的消息又高于低价值礼物的消息。

根据这些业务理论,我们在真实代码开发中,可以做如下的控制:

结合具体业务特点,给各个业务类型的消息划分出不同等级,在消息分发触发流控的时候,根据消息优先级选择性丢弃低优先级消息。

消息结构体新增创建时间和发送时间两个字段,在实际调用长连接通道的时候,需要判断当前时间与消息的创建时间是够间隔过大,如果过大,则直接丢弃消息。

增益消息(纠正消息),在业务开发中,消息的设计中,尽量地去设计增益消息,增益消息指的是后续到达的消息能够包含前续到达的消息,举例来说,9点10的消息,主播A和主播B的PK值是20比10,那么9点11分分发的PK消息值就是22比10,而不能分发增量消息2:0,希望客户端做PK条的累加(20+2 :10+0),但是存在消息因为网络颤抖或者前置消息丢弃,导致消息丢弃,所以分发增益消息或者纠正消息会能够帮助业务重新恢复正常。

四、写在最后

任何一个直播系统,随着业务的发展和直播间人气不断的增加,消息系统遇到的问题和挑战也会随之而来,不管是长连接的消息风暴,还是海量http短轮询的请求,都会导致服务器压力的剧增,都是我们需要不断解决和优化的。我们要针对每一个时期的业务特点,做直播消息的持续升级,做可演进的消息模块,确保消息分发的能力能够确保业务的持续发展。

vivo直播消息模块也是逐步演进的,演进的动力主要来自于因为业务的发展,随着业务形态的多样化,观看的用户数越来越多,系统的功能也会逐步增多,也会遇到各种性能瓶颈,为了解决实际遇到的性能问题,会逐一进行代码分析,接口性能瓶颈的分析,然后给出对应的解决方案或者解耦方案,消息模块也不例外,希望这篇文章能够给大家带来相关直播消息模块的设计启发。

以上就是详解玩转直播系列之消息模块演进的详细内容,更多关于直播消息模块演进的资料请关注我们其它相关文章!

(0)

相关推荐

  • python实现b站直播自动发送弹幕功能

    基本开发环境 · Python 3.6 · Pycharm 相关模块使用 import requests import time from tkinter import * import random 目标i网页分析 首先你要登陆B站账号,然后随便点击一个直播间,这里建议先选择人气少的,弹幕少的,这样方便查看效果 如上图所示,先打开开发者工具,定位到xhr输入发送内容,点击发送,会有一个post请求的send数据接口. 所以只需要请求这个数据接口即可发送弹幕.就是正常的时候爬取数据,使用requ

  • Android实现聊天记录上传本地服务器(即时通讯)

    即时通讯功能,使用SDK里封装的方法,获取聊天记录,接口请求成功,但获取不到数据.使用本地的服务器保存聊天记录,实现方法如下: 1. ChatFragment.java中请求聊天记录: public class ChatFragment extends EaseChatFragment implements EaseChatFragmentHelper { @Override protected void setUpView() { setChatFragmentHelper(this); St

  • java实现即时通信的完整步骤分享

    前言 移动社交是我们日常生活中很常见的软件,最近在做即时通信,我用的是环信,和大家分享一下~~ 环信的API都是基于JSON的,所以在构造HTTP请求的时候,要指定请求头: 注意==>环信API必须携带token才可以访问. 创建一个认证类 public class Authentic { private static Token token = new Token(); private TalkHttpService service; public Authentic(TalkHttpServ

  • 2分钟实现一个Vue实时直播系统的示例代码

    前言 我们在不敲代码的时候可能会去看游戏直播,那么是前台怎么实现的呢?下面我们来讲一下. 第一步,购买云直播服务 首先,你必须去阿里云或者腾讯云注册一个直播服务.也花不了几个钱,练手的话,几十块钱就够了. 这里我拿阿里云举例,购买完了,配置好推流域名跟播流域名,下面我们将进行地址生成.记住下面生成的地址,下面会用到. 第二步,下载本地推流工具 https://obsproject.com/ 第三步,设置OBS 在第一步中图片底部有推流地址,需要注意,分为两部分填入下方图所示. 在AppName字

  • C# 调用腾讯即时通信 IM的示例

    IM SDK API 概述 https://cloud.tencent.com/document/product/269/33543 /// <summary> /// IM SDK 初始化. /// </summary> /// <param name="sdk_app_id"></param> /// <param name="json_sdk_config"></param> /// &l

  • 详解阿里云视频直播PHP-SDK接入教程

    阿里云 视频直播 配置 及 PHP-SDK 接入教程 个人感觉,阿里的文档比微信的要坑很多- 微信最多是有些比较重要的东西放到比较不起眼.比较难发现的地方. 阿里的文档就是要么就是sdk已经更新了,但是文档还没更新,导致文档与SDK不匹配.在关键点卡我一下- 要么是同样的功能有好几个版本的SDK以及文档,却不告诉你哪个是最新的- 吐槽结束~ 准备工作 1.最重要的,先仔细看下视频直播文档! 2. 购买阿里云的视频直播服务 ,用量不大的时候建议使用按量收费的方式结算,接通之后消耗了流量才扣钱: 3

  • jQuery+ThinkPHP+Ajax实现即时消息提醒功能实例代码

    心血来潮想为自己的小项目做一个提醒系统,譬如私信,评论等消息都能及时传递过来.由于道行尚浅,网上那些长轮询对于我略微复杂,于是觉得还是自己写一写试试比较好. 我的思路是,单独在数据库中建一个提醒表,表主要由接收者的id和消息类型两个字段组成 /* 前台提醒表 */ CREATE TABLE IF NOT EXISTS notification( id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, -- 主键自增 mid INT NOT NULL DEFAULT

  • php和腾讯直播的实现代码

    戏说前文 不要想太多,直播和你(php)没啥关系.帮忙配置一下推拉流地址和License.然后生成一下推拉流地址详细链接就好了 但是,像是送礼物,弹幕自己写长连接或调用im.家族,充币等都是逻辑问题,这里就不说了 下面 第一步 配置推拉流地址 bizid appkey 第二步:生成地址 像这样生成 if (!function_exists('create_live')) { function create_live($user_id = 0) { $live_bizid = Config::ge

  • 详解玩转直播系列之消息模块演进

    目录 一.背景 二.直播消息业务 2.1.主播与用户 2.2.房间号 2.3.消息类型划分 2.4.消息优先级 三.消息技术点 3.1.消息架构模型 3.2.短轮询 VS 长链接 3.2.1.短轮询 3.2.2.长连接 3.2.3.直播间IM消息分发 3.3.消息丢弃 四.写在最后 一.背景 即时消息(IM)系统是直播系统重要的组成部分,一个稳定的,有容错的,灵活的,支持高并发的消息模块是影响直播系统用户体验的重要因素.IM长连接服务在直播系统有发挥着举足轻重的作用. 在目前大部分主流的直播业务

  • 详解SpringBoot整合RabbitMQ如何实现消息确认

    目录 简介 生产者消息确认 介绍 流程 配置 ConfirmCallback ReturnCallback 注册ConfirmCallback和ReturnCallback 消费者消息确认 介绍 手动确认三种方式 简介 本文介绍SpringBoot整合RabbitMQ如何进行消息的确认. 生产者消息确认 介绍 发送消息确认:用来确认消息从 producer发送到 broker 然后broker 的 exchange 到 queue过程中,消息是否成功投递. 如果消息和队列是可持久化的,那么确认消

  • 详解vue-router的Import异步加载模块问题的解决方案

    1.问题现象 2.出现问题的代码点 3.替代方案: 把import() 替换成如下: Promise.resolve().then(()=>require(`@/views/${str}`)) 4.原因分析 项目在编译时,出现一个警告 这个警告的含义: require接收了一个变量,会报上面的警告,接收一个写死的字符串值时则没有警告! 我们通过控制台查看到import()对应编译过后的代码: 从上图可以看到require接收了一个变量,所以运行时出现了警告. 那这样就会报上面找不到对应的模块.

  • 详解Python常用标准库之时间模块time和datetime

    目录 time时间模块 time -- 获取本地时间戳 localtime -- 获取本地时间元组(UTC) gmtime -- 获取时间元组(GMT) mktime -- 时间元组获取时间戳 ctime -- 获取时间字符串 asctime -- 时间元组获取时间字符串 strftime -- 格式化时间 strptime -- 格式化时间 sleep -- 时间睡眠 perf_counter -- 时间计时 模拟进度条 程序计时 时间转换示意图 datetime时间模块 date类 time

  • 详解Python常用标准库之os模块与shutil模块

    目录 系统模块 常用方法 常用属性 文件操作 路径模块 文件复制移动模块(文件操作) copyfileobj -- 复制文件(内容) copyfile -- 复制文件(内容) copymode -- 复制文件(权限) copystat -- 复制文件(除了内容) copy & copy2 -- 复制文件 copytree -- 迭代复制文件夹中的所有 rmtree -- 迭代删除文件夹(即使文件夹中有文件) move -- 移动文件或文件夹 系统模块 import os 系统模块用于对系统进行操

  • 代码详解iOS视频直播弹幕功能

    本篇内容通过步骤详细给大家讲解了iOS视频直播弹幕的原理以及实现代码分析,以下就是全部内容: 1.弹幕的实现性分析 首先,从视觉上明确当前弹幕所具有的功能 从屏幕右侧滑入左侧,直至完全消失 不管是长的弹幕,还是短的弹幕,速度一致(可能有的需求是依据弹幕长度,调整速度) 有弹幕轨道,不是随机产生的弹幕 弹幕不会进行重叠 接下来从功能角度思考需要做什么 重用机制,类似tableView有一个重用池,每个弹幕就是一个cell,当有弹幕发送的时候,如果当前的重用池没有控件,则创建一个新的控件,如果重用池

  • 详解Spring Cloud Stream使用延迟消息实现定时任务(RabbitMQ)

    我们在使用一些开源调度系统(比如:elastic-job等)的时候,对于任务的执行时间通常都是有规律性的,可能是每隔半小时执行一次,或者每天凌晨一点执行一次.然而实际业务中还存在另外一种定时任务,它可能需要一些触发条件才开始定时,比如:编写博文时候,设置2小时之后发送.对于这些开始时间不确定的定时任务,我们也可以通过Spring Cloud Stream来很好的处理. 为了实现开始时间不确定的定时任务触发,我们将引入延迟消息的使用.RabbitMQ中提供了关于延迟消息的插件,所以本文就来具体介绍

  • 详解redis是如何实现队列消息的ack

    前言 由于公司提供的队列实在太过于蛋疼而且还限制不能使用其他队列,但为了保证数据安全性需要一个可以有ack功能的队列. 原生的redis中通过L/R PUSH/POP方式来实现队列的功能,这个当然是没办法满足需求的(没有ack功能),所以需要自己对redis的list(队列)做个小小的调整. 大体思路为在POP时将pop出的数据放到备份的地方,当有ACK请求(确认消息被消耗)后将备份的信息删除掉:每次在pop前需要检查备份队列中有没有过期的数据没有ack的,如果有则PUSH到list中后再从li

  • 详解IOS开发之实现App消息推送(最新)

    好久没有写过博客啦,今天就由本菜鸟给大家做一个简单的IOSApp消息推送教程吧!一切从0开始,包括XCode6, IOS8, 以及苹果开发者中心最新如何注册应用,申请证书以及下载配置概要文件,相信很多刚开始接触iOS的人会很想了解一下.(ps:网上看了一下虽然有很多讲述推送的好教程,我也是看着一步步学会的,但是这些教程的时间都是去年或者更早时期的,对引导新手来说不是很合适) 第一部分 首先第一步当然是介绍一下苹果的推送机制(APNS)咯(ps:其实每一篇教程都有),先来看一张苹果官方对其推送做出

  • 详解Spring Data JPA系列之投影(Projection)的用法

    本文介绍了Spring Data JPA系列之投影(Projection)的用法,分享给大家 在JPA的查询中,有一个不方便的地方,@Query注解,如果查询直接是 Select C from Customer c ,这时候,查询的返回对象就是Customer这个完整的对象,包含所有字段,对于我们的示例并没有什么问题,但是对于比较庞大的domain类,这个查询时就比较要命,并不是所有的字段都能用到,比较头疼.另外,如果定义 select c.firstName as firstName,c.la

随机推荐