来了!HarmonyOS源码获取大全

技术交流梅川酷子 发表了文章 • 0 个评论 • 96 次浏览 • 2020-09-11 17:19 • 来自相关话题

源码获取详情请参考:https://gitee.com/openharmony/docs/blob/master/get-code/%E6%BA%90%E7%A0%81%E8%8E%B7%E5%8F%96.mdOpenHarmony介绍OpenHarmony是... ...查看全部

源码获取

详情请参考:https://gitee.com/openharmony/docs/blob/master/get-code/%E6%BA%90%E7%A0%81%E8%8E%B7%E5%8F%96.md

OpenHarmony介绍

OpenHarmony是HarmonyOS的开源版,由华为捐赠给开放原子开源基金会(OpenAtom Foundation)开源。第一个开源版本支持在128KB~128MB设备上运行,欢迎参加开源社区一起持续演进。

代码仓库地址:https://openharmony.gitee.com

源码获取概述

本文档将介绍如何获取OpenHarmony源码并说明OpenHarmony的源码目录结构。OpenHarmony的代码以组件的形式开放,开发者可以通过如下其中一种方式获取:

获取方式1: 从镜像站点下载压缩文件(推荐)

获取方式2: 从hpm网站组件式获取。通过HPM,查找满足需求的解决方案,挑选/裁剪组件后下载。

获取方式3: 用包管理器命令行工具获取。通过HPM的hpm-cli命令行工具,执行命令下载。

获取方式4: 从代码仓库获取。通过repo或git工具从代码仓库中下载。

获取方式1:从镜像站点获取

为了获得更好的下载性能,您可以选择从以下站点的镜像库获取源码或者对应的解决方案。

表 1 源码获取路径

1.png

获取方式2:从hpm网站组件式获取

适用场景

对于刚接触OpenHarmony的新用户,希望能够参考一些示例解决方案从而进行快速开发。可以在HPM获取推荐的解决方案,以此为基础,增加或裁剪部分组件,快速定制系统。

操作步骤

查找合适的解决方案组件包。

打开包管理页面HPM,设定搜索的对象为“解决方案“,如下图所示。

自搜索框输入关键字搜索,如"camera"。

结果中显示匹配的解决方案,可以进一步根据组件类别等过滤条件(如:适配的开发板,内核)精确筛选。

查找合适的解决方案,点击查看解决方案详情介绍

定制解决方案组件包。

仔细阅读解决方案的说明,以了解该解决方案的使用场景、特性、使用方法以及如何进行定制化,如下图所示。

点击「直接下载」,将解决方案下载到本地。

点击「定制组件」,将对解决方案包含的组件进行定制。

定制组件。

  • 下载的压缩文件并未包含源代码的原始文件,可以在IDE中导入下载的压缩包,解压后执行hpm的安装指令(hpm install),才会将所需要的组件全部下载下来。

  • 下载的组件存在工程目录下的ohos_bundles文件夹中。

进入解决方案定制页面。

通过关闭开关移除可选组件,或者通过“添加组件”增加新的组件。

在右边填写您的项目基本信息,包括名称、版本、描述等信息。

点击“下载“,系统会根据您的选择,生成相应的OpenHarmony代码结构文件(如name.zip),保存至本地文件。

获取方式3:用包管理器命令行获取

适用场景

  • 用户已通过组件式获取的方式获取源码,需要对源码中的某个或某几个组件进行独立升级。

  • 用户已经比较熟悉OpenHarmony系统的开发并且熟练掌握命令行工具的使用。

准备

通过命令行获取,需要先安装Node.js和hpm命令行工具,安装步骤如下:

  • 安装Node.js。

官网下载并在本地安装Node.js.

推荐安装 Node.js 12.x (包含 npm 6.14.4)或更高版本 (推荐 12.13.0+)。

  • 通过Node.js自带的npm安装hpm命令行工具。

打开CMD,执行以下命令:

npm install -g @ohos/hpm-cli

安装完成后执行如下命令,显示hpm版本,即安装成功。

hpm -V 或 hpm --version

如果升级hpm的版本,请执行如下命令:

npm update -g @ohos/hpm-cli

操作

接下来将组件添加到开发项目中,假定要获取的组件名为@ohos/demo,具体操作如下:

  • 进入开发目录,执行如下命令,采用默认模板创建一个开发项目。

hpm init -t default
  • 执行如下命令,安装组件@ohos/demo

hpm install @ohos/demo
  • 工具会自动从服务器下载所有依赖的组件,下载成功则显示Install successfully!

获取方式4:从代码仓库获取

适用场景

  • 基于OpenHarmony的稳定分支建立自己的基线,分发下游客户。

  • 已经完成自身软件与OpenHarmony的对接,需要进行OpenHarmony官方认证。

  • 芯片/模组/app通过OpenHarmony官方认证后,贡献代码到OpenHarmony生态。

  • 修复OpenHarmony的问题。

  • 学习OpenHarmony的源码。

准备

注册码云gitee账号。

注册码云SSH公钥,请参考码云帮助中心的公钥管理https://gitee.com/help/articles/4181

安装git客户端并配置用户信息。

git config --global user.name "yourname"git config --global user.email "your-email-address"git config --global credential.helper store

安装码云repo工具,可以执行如下命令。

curl https://gitee.com/oschina/repo/raw/fork_flow/repo-py3 > /usr/local/bin/repochmod a+x /usr/local/bin/repopip install -i https://pypi.tuna.tsinghua.edu.cn/simple requests

操作

方式一(推荐):通过repo下载

repo init -u https://gitee.com/openharmony/manifest.git -b master --no-repo-verifyrepo sync -c

方式二:通过git clone单个代码仓库

进入代码仓库主页:https://gitee.com/openharmony ,选择需要克隆的代码仓库,执行命令,如:

git clone https://gitee.com/openharmony/manifest.git -b master

源码目录简介

下表是OpenHarmony源码的目录及简单说明:

表 2 源码目录的说明

微信截图_20200911171836.png


HarmonyOS官方开发者论坛:https://developer.huawei.com/consumer/cn/forum/blockdisplay?fid=0101303901040230869


原文链接:https://developer.huawei.com/consumer/cn/forum/topicview?tid=0202350736685590542&fid=0101303901040230869

原作者:kelly


如何用JAVA设计一个亿级消息量的 IM 系统

技术交流大兴 发表了文章 • 0 个评论 • 38 次浏览 • 2020-09-11 11:01 • 来自相关话题

本文不会给出一套通用的IM方案,也不会评判某种架构的好坏,而是讨论设计IM系统的常见难题跟业界的解决方案。因为也没有所谓的通用方案,不同的解决方案都有其优缺点,只有最满足业务的系统才是一个好的系统。而且,在有限的人力、物力跟时间资源下,通常需要做出很多权衡,此... ...查看全部

本文不会给出一套通用的IM方案,也不会评判某种架构的好坏,而是讨论设计IM系统的常见难题跟业界的解决方案。因为也没有所谓的通用方案,不同的解决方案都有其优缺点,只有最满足业务的系统才是一个好的系统。而且,在有限的人力、物力跟时间资源下,通常需要做出很多权衡,此时,一个能够快速迭代、方便扩展的系统才是一个好的系统。

 

IM核心概念

用户:系统的使用者

消息:是指用户之间的沟通内容。通常在IM系统中,消息会有以下几类:文本消息、表情消息、图片消息、视频消息、文件消息等等

会话:通常指两个用户之间因聊天而建立起的关联

群:通常指多个用户之间因聊天而建立起的关联

终端:指用户使用IM系统的机器。通常有Android端、iOS端、Web端等等

未读数:指用户还没读的消息数量

用户状态:指用户当前是在线、离线还是挂起等状态

关系链:是指用户与用户之间的关系,通常有单向的好友关系、双向的好友关系、关注关系等等。这里需要注意与会话的区别,用户只有在发起聊天时才产生会话,但关系并不需要聊天才能建立。对于关系链的存储,可以使用图数据库(Neo4j等等),可以很自然地表达现实世界中的关系,易于建模

单聊:一对一聊天

群聊:多人聊天

客服:在电商领域,通常需要对用户提供售前咨询、售后咨询等服务。这时,就需要引入客服来处理用户的咨询

消息分流:在电商领域,一个店铺通常会有多个客服,此时决定用户的咨询由哪个客服来处理就是消息分流。通常消息分流会根据一系列规则来确定消息会分流给哪个客服,例如客服是否在线(客服不在线的话需要重新分流给另一个客服)、该消息是售前咨询还是售后咨询、当前客服的繁忙程度等等

信箱:本文的信箱我们指一个Timeline、一个收发消息的队列

 

读扩散 vs 写扩散

读扩散

我们先来看看读扩散。如上图所示,A与每个聊天的人跟群都有一个信箱(有些博文会叫Timeline),A在查看聊天信息的时候需要读取所有有新消息的信箱。这里的读扩散需要注意与Feeds系统的区别,在Feeds系统中,每个人都有一个写信箱,写只需要往自己的写信箱里写一次就好了,读需要从所有关注的人的写信箱里读。但IM系统里的读扩散通常是每两个相关联的人就有一个信箱,或者每个群一个信箱。

读扩散的优点:

写操作(发消息)很轻量,不管是单聊还是群聊,只需要往相应的信箱写一次就好了

每一个信箱天然就是两个人的聊天记录,可以方便查看聊天记录跟进行聊天记录的搜索

读扩散的缺点:

读操作(读消息)很重

写扩散

接下来看看写扩散。

e38c316470c48ab4e7f8492ec20398672f5e14.jpg.png

在写扩散中,每个人都只从自己的信箱里读取消息,但写(发消息)的时候,对于单聊跟群聊处理如下:

单聊:往自己的信箱跟对方的信箱都写一份消息,同时,如果需要查看两个人的聊天历史记录的话还需要再写一份(当然,如果从个人信箱也能回溯出两个人的所有聊天记录,但这样效率会很低)。

群聊:需要往所有的群成员的信箱都写一份消息,同时,如果需要查看群的聊天历史记录的话还需要再写一份。可以看出,写扩散对于群聊来说大大地放大了写操作。

写扩散优点:

读操作很轻量

可以很方便地做消息的多终端同步

写扩散缺点:

写操作很重,尤其是对于群聊来说

注意,在Feeds系统中:

写扩散也叫:Push、Fan-out或者Write-fanout

读扩散也叫:Pull、Fan-in或者Read-fanout

 

唯一ID设计

通常情况下,ID的设计主要有以下几大类:

UUID

基于Snowflake的ID生成方式

基于申请DB步长的生成方式

基于Redis或者DB的自增ID生成方式

特殊的规则生成唯一ID

具体的实现方法跟优缺点可以参考之前的一篇博文:分布式唯一 ID 解析

在IM系统中需要唯一Id的地方主要是:

会话ID

消息ID

 

消息ID

我们来看看在设计消息ID时需要考虑的三个问题。

 

消息ID不递增可以吗

我们先看看不递增的话会怎样:

使用字符串,浪费存储空间,而且不能利用存储引擎的特性让相邻的消息存储在一起,降低消息的写入跟读取性能

使用数字,但数字随机,也不能利用存储引擎的特性让相邻的消息存储在一起,会加大随机IO,降低性能;而且随机的ID不好保证ID的唯一性

因此,消息ID最好是递增的。

 

全局递增 vs 用户级别递增 vs 会话级别递增

全局递增:指消息ID在整个IM系统随着时间的推移是递增的。全局递增的话一般可以使用Snowflake(当然,Snowflake也只是worker级别的递增)。此时,如果你的系统是读扩散的话为了防止消息丢失,那每一条消息就只能带上上一条消息的ID,前端根据上一条消息判断是否有丢失消息,有消息丢失的话需要重新拉一次。

用户级别递增:指消息ID只保证在单个用户中是递增的,不同用户之间不影响并且可能重复。典型代表:微信。如果是写扩散系统的话信箱时间线ID跟消息ID需要分开设计,信箱时间线ID用户级别递增,消息ID全局递增。如果是读扩散系统的话感觉使用用户级别递增必要性不是很大。

会话级别递增:指消息ID只保证在单个会话中是递增的,不同会话之间不影响并且可能重复。典型代表:QQ。

 

连续递增 vs 单调递增

连续递增是指ID按 1,2,3...n 的方式生成;而单调递增是指只要保证后面生成的ID比前面生成的ID大就可以了,不需要连续。

据我所知,QQ的消息ID就是在会话级别使用的连续递增,这样的好处是,如果丢失了消息,当下一条消息来的时候发现ID不连续就会去请求服务器,避免丢失消息。此时,可能有人会想,我不能用定时拉的方式看有没有消息丢失吗?当然不能,因为消息ID只在会话级别连续递增的话那如果一个人有上千个会话,那得拉多少次啊,服务器肯定是抗不住的。

对于读扩散来说,消息ID使用连续递增就是一种不错的方式了。如果使用单调递增的话当前消息需要带上前一条消息的ID(即聊天消息组成一个链表),这样,才能判断消息是否丢失。

总结一下就是:

写扩散:信箱时间线ID使用用户级别递增,消息ID全局递增,此时只要保证单调递增就可以了

读扩散:消息ID可以使用会话级别递增并且最好是连续递增

 

会话ID

我们来看看设计会话ID需要注意的问题:

其中,会话ID有种比较简单的生成方式(特殊的规则生成唯一ID):拼接 from_user_id 跟 to_user_id:

如果 from_user_id 跟 to_user_id 都是32位整形数据的话可以很方便地用位运算拼接成一个64位的会话ID,即: conversation_id = ${from_user_id} << 32 | ${to_user_id} (在拼接前需要确保值比较小的用户ID是 from_user_id,这样任意两个用户发起会话可以很方便地知道会话ID)

如果from_user_id 跟 to_user_id 都是64位整形数据的话那就只能拼接成一个字符串了,拼接成字符串的话就比较伤了,浪费存储空间性能又不好。

前东家就是使用的上面第1种方式,第1种方式有个硬伤:随着业务在全球的扩展,32位的用户ID如果不够用需要扩展到64位的话那就需要大刀阔斧地改了。32位整形ID看起来能够容纳21亿个用户,但通常我们为了防止别人知道真实的用户数据,使用的ID通常不是连续的,这时,32位的用户ID就完全不够用了。因此,该设计完全依赖于用户ID,不是一种可取的设计方式。

因此,会话ID的设计可以使用全局递增的方式,加一个映射表,保存from_user_id、to_user_id跟conversation_id的关系。

 

推模式 vs 拉模式 vs 推拉结合模式

在IM系统中,新消息的获取通常会有三种可能的做法:

推模式:有新消息时服务器主动推给所有端(iOS、Android、PC等)

拉模式:由前端主动发起拉取消息的请求,为了保证消息的实时性,一般采用推模式,拉模式一般用于获取历史消息

推拉结合模式:有新消息时服务器会先推一个有新消息的通知给前端,前端接收到通知后就向服务器拉取消息

推模式简化图如下:

04cfb696364aeffcfdd83382d29a45bfefb11a.jpg.png

如上图所示,正常情况下,用户发的消息经过服务器存储等操作后会推给接收方的所有端。但推是有可能会丢失的,最常见的情况就是用户可能会伪在线(是指如果推送服务基于长连接,而长连接可能已经断开,即用户已经掉线,但一般需要经过一个心跳周期后服务器才能感知到,这时服务器会错误地以为用户还在线;伪在线是本人自己想的一个概念,没想到合适的词来解释)。因此如果单纯使用推模式的话,是有可能会丢失消息的。

推拉结合模式简化图如下:

6760f5926b20f8763ec72480c1328e859795dd.jpg.png

可以使用推拉结合模式解决推模式可能会丢消息的问题。在用户发新消息时服务器推送一个通知,然后前端请求最新消息列表,为了防止有消息丢失,可以再每隔一段时间主动请求一次。可以看出,使用推拉结合模式最好是用写扩散,因为写扩散只需要拉一条时间线的个人信箱就好了,而读扩散有N条时间线(每个信箱一条),如果也定时拉取的话性能会很差。

 

业界解决方案

前面了解了IM系统的常见设计问题,接下来我们再看看业界是怎么设计IM系统的。研究业界的主流方案有助于我们深入理解IM系统的设计。以下研究都是基于网上已经公开的资料,不一定正确,大家仅作参考就好了。

微信

虽然微信很多基础框架都是自研,但这并不妨碍我们理解微信的架构设计。从微信公开的《从0到1:微信后台系统的演进之路》这篇文章可以看出,微信采用的主要是:写扩散 + 推拉结合。由于群聊使用的也是写扩散,而写扩散很消耗资源,因此微信群有人数上限(目前是500)。所以这也是写扩散的一个明显缺点,如果需要万人群就比较难了。

从文中还可以看出,微信采用了多数据中心架构:

 62f39582378e16672d3132062133f47142ce8e.jpg.png

 


微信每个数据中心都是自治的,每个数据中心都有全量的数据,数据中心间通过自研的消息队列来同步数据。为了保证数据的一致性,每个用户都只属于一个数据中心,只能在自己所属的数据中心进行数据读写,如果用户连了其它数据中心则会自动引导用户接入所属的数据中心。而如果需要访问其它用户的数据那只需要访问自己所属的数据中心就可以了。同时,微信使用了三园区容灾的架构,使用Paxos来保证数据的一致性。

从微信公开的《万亿级调用系统:微信序列号生成器架构设计及演变》这篇文章可以看出,微信的ID设计采用的是:基于申请DB步长的生成方式 + 用户级别递增。如下图所示:

1.png

微信的序列号生成器由仲裁服务生成路由表(路由表保存了uid号段到AllocSvr的全映射),路由表会同步到AllocSvr跟Client。如果AllocSvr宕机的话会由仲裁服务重新调度uid号段到其它AllocSvr。

 

钉钉

钉钉公开的资料不多,从《阿里钉钉技术分享:企业级IM王者——钉钉在后端架构上的过人之处》这篇文章我们只能知道,钉钉最开始使用的是写扩散模型,为了支持万人群,后来貌似优化成了读扩散。

但聊到阿里的IM系统,不得不提的是阿里自研的Tablestore。一般情况下,IM系统都会有一个自增ID生成系统,但Tablestore创造性地引入了主键列自增,即把ID的生成整合到了DB层,支持了用户级别递增(传统MySQL等DB只能支持表级自增,即全局自增)。具体可以参考:《如何优化高并发IM系统架构》

 

Twitter

什么?Twitter不是Feeds系统吗?这篇文章不是讨论IM的吗?是的,Twitter是Feeds系统,但Feeds系统跟IM系统其实有很多设计上的共性,研究下Feeds系统有助于我们在设计IM系统时进行参考。再说了,研究下Feeds系统也没有坏处,扩展下技术视野嘛。

Twitter的自增ID设计估计大家都耳熟能详了,即大名鼎鼎的Snowflake,因此ID是全局递增的。


从这个视频分享《How We Learned to Stop Worrying and Love Fan-In at Twitter》可以看出,Twitter一开始使用的是写扩散模型,Fanout Service负责扩散写到Timelines Cache(使用了Redis),Timeline Service负责读取Timeline数据,然后由API Services返回给用户。

但由于写扩散对于大V来说写的消耗太大,因此后面Twitter又使用了写扩散跟读扩散结合的方式。如下图所示:



 2.png

对于粉丝数不多的用户如果发Twitter使用的还是写扩散模型,由Timeline Mixer服务将用户的Timeline、大V的写Timeline跟系统推荐等内容整合起来,最后再由API Services返回给用户。

 

58到家

58到家实现了一个通用的实时消息平台:

3.png

可以看出,msg-server保存了应用跟MQ主题之间的对应关系,msg-server根据这个配置将消息推到不同的MQ队列,具体的应用来消费就可以了。因此,新增一个应用只需要修改配置就可以了。

58到家为了保证消息投递的可靠性,还引入了确认机制:消息平台收到消息先落地数据库,接收方收到后应用层ACK再删除。使用确认机制最好是只能单点登录,如果多端能够同时登录的话那就比较麻烦了,因为需要所有端都确认收到消息后才能删除。

看到这里,估计大家已经明白了,设计一个IM系统很有挑战性。我们还是继续来看设计一个IM系统需要考虑的问题吧。

 

IM需要解决的问题

如何保证消息的实时性

在通信协议的选择上,我们主要有以下几个选择:

使用TCP Socket通信,自己设计协议:58到家等等

使用UDP Socket通信:QQ等等

使用HTTP长轮循:微信网页版等等

不管使用哪种方式,我们都能够做到消息的实时通知。但影响我们消息实时性的可能会在我们处理消息的方式上。例如:假如我们推送的时候使用MQ去处理并推送一个万人群的消息,推送一个人需要2ms,那么推完一万人需要20s,那么后面的消息就阻塞了20s。如果我们需要在10ms内推完,那么我们推送的并发度应该是:人数:10000 / (推送总时长:10 / 单个人推送时长:2) = 2000

因此,我们在选择具体的实现方案的时候一定要评估好我们系统的吞吐量,系统的每一个环节都要进行评估压测。只有把每一个环节的吞吐量评估好了,才能保证消息推送的实时性。

如何保证消息时序

以下情况下消息可能会乱序:

发送消息如果使用的不是长连接,而是使用HTTP的话可能会出现乱序。因为后端一般是集群部署,使用HTTP的话请求可能会打到不同的服务器,由于网络延迟或者服务器处理速度的不同,后发的消息可能会先完成,此时就产生了消息乱序。解决方案:

前端依次对消息进行处理,发送完一个消息再发送下一个消息。这种方式会降低用户体验,一般情况下不建议使用。

带上一个前端生成的顺序ID,让接收方根据该ID进行排序。这种方式前端处理会比较麻烦一点,而且聊天的过程中接收方的历史消息列表中可能会在中间插入一条消息,这样会很奇怪,而且用户可能会漏读消息。但这种情况可以通过在用户切换窗口的时候再进行重排来解决,接收方每次收到消息都先往最后面追加。

通常为了优化体验,有的IM系统可能会采取异步发送确认机制(例如:QQ)。即消息只要到达服务器,然后服务器发送到MQ就算发送成功。如果由于权限等问题发送失败的话后端再推一个通知下去。这种情况下MQ就要选择合适的Sharding策略了:

按to_user_id进行Sharding:使用该策略如果需要做多端同步的话发送方多个端进行同步可能会乱序,因为不同队列的处理速度可能会不一样。例如发送方先发送m1然后发送m2,但服务器可能会先处理完m2再处理m1,这里其它端会先收到m2然后是m1,此时其它端的会话列表就乱了。

按conversation_id进行Sharding:使用该策略同样会导致多端同步会乱序。

按from_user_id进行Sharding:这种情况下使用该策略是比较好的选择

通常为了优化性能,推送前可能会先往MQ推,这种情况下使用to_user_id才是比较好的选择。

用户在线状态如何做

很多IM系统都需要展示用户的状态:是否在线,是否忙碌等。主要可以使用Redis或者分布式一致性哈希来实现用户在线状态的存储。

看上面的图可能会有人疑惑,为什么每次心跳都需要更新Redis?如果我使用的是TCP长连接那是不是就不用每次心跳都更新了?确实,正常情况下服务器只需要在新建连接或者断开连接的时候更新一下Redis就好了。但由于服务器可能会出现异常,或者服务器跟Redis之间的网络会出现问题,此时基于事件的更新就会出现问题,导致用户状态不正确。因此,如果需要用户在线状态准确的话最好通过心跳来更新在线状态。

由于Redis是单机存储的,因此,为了提高可靠性跟性能,我们可以使用Redis Cluster或者Codis。

使用分布式一致性哈希需要注意在对Status Server Cluster进行扩容或者缩容的时候要先对用户状态进行迁移,不然在刚操作时会出现用户状态不一致的情况。同时还需要使用虚拟节点避免数据倾斜的问题。

 

多端同步怎么做

读扩散

前面也提到过,对于读扩散,消息的同步主要是以推模式为主,单个会话的消息ID顺序递增,前端收到推的消息如果发现消息ID不连续就请求后端重新获取消息。但这样仍然可能丢失会话的最后一条消息,为了加大消息的可靠性,可以在历史会话列表的会话里再带上最后一条消息的ID,前端在收到新消息的时候会先拉取最新的会话列表,然后判断会话的最后一条消息是否存在,如果不存在,消息就可能丢失了,前端需要再拉一次会话的消息列表;如果会话的最后一条消息ID跟消息列表里的最后一条消息ID一样,前端就不再处理。这种做法的性能瓶颈会在拉取历史会话列表那里,因为每次新消息都需要拉取后端一次,如果按微信的量级来看,单是消息就可能会有20万的QPS,如果历史会话列表放到MySQL等传统DB的话肯定抗不住。因此,最好将历史会话列表存到开了AOF(用RDB的话可能会丢数据)的Redis集群。这里只能感慨性能跟简单性不能兼得。

 

写扩散

对于写扩散来说,多端同步就简单些了。前端只需要记录最后同步的位点,同步的时候带上同步位点,然后服务器就将该位点后面的数据全部返回给前端,前端更新同步位点就可以了。

如何处理未读数

在IM系统中,未读数的处理非常重要。未读数一般分为会话未读数跟总未读数,如果处理不当,会话未读数跟总未读数可能会不一致,严重降低用户体验。

读扩散

对于读扩散来说,我们可以将会话未读数跟总未读数都存在后端,但后端需要保证两个未读数更新的原子性跟一致性,一般可以通过以下两种方法来实现:

使用Redis的multi事务功能,事务更新失败可以重试。但要注意如果你使用Codis集群的话并不支持事务功能。

使用Lua嵌入脚本的方式。使用这种方式需要保证会话未读数跟总未读数都在同一个Redis节点(Codis的话可以使用Hashtag)。这种方式会导致实现逻辑分散,加大维护成本。

写扩散

对于写扩散来说,服务端通常会弱化会话的概念,即服务端不存储历史会话列表。未读数的计算可由前端来负责,标记已读跟标记未读可以只记录一个事件到信箱里,各个端通过重放该事件的形式来处理会话未读数。使用这种方式可能会造成各个端的未读数不一致,至少微信就会有这个问题。

如果写扩散也通过历史会话列表来存储未读数的话那用户时间线服务跟会话服务紧耦合,这个时候需要保证原子性跟一致性的话那就只能使用分布式事务了,会大大降低系统的性能。

如何存储历史消息

读扩散

对于读扩散,只需要按会话ID进行Sharding存储一份就可以了。

 

写扩散

对于写扩散,需要存储两份:一份是以用户为Timeline的消息列表,一份是以会话为Timeline的消息列表。以用户为Timeline的消息列表可以用用户ID来做Sharding,以会话为Timeline的消息列表可以用会话ID来做Sharding。

 

数据冷热分离

对于IM来说,历史消息的存储有很强的时间序列特性,时间越久,消息被访问的概率也越低,价值也越低。如果我们需要存储几年甚至是永久的历史消息的话(电商IM中比较常见),那么做历史消息的冷热分离就非常有必要了。数据的冷热分离一般是HWC(Hot-Warm-Cold)架构。对于刚发送的消息可以放到Hot存储系统(可以用Redis)跟Warm存储系统,然后由Store Scheduler根据一定的规则定时将冷数据迁移到Cold存储系统。获取消息的时候需要依次访问Hot、Warm跟Cold存储系统,由Store Service整合数据返回给IM Service。

 

接入层怎么做

实现接入层的负载均衡主要有以下几个方法:

硬件负载均衡:例如F5、A10等等。硬件负载均衡性能强大,稳定性高,但价格非常贵,不是土豪公司不建议使用。

使用DNS实现负载均衡:使用DNS实现负载均衡比较简单,但使用DNS实现负载均衡如果需要切换或者扩容那生效会很慢,而且使用DNS实现负载均衡支持的IP个数有限制、支持的负载均衡策略也比较简单。

DNS + 4层负载均衡 + 7层负载均衡架构:例如 DNS + DPVS + Nginx 或者 DNS + LVS + Nginx。有人可能会疑惑为什么要加入4层负载均衡呢?这是因为7层负载均衡很耗CPU,并且经常需要扩容或者缩容,对于大型网站来说可能需要很多7层负载均衡服务器,但只需要少量的4层负载均衡服务器即可。因此,该架构对于HTTP等短连接大型应用很有用。当然,如果流量不大的话只使用DNS + 7层负载均衡即可。但对于长连接来说,加入7层负载均衡Nginx就不大好了。因为Nginx经常需要改配置并且reload配置,reload的时候TCP连接会断开,造成大量掉线。

DNS + 4层负载均衡:4层负载均衡一般比较稳定,很少改动,比较适合于长连接。

对于长连接的接入层,如果我们需要更加灵活的负载均衡策略或者需要做灰度的话,那我们可以引入一个调度服务,如下图所示:

 4.png

Access Schedule Service可以实现根据各种策略来分配Access Service,例如:

根据灰度策略来分配

根据就近原则来分配

根据最少连接数来分配

 

架构心得

最后,分享一下做大型应用的架构心得:

灰度!灰度!灰度!

监控!监控!监控!

告警!告警!告警!

缓存!缓存!缓存!

限流!熔断!降级!

低耦合,高内聚!

避免单点,拥抱无状态!

评估!评估!评估!

压测!压测!压测!

 

来源:InfoQ 


【Geek Online 2020 编程挑战赛】有人组队吗?

活动梅川酷子 回复了问题 • 3 人关注 • 2 个回复 • 78 次浏览 • 2020-09-10 18:25 • 来自相关话题

英雄会被表彰,这些技术与代码也将载入史册!

科技前线柠檬^ 发表了文章 • 1 个评论 • 45 次浏览 • 2020-09-10 16:14 • 来自相关话题

昨天,我们被「人民英雄」刷屏了。上午十点,全国抗击新冠肺炎疫情表彰大会,在人民大会堂隆重举行。大会授予钟南山「共和国勋章」,授予张伯礼、张定宇、陈薇「人民英雄」国家荣誉称号。除了这些战疫者之外,在今年抗击疫情过程中,还有一批特殊的「功臣」,也在今年的抗疫战中立... ...查看全部

昨天,我们被「人民英雄」刷屏了。

上午十点,全国抗击新冠肺炎疫情表彰大会,在人民大会堂隆重举行。

大会授予钟南山「共和国勋章」,授予张伯礼、张定宇、陈薇「人民英雄」国家荣誉称号。

除了这些战疫者之外,在今年抗击疫情过程中,还有一批特殊的「功臣」,也在今年的抗疫战中立下汗马功劳,从而被纳入国家博物馆收藏。

历史也将铭记:代码、无人车、外卖服

近日,国家博物馆陆续上新,这批最新纳入的藏品,与以往的有所不同:这些物品都是为纪念抗疫征集而来,将成为历史文物。

2.png

国博曾在 3 月向社会公开征集

抗疫相关实物与资料

国博发出抗疫藏品征集公告之后,社会各界都纷纷响应,捐出了各种具有纪念意义的物品。

如今最新加入国博的这些成员,不仅因为见证了这场抗疫历史,而拥有了特殊的意义,也因为其自身鲜明的时代特色,而显得十分别样。

阿里:三段代码 

本次藏品征集中,阿里提交了包括 4 本新型冠状病毒肺炎临床救治手册、2 本新冠疫情爆发下的医院应对策略、六大洲捐赠的提单和报关单、等 14 种共 30 件抗疫实物。

这其中,有三件「物品」与众不同,它们分别是:

  • 支付宝团队研发的健康码系统第一行代码;
  • 阿里云研发的全国健康码引擎第一行代码;
  • 阿里巴巴达摩院研发的新冠肺炎 CT 影像 AI 辅助诊断产品第一行代码。

3.png

与代码一起纳入收藏的,还有参与该项目的程序员签名

众所周知,自 2020 年初新冠肺炎疫情爆发之后,疫情防控成为全国上下第一要务。

除了体温、核酸检测等线下手段外,健康码这个数字化防疫工具,也成为人人出行的必备凭证。

4.png

出入公共场所,健康码已必不可少
据介绍,健康码项目需要阿里旗下的支付宝、阿里云和钉钉团队三方合作完成,因此,这三方团队的工程师组成了健康码团队。
阿里云团队的核心任务是开发码引擎,支付宝和钉钉团队则提供查询获取入口、和核验等功能。
注:码引擎是健康码的后端,它会将用户的个人身份信息通过公安数据库转换化成系统中的唯一代码,指挥红黄绿三码的判断和实时发放。
在三方团队协作下,健康码的第一行代码,于 2 月初的一个凌晨提交,2 月 11 日便在杭州上线。随后,因其方便出示与使用,很快便被推广至全国各地。
如今,这行代码正式被国家博物馆收藏,不仅仅在于其技术上带来的突破,其收藏意义更在于这是中国数字化抗疫的见证、包含着全国人民一段刻骨铭心的记忆。
京东:无人配送车 
京东共有五件物品入选国博藏品,被称为「五件套」。

它们包括:JD40006 号无人配送车、湖北省新冠疫情防控指挥部的感谢信、钟南山院士的感谢信、内蒙古援鄂医疗队医护人员写给京东快递小哥的感谢信、技术抗疫纪录片。

5.png

该无人配送车由京东智能行驶部研发
这辆 JD40006 号无人配送车,是首个成为京东正式员工的机器人。在疫情初期,JD40006 成为京东智能科技应急小组的成员之一,被亲切地称为「大白」,负责疫情期间无接触配送物资。
它依托 L4 级别自动驾驶技术和北斗卫星定位系统,以及远程部署,使整个无人配送过程实现全自动化。抗疫期间,它往返行驶总里程超过 6800 公里,运送包裹约 1.3 万件。
饿了么:骑士外卖服 
外卖,已经成为这个时代不可或缺的一部分。根据易观数据,当前中国一天的外卖规模就超过 20 亿元。如今,外卖早已不限于餐饮,还延伸到生鲜、日常用品、医疗用品等的配送。
如果说,此前外卖带给我们的是便捷与时间自由,那么疫情期间,外卖还带给我们更多的安全感。

据报道,疫情期间,32 岁的退伍军人付腾虎,组建了一支特别的外卖配送队「飞虎队」,给武汉协和医护人员送餐。他们每天一趟送几十份餐,累计送了万份餐。

6.png

「飞虎队」所有骑手签名的外卖服
在这些科技抗疫的代表作中,代码作为一项最为特殊的藏品,也在网络上引起热议。

「写代码写进国博挺酷的,有点激动,是个纪念。到时候国博有展,我一定会去北京看的。」支付宝前端开发刘志飞说。

7.png

刘志飞为参与健康码项目成员之一
代码:现代科技的载体,人类的共同遗产
中国国家博物馆作为中华文物收藏量最丰富的博物馆之一,收藏着上百万件珍贵藏品,而这些藏品无一不蕴藏着厚重的历史气息。
从远古时期的人面鱼纹陶盆,到明清时期的郑和铜钟。这些藏品,都是能够摸得着的实实在在的物体。

收藏代码,是国家博物馆的第一次,却也有例可循。GitHub 在前不久将一部分开源代码,以胶片的形式储存,打包运往北极冷岸群岛。

8.png

这批代码胶片被存放在极其干燥的、-5°C 恒温的矿井中

据介绍,这些代码至多可以保存一千年。GitHub 官方启动这个计划的原因,便是:世界由开源软件提供动力。这些代码是现代文明的隐藏基石,也是全人类的共同遗产。

健康码也是一样,这些「摸不着」的代码,是这段重要、特殊的 2020 年里,重要的组成部分。

9.png

来自知乎用户@克里姆林之主的观点
将这段代码纳入国博藏品,不仅理所应当,也更兼具时代意义。

我们将铭记这段不同寻常的时期,后人也会了解到这段用科技、医疗、人文关怀一起驱动着全体国民,共同抗击疫情的历史时刻。


来源公众号:HyperAI超神经

那些被困在系统里的外卖骑手(下)

科技前线梅川酷子 发表了文章 • 0 个评论 • 43 次浏览 • 2020-09-10 11:34 • 来自相关话题

佩奇与可乐因为一次与顾客的冲突,美团骑手小林发现了一个隐藏在系统内的秘密——顾客端显示的送达时间与骑手端不一致。当时,他刚开始跑美团众包,有一次接了个单,刚赶到店家,就收到了顾客劈头盖脸的质问,你怎么还没送到?都超时好久了。小林觉得顾客无理取闹,因为,当时距离... ...查看全部

佩奇与可乐

因为一次与顾客的冲突,美团骑手小林发现了一个隐藏在系统内的秘密——顾客端显示的送达时间与骑手端不一致。

当时,他刚开始跑美团众包,有一次接了个单,刚赶到店家,就收到了顾客劈头盖脸的质问,你怎么还没送到?都超时好久了。小林觉得顾客无理取闹,因为,当时距离他手机上显示的送达时间,还有将近10分钟。后来送餐时,他和顾客又因为时间起了争执,两人掏出手机一对——顾客端的期望送达时间比骑手端的要求送达时间少了整整10分钟。

自从发现了这个秘密,小林每个月都会给美团客服打电话,至今已打了将近四年,每一次的客服都不一样,但话术始终如一:跟客人解释一下,那只是期望送达时间。

这并不是小林的个体遭遇,多位骑手都对《人物》提到了这个问题。在他们看来,这是系统讨好顾客、稳住顾客的方式,而这也是引发顾客与骑手矛盾的重要原因之一。

学者卢泰宏在《消费者行为学:中国消费者透视》一书中指出,数字时代提供的便捷,令消费者变得越来越挑剔,他们越来越注重服务质量和产品体验,但对产品和品牌的忠诚度降低,随时准备更换供应商,因此,他们拥有不同于以往的、对市场更大的影响力和主导权。

在这种影响力面前,注重用户量和订单量的外卖平台也用算法构筑起了一种权力结构,在这个体系中,顾客成了最顶端的存在,拥有至高无上的权力。

顾客可以犯错。顾客有的时候真的,没法说。关于这个话题,甘肃骑手王兵有一肚子的话要说,很多人都不知道自己住在哪里,明明住在804,给自己写801。明明住在南门,写自己在北门。还有的顾客点完餐居然忘记了,打电话还没人接,第二天想起来了打电话给我,我的餐呢……还有人下单时根本不看地址,我接单一看,这地址不对啊,都跨省了……只是,顾客不需要为自己的错误付出代价,如果订单超时,受罚的依然是骑手。

作为长期研究外卖骑手职业困境的社会学学者,孙萍也在一篇研究报告中谈到了这种顾客的最高权力。在骑手送餐的过程中,顾客可以洞悉骑手的一切——真实姓名、手机号、准时率、得到过几次打赏、取餐时间、送餐路线、还有多长时间到达。在订单进行的过程中,顾客还有权取消订单。

他们可以看到一切,所有的进程,但我们不知道他们是谁。而且一旦出问题,我们也不能像他们那样取消订单。一位骑手对孙萍抱怨道,他还分享了一个自己被取消订单的经历:

我手里有两个订单。一个1.5公里,剩余时间45分钟;另一个3公里,剩余20分钟。我先去送了远的那个。1.5公里的那位顾客生气了,因为他看到我的GPS经过他家却没有给他送餐。他很愤怒,取消了订单,还向平台投诉了我……

在《人物》的调查中,也有骑手讲了类似的经历,那天,顾客在接到餐后反问骑手,你不是只送我这一单吗?

越来越快的送餐速度,评价体系的完全倾斜,在系统的宠溺下,顾客们也变得越来越缺乏耐心。

10.jpeg

客户端和骑手端的送达时间不一致

家住上海的井井承认,自己已经被惯坏了。他平时工作忙,不会做饭,填饱肚子几乎全部依赖外卖。他常常在一家距离不远的轻食店点餐,据他回忆,过去,从下单到吃进凯撒沙拉里的第一颗小番茄,大约需要45分钟,为了打发时间,他通常会在等待的时候看一集45分钟的电视剧。最近,等待的时间稳定在了26分钟,但前不久有一次,骑手的送餐时间超过了30分钟,他变得无法忍受,连打了5个电话催单。

2017年,法国研究机构益普索(Ipsos)曾对中国12个省市的消费者进行了不耐烦调查,结果显示,移动端技术的发展让消费者在各个方面都变得越来越不耐烦,这种现象在经济发达地区以及年轻群体中越发显著,其中,北京地区的消费者最不耐烦。

面对越来越不耐烦的顾客,骑手们只好想尽各种办法安抚。

谈起这一点,王兵同样有一肚子的话可说——手里订单配送时间都差不多的情况下,他会先挑贵的送,因为,单价高的顾客通常更容易发脾气,怎么解释都不听,突然发个火儿,就说要退货。100多块钱的外卖,我哪有钱天天赔。

还有,要尽量满足顾客提出的送餐之外的需求,比如买烟买水,或者带支剃须刀到网吧。有段时间受抖音的影响,总有顾客要求王兵在送餐时画一只小猪佩奇,不画就给差评。王兵很生气,但也不得不画,买了张牛皮纸,画了个佩奇,还写了一句,你是不是傻?

配送,是一种以顾客为中心的社会表演。孙萍在调查报告中写道,她将骑手们取悦顾客、争取五星好评的行为称为情感与情绪劳动,在她看来,这部分的劳动常常被忽视,但它对骑手的折损和消耗,远大于体力劳动。

在同《人物》的交谈中,她提到了那位印象最深的骑手,他三天被偷了两次车,还被偷了三次电瓶,说着说着就哭起来了,他说,平台要求我们说『祝你用餐愉快』,大家都不认识,我从农村来的,之前都是种地,实在不好意思说这个,还有让人给我打五星什么的,我一个大男人,怎么去说啊?

在就SKP事件接受界面新闻采访时,上海交通大学公共经济与社会政策系副教授沈洋表示,尽管外卖骑手可能拥有月薪过万的工资,但他们仍处在阶层不平等中,是在牺牲了时间和健康的条件下赚更多钱的,要做更高强度的工作——包括体力上和情感上的——才能得到更多的工资。

王兵还在继续开发安抚顾客的新招数——夏天,很多人都会随餐多点一份杯装可乐,但今年夏天雨水多,他经常因为赶单子摔车,车一摔,可乐基本就没救了。如果跑回商家再补一份,不仅自己要搭钱,订单也必然超时。为了避免顾客发火,他的外卖箱里永远放着一瓶可乐,如果顾客的可乐洒了,他就找个没人的地方,把备用可乐灌进原来的纸杯,再把杯口来回擦上几遍,没有痕迹。他觉得,这个办法棒极了。

与此同时,在几个法律咨询网站上,也出现了一些惴惴不安的顾客,有人发帖问,我催单外卖小哥,导致对方车祸,我是否需要承担法律责任?问题下面,有律师回复:没有责任。

11.jpeg

外卖小哥应顾客要求画的小猪佩奇 图源网络

游戏

不久前,美团和饿了么先后公布了2020年第二季度财报。在这一季度,饿了么实现每单盈利转正,而美团则完成了了22亿人民币的净利润,同比增长95.5%,其中,外卖业务是美团实现盈利的最大功臣。

2020年8月24日,美团股价也再创新高,市值突破2000亿美元,成为港股第五大市值公司。

在此次长达半年的调查中,《人物》接触到了近30名外卖骑手,他们频繁提起的一个词却是:一毛钱。

一位湖南的美团骑手说,准时率低于98%一单扣一毛钱,低于97%一单扣两毛钱。这不就是逼着骑手们加快速度吗?毕竟,一单中的一毛钱对于我们来说,差很多很多的。

一位上海的饿了么骑手说,饿了么单价最低是4.5元,跑得越多,单价越高,有时候多一毛钱都觉得很感人,4块9和5块,看着都不一样。

为了留住这一毛钱,骑手们不仅需要跑得更快,还要跑得更多。

这也是系统希望看到的,因为,在系统中,还藏着的另一个秘密——一个关于等级的游戏。

无论是美团还是饿了么,系统都为骑手设置了积分等级体系——跑的单越多,准时率越高,顾客评价越好,骑手获得的积分便会越高,积分越高,等级就越高,奖励收入也会更多——系统还将这种评价体系包装成了升级打怪的游戏,不同等级的骑手,拥有不同的称号,以美团为例,这些称号从低到高分别为普通、青铜、白银、黄金、钻石、王者。

一位东南某城市的美团众包骑手讲述了具体的等级设置:一周之内,完成有效订单140单,准时率达到97%,将成为白银骑手,每周可获得140元的额外奖励,若完成有效订单200单,准时率达到97%,则会成为黄金骑手,每周额外奖金220元。在饿了么,单量则直接与配送费挂钩,每月完成订单数在500以内,每单5元;500到800单,每单5.5元;800到1000单,每单6元……依次类推。而在游戏规则中,积分将以周或月为单位清零。

在研究报告《订单与劳动:中国外卖平台经济视野下的算法与劳动探究》中,孙萍表示,在超时的惩戒之外,系统还用这种游戏化的评估方式,将很多骑手卷进了一个无法停歇的循环,他们希望我们夜以继日地工作,一位骑手对她说,但他们却无法脱身,我上个月已经是黑金骑士了,如果我想维持,我还需要832点,还有很多活儿要干。

等级越高,骑手们面临的维持等级的压力就越大。在孙萍看来,这种游戏化的包装,不仅具备成瘾的可能性,还巧妙地把骑手的自我价值实现与资本管理结合在一起,而游戏化的外衣,则为算法的剥削进行了普遍的、内化的、合理的解释。

12.jpeg

累瘫在路边的骑手

据美团公布的《2020年上半年骑手就业报告》显示,目前,美团的骑手总数达到295.2万人。而饿了么蜂鸟即配官网显示的骑手数量则为300万人。面对近600万骑手的系统化生存,华中师范大学社会学者郑广怀提出了下载劳动的概念。

在调查报道《武汉市快递员外卖员群体调查:平台工人与下载劳动》中,郑广怀团队对这一概念进行了深入的阐释——

骑手们通过下载app进行工作,表面上,这个app只是一个辅佐他们工作的生产工具,但实际上,骑手们下载的则是一套精密的劳动控制模式,在这套模式下,工人原有的主体性被全面塑造乃至取代,他们看似用更自由的方式在工作,但同时却遭受着更深切的控制。

平台通过下载劳动创造『平台工人』。郑广怀团队写道,而这种劳动模式的特点则为:强吸引、弱契约、高监管以及低反抗。

协助系统完成下载劳动的媒介,则是骑手们自己的手机——作为最重要的劳动工具,在公开报道中,外卖平台一直在努力帮助送餐的骑手们摆脱手机。

我们就怕骑手路上为了接单出事。2018年4月,在接受36氪采访时,美团外卖配送算法团队负责人何仁清特别提到,对于美团而言,最棘手的问题就是如何让骑手在骑车过程中不要看手机。

为此,美团耗时7个月研发了内置智能语音交互系统的蓝牙耳机,据何仁清介绍,这款耳机防风防水去噪且智能,骑手们只要带上它,便可通过说话完成所有操作,确保在送餐的过程中摆脱手机。

而现实中,所有与《人物》有过交流的美团骑手,没有一人收到或使用过这款智能蓝牙耳机,也没有一位骑手能真正摆脱手机。

尽管只体验了几天外卖员的生活,曹导仍对那种被手机支配的恐惧心有余悸,就是你导着航,系统这边还要不停地提醒你说,美团众包又有新订单,请及时查询,然后又跟导航的声音混在一起,马上又要超时了,有的顾客会打电话问你到哪儿了,你可能还要边导航边接单,再边接电话跟他解释为什么超时了……曹导说,那种感觉让她觉得,每一分钟都很重要,每天都被追着跑,只能快,更快。

13.jpeg

被手机支配的外卖骑手

电动车

我们永远不可能在路上耽误时间,在路上的时间是最快的。一位饿了么骑手告诉《人物》,另一位美团骑手则表示,一个订单能够真正掌握在自己手里的,只有跑在路上的那段时间,除非有个交警跟在屁股后面,说你不能超速不能超速,不然单子多的时候,所有骑手都想着飞起来。说完,他又补充了一句,飞都来不及。

此时,能帮助他们的,只有自己骑着的电动车。

在上岗之前,骑手们需要自己解决电动车的问题。通常,配送站都有长期合作的第三方公司,为骑手提供电动车的租赁。为了节约成本,大多数骑手会选择租金在几百块的车,而这些车的车况也大多一言难尽——有的没有后视镜,有的脚踏板和车头被胶条缠绕了七八圈,一位骑手说,跑外卖之后,自己变成了电动车修理大师。

如果不想租,有的站点也会引导骑手用分期付款的方式买车。

一位成都的美团骑手在站点的要求下,用高出市场价1000元的价格买了一台不知名品牌的电动车,还有一位骑手表示,自己花了好几千通过站点购买的电动车,刚跑了没两天,电池就坏了。

比起这些花了太多冤枉钱的同行,美团骑手王福贵觉得自己幸运多了。他只不过是在成为骑手的第一天,和电动车的电池一起飞了出去,头还被卡在了马路中间的护栏里——那辆车是他通过站点租的,月租金200元,基本就是一堆零件拼拼凑凑攒起来的,没有车灯,刹车片也被磨没了,有时候踩刹车,它会往前走,但踩油门时,反而会倒退。

但这都不成问题。摔车的第二天,他花了10块钱自己装了一枚脚刹片,跑夜班的时候,他会在嘴里含一个小手电代替车灯,或者把手电用胶条粘在车头。毕竟,这台车也是有优点的,速度极快,最快能跑到时速65公里。王福贵说。

根据公安部在2018年发表的数据,2013-2017年间,我国共发生电动自行车肇事致人伤亡的道路交通事故5.62万起,造成死亡8431人,直接财产损失1.11亿元。为了进一步规范电动车的使用,2019年4月,全国正式实行电动车新国标——根据规定,电动车时速不得超过25公里/小时,而一台符合新国标标准的电动车,至少要卖到1000元以上。

只是,在《人物》此次调查接触到的近30名外卖骑手中,无论美团还是饿了么,没有一人的电动车符合新国标,这些电动车的时速一般都能跑到40公里左右,远远超过限速。骑手群和贴吧里,还有很多人交流如何通过改装,让新买的电动车解除限速。

做了一年多骑手,那台破车闹罢工的频率越来越高,王福贵有时不得不打车去送餐——好在他所在的西北某县城面积小,与其骑着罢工的电动车每单都超时,打一辆出租车反倒更实惠,花50块就能轻轻松松送完十几单。

后来,为了跑得更快,他还是咬咬牙自己掏钱买了一辆新车,至于之前的那台破车,不知道又被拆成了多少零件装在了多少等待出租的电动车上。

无论是骑着旧车还是新车,王福贵的业绩始终排在地区的前五、前三,但干了没多久,他还是辞职了,因为无法忍受平台的拉新要求,美团为了扩张,让我们上街拉客。每天要拉两个从没下过美团app的人注册,我刚开始还忍着拉了几天,后来,实在受不了了,就跑了。

14.jpeg

外卖骑手和他的电动车

微笑行动

在外卖骑手已成最高危职业成为热门话题后,系统也做出过努力。

在平台成立的早期,无论是美团还是饿了么,都有针对骑手的安全培训,只是大都集中在入职阶段,专送和众包骑手都需要经过一个简单的安全知识测试,才能开始跑单。

对于专送骑手,站长也会时常叮嘱安全问题。一位美团站长告诉《人物》,每次做安全培训,他都会特意放一段自己做的小视频,全是电动车车祸事故集锦,让300多号骑手围着看,看完之后,他还会语重心长一番,我知道你们很急,逆行也不可避免,但麻烦多看看路。这也是另一位饿了么配送站站长的心声,说再多遍,骑手们心里装的都还是时间第一,有时候也不是很珍惜自己,终归还是怕超时。

后来,随着外卖骑手交通事故率不断增高,为了进一步提升骑手的安全意识,外卖平台也想了一些办法,例如请交警去站点讲课,或者组织骑手去交警队考试……美团还为骑手们设计了一对袋鼠造型的黄色耳朵,这些耳朵上大都写着与速度、安全有关的口号。最常见的耳朵上,正面写着送餐再忙,安全不忘,背面写着美团外卖,送啥都快——但在现实中,这两者依然很难兼得,多数骑手都不愿意戴上这对耳朵,因为太麻烦了,一位骑手告诉《人物》,只要速度一快,耳朵就会被风吹掉。

15.jpeg

美团袋鼠造型的黄色耳朵

为了安全,系统还被植入了一项新功能——在骑手上线之后,不定时随机弹出安全教育视频。

经常跑着跑着就被限制接单了,必须立刻停车看,看完接单系统才恢复正常。湖南的美团骑手阿斗说,一次送餐高峰期,他不得不停车在路边观看突然弹出的安全教育视频,结果被一辆飞驰的自行车撞倒,脚踝扭伤,被迫休息。

每天都生活在超时的恐惧中,还要时不时在送餐路上观看安全教育视频,对此,骑手们大多都揣着不满。但有时,他们也会庆幸,自己手机中弹出的是安全教育视频,而不是另一个更要命的惊喜——微笑行动。

2017年6月左右,美团开始实施微笑行动。这是一项系统的抽查举措,同样是不定时、随机的模式,被抽到的骑手也需要立即停车,然后拍摄从胸部到头顶的照片,并保证面部清晰,展现头盔、工服、工牌——这一切,需要在5分钟之内完成,如果没有及时上传照片,或者照片内容不合格,系统都有可能判定审核失败,骑手们将会面临少则300元,多则1000元的罚款,还有可能被封号三天或永远封号。

自从微笑行动上线,它就变成了美团骑手们心中的玄学。

关于它出现的时刻,每位美团骑手的答案都不同——在爬楼的时候,在等电梯的时候,在等餐的时候,在爆单的时候……

令阿斗最难忘的一次微笑行动,出现在大暴雨爆单的时候。那天,他穿着雨衣,路都看不太清楚,还需要把车停在路边,把雨衣脱下来,露出工牌和衣服,拍一张照片。同站点的另一位骑手因为手机在口袋里没有听到提示音,最终被罚款400元。

同样是雨天,今年2月,江西南昌的一位脑瘫骑手因为没来得及拍照,导致账号被封,好在事件的相关视频在抖音上引发了广泛关注,在收到无数网友反馈后,美团官方迅速解封了他的账号。

16.jpeg

错过了微笑行动的南昌骑手

但并不是每一位骑手都能获得这样的特殊对待。

在美团骑手群和贴吧里,每天都有人重复同一个话题——我的照片明明符合要求,但却被判定审核失败,向客服申诉得到的结果是,系统原因,无法解封。我们的声音永远抵达不了上层。一位骑手抱怨道。

与此同时,一些并不符合要求的照片却通过了审核。一位深圳骑手透露,自己被封号后一直用妻子的账号登陆跑单,但自己的照片也能顺利通过微笑行动的审核。还有的骑手会提前存好一张别人的自拍,也照样通过了审核。

疫情之后,佩戴口罩也成为了微笑行动的检测项目,一位湖北骑手说,自己的口罩被雨水打湿了,还没有来得及更换,系统审核不通过,账号被停止接单。而另一位广东骑手拍了一张用手捂住嘴巴的照片,却顺利通过了。

去年冬天,在内蒙古海拉尔,一位美团骑手在送餐途中被抽中,零下30℃的气温中,他只能把车停在路边,脱下所有的防寒衣物,露出美团制服和头盔,在5分钟之内拍照并上传——在《人物》接触到的美团骑手中,对于微笑行动,他们的评价大多是——可怕的、没有感情的、耽误工夫的。

饿了么也有类似的检测行动,取名蓝色风暴,不同的是,蓝色风暴给骑手的时间是15分钟,罚款力度也相对较小,大多在5元到30元之间——《人物》在2019年进行调查时,并没有饿了么骑手抱怨过此项检测行动。

只是,好景不长,一则最新的消息是——据饿了么骑手透露,为了全面追赶美团,今年,饿了么蓝色风暴的检测时间也从15分钟缩短到了5分钟。

17.jpeg

骑手群讨论微笑行动

五星好评

随着外卖骑手违章率和事故率越来越高,交警也从局外人变成了与系统有关的人。

熊崇君是一名深圳交警,做了近10年的交通节目外景主持,因多段执法视频在互联网上走红,成为网红交警,人称深圳熊警官。去年夏天,因为罚两位逆行的美团骑手写检查并大声朗读,熊警官制造了一次热搜——#你的外卖员没到可能在写检讨#,有网友评论,熊警官太温柔,罚得太轻了。

事实上,近两年内,全国各地的交管部门出台了各种针对外卖骑手的交通处罚政策。

在上海浦东,外卖骑手们被交警部门要求穿上印有个人专属编号的电子马甲,同时,一人一张外卖骑手交通文明记分卡,每张卡36分。执勤交警与监控探头同时执法,不穿马甲扣12分,驾驶未登记备案电动车扣12分,闯红灯扣6分,逆行扣3分,在机动车道骑行扣3分,在人行道骑行扣3分……36分扣完后,骑手会面临直接永久封号或被公司开除——上海浦东也是全国首个执行骑手电子马甲政策的地区。

河北邢台、广东深圳等地也先后学习上海,引入了文明积分卡制度;青岛则开展了违法外卖骑手黑名单制度;在江苏,外卖骑手交通违法1次停工1天,南京交管部门还会给二次违法的外卖骑手开展学习日。

18.jpeg

民警向骑手讲解DS骑手记分小程序的使用方法

只是,在超时的巨大威慑力之下,这些举措收效甚微。

2019年12月和2020年5月,《人物》分别两次前往上海浦东陆家嘴地区,实地观察外卖骑手穿戴电子马甲的情况。根据一小时内通过世纪大道的骑手数量统计,白天,由于执勤交警多,这一区域内穿电子马甲的骑手比例可以达到70%以上。只是,即便穿着马甲,依然有骑手会选择违章。

这是骑手们精心计算过的结果。白天交警多,不穿马甲容易被抓,一扣就是12分,但如果穿着马甲违章被拍,闯红灯、逆行都是小分啦。 而进入夜晚后,骑手们穿马甲的比例会大幅下降,原因很简单,交警下班了。

作为执法者,包括熊警官在内的很多交警心情复杂,他们是目睹外卖骑手交通违章最多的人,有时,也很理解骑手的处境。

熊警官告诉《人物》,他经常出现在外卖骑手的车祸现场,翻车的,撞车的,撞人的,被撞的……据他观察,所有骑手摔倒后的第一反应,都是赶紧爬起来,去看外卖洒没洒,然后打电话给客人解释,没有人在乎自己。

这让他更非常理解骑手们的不易。熊警官说,他经常和外卖骑手聊天,发现这个群体的想法很简单,就想着不超时,不被顾客差评,不太把自己放在心上,人身安全永远都不是他们的重点,如何准时地把餐送到顾客手上,才是他们的重点。

作为一名一线交警,在熊警官看来,造成这一切的,是外卖平台之间的激烈竞争,同时,也暴露了很多城市非机动车道不足的问题。公司之间竞争导致送餐时间缩短,骑手越来越紧张,一边是超时,一边是违法,他们必须选择一条路走。

因此,每当遇到骑手违章,在执法的同时,有些交警也会表达体谅,罚骑手写检查的那天,熊警官就特意叮嘱对方去树荫下写,而很多交警还需要帮骑手们去送餐。

公开新闻报道中,类似的事件,不胜枚举。

今年3月25日,一位浙江桐乡的外卖骑手因逆行被交警拦下,被罚站在路口参与交通劝导。他告诉交警,自己刚接了一个订单,还没来得及取餐,如果超时就要被扣钱。最终,交警委托一名辅警骑着骑手的电动车去送餐,一路上,那辆电动车熄火3次,终于到了顾客家楼下,辅警一低头,餐打翻了。

好在这种状况并不常出现,大部分交警还是顺利地完成了送餐任务——

4月16日,江西南昌,一位美团外卖骑手急着送餐连续三次违章,被交警拦下来接受处罚;6月初,浙江温州,一名饿了么骑手违规驾驶摩托车被查扣;6月29日,广东东莞交警在执法时,发现一名美团骑手摩托车未悬挂机动车号牌,随即将车当场查扣——这些骑手未能送完的订单,都由交警或辅警帮忙送达。

送餐完成后,几乎所有的送餐交警还会做同一件事——对点餐的顾客说:祝你用餐愉快,麻烦给一个五星好评。

19.jpeg

交警帮助骑手完成送餐任务 图源搜狐视频

最后一道屏障

在《人物》此次调查接触到的所有外卖骑手中,石沉是个独特的存在。因为宁愿扣钱也不想玩命,他坚称自己在一年多的骑手生涯中,从未闯过红灯,也绝不逆行,每天送餐,制服和头盔都穿戴整齐。

但他依然遭遇了车祸。2019年7月的某天晚上,他送餐时被一辆小客车撞倒,右脚脚踝骨折,交警到达后判定对方全责。被送去医院后,车主负担了包括手术在内的全部医疗费用。

作为专送骑手,站点每个月都会从石沉的工资中扣除106元保险费,这其中包含意外险,正常情况下,石沉还可以获得这笔赔付。但当他出院后联系站点时却发现,自己的骑手账号已经被删除。

对此,站点给出的理由是,他因住院手术长时间不能跑单,上岗率不达标,已被系统删号——随着骑手账号一同消失的,还有账号上的保险缴纳记录,没有记录,他也法找保险公司理赔。为了找回记录,他试图通过站点与美团沟通,却发现自己被踢出了站点群。

在外卖骑手群体中,石沉的遭遇并非个案——在系统中,保险是骑手们能获得的唯一也是最后一道安全保障,但《人物》在调查中发现,大量的骑手在遇到交通事故后,都无法顺利获得理赔。

按照外卖平台的设计,专送骑手的保险由站点按月扣除,具体金额也由站点决定;众包骑手的保险则按天扣除,每天3元,保障时间从骑手当天第一次接单到当日24时,如果此时骑手还在送餐,保险时间最多可延长一个半小时。

在社会学者郑广怀看来,这种劳动保障体系,其实是外卖平台对于自身责任的一种巧妙转嫁。

今年五一劳动节期间接受界面文化专访时,郑广怀将外卖平台形容为甩手掌柜,平台将派送业务承包给外包公司,解除了(与工人)直接的雇佣关系。保险问题由工人购买意外伤害险,工人发生交通事故,平台则可以推给保险公司。郑广怀说,在这种转嫁之中,模糊的劳动关系也使工人们维护权益变得更加困难。

孙萍也在调查中发现,如果是小剐小蹭,她接触到的大部分外卖骑手都会选择自己忍受。他们中很多人跟我反馈说,那个申请流程特别复杂,特别麻烦,他们宁愿自己承受,也不愿意去走那一套复杂的流程。

20.jpeg

骑手在骑手社区讲述自己发生车祸

只是,一旦事故超出小剐小蹭的范围,石沉的故事就会一再上演。

一位在饿了么跑众包的骑手告诉《人物》,他在送餐中出了交通事故,把行人撞进了医院,保险公司拖延了一年还没赔偿,最后,他借了网贷垫付医疗费;

一位宿迁骑手则在入职美团时,被站长要求填写自愿放弃保险合同保证书。他感到不解,站长告诉他:骑手是最高危的职业,每天都有可能是最后一天,我们这儿无人敢保——这种状况也并非个案,曾做过美团配送站站长的金壮壮说,众包骑手的保险直接通过app缴纳,是必选项,而专送骑手的保险则由站点缴纳,很多站点因为怕麻烦,就没有给骑手上保险。

权益无法得到保障的,还有被外卖骑手撞伤的行人。

去年4月,林伟在回家路上被一位美团骑手撞倒,左腿骨折,当天是这位骑手第一天上班,站点负责人表示,保险还没来得及买,以及,此事也与站点无关,我们只让骑手送外卖,可没让他去撞人啊。这位负责人说。

数次沟通后,站点拿出的处理意见是:可以帮忙说服骑手分期支付医疗费、营养费。

最后,这件事的解决依靠的是关系——林伟的公司领导认识美团的某位高层,在高层的施压下,站点最终同意支付医疗费用。

社交平台上,一位美团骑手维权的帖子下,一位网友留言道:外卖员帮美团跑出了单量、跑出了市值,但美团,一个靠外卖业务做大的公司,却不会给任何一位外卖员提供正式的劳动雇佣合同。

车祸过去一年后,石沉的骑手账号仍然没有恢复,他也没能获得那笔意外险的赔偿。他告诉《人物》, 我决定离开这个行业,不再回来了。而那些还在路上拼命抢时间的骑手,则只能在心中默默祈祷——曾在路口目睹过同行当场丧命的美团骑手魏莱,在自己的网络日记中写道,愿天下骑手都能平安回家。

无限游戏

在发布外卖骑手体验视频时,曹导正在自驾环中国拍摄新的作品,在前往西藏无人区的路上,跟《人物》回忆起自己做骑手的那几天,她仍感觉窒息。

作为系统的短期体验者,曹导提出了一个建议:可以让外卖平台所有的产品经理和算法工程师都去当一个月骑手,这样。他们才会知道这个系统对人的压迫有多么严重。

在一篇讲述美团系统如何将配送时间缩短至28分钟的报道下,一位骑手也提出了相同的建议:要不你们亲自来一线送个三两天试试?看看不闯红灯、不逆行、不狂飙,你的28分钟怎么送。

某种程度上,这种建议与数据社会学家尼克·西弗不谋而合。

西弗曾提出过算法文化的概念。在他看来,算法不仅由理性的程序形成,还由制度、人类、交叉环境和在普通文化生活中获得的粗糙-现成的理解形成。他认为,算法是由人类的集体实践组成的,并建议,研究者应该人类学地探索算法。

作为学者,孙萍完全认同西弗的观点,但现实中的算法,依然更多地建立在数字逻辑的基础上。

加强程序员的培训和价值导向很重要。但目前国内的情况是,程序员大部分都是理工的直线性思维,很少有社会科学的这种思维,所以,他们对于公平和价值的这些问题,理念上都比较欠缺。

在调研的过程中,孙萍也与一些参与算法的程序员有过交流,她发现,程序员们有自己的逻辑,也会考虑到各种突发事件,但是,程序员只是执行者,并不是规则的制定者,规则的制定者是外卖平台,而程序员也只是在履行平台的决定。

本次调查中,《人物》也多次尝试联系外卖平台的算法团队,但对方均以公司要求之名拒绝讨论系统的话题,这是公司机密,一位美团的算法工程师表示。

孙萍说,单项话语权是目前这套算法最大的问题。而在整个系统中,最无解的部分在于,在让骑手们越跑越快的推手中,也包括骑手自己。

这是一个更大、也更不可见的游戏——外卖员每跑一单的任何数据都会被上传到平台的云数据里,作为大数据的一部分。孙萍说,系统要求骑手越跑越快,而骑手们在超时的惩戒面前,也会尽力去满足系统的要求,外卖员的劳动越来越快,也变相帮助系统增加了越来越多的『短时长数据』,数据是算法的基础,它会去训练算法,当算法发现原来大家都越来越快,它也会再次加速。

在孙萍看来,外卖骑手在送餐过程中产生的数据依然存在所有权争议问题,但骑手们仍在奋力奔跑。据美团最新公布的数据显示,2020年上半年,遍布在全国2800个县市区的骑手不顾疫情、不分昼夜,将餐、菜、药等生活必需品及时送到了超过4亿的用户手中。

美团市值突破2000亿美元的新闻发布后,一片惊叹声中,有人再次提及王兴对速度的迷恋,还有他曾提起过的那本对自己影响很大的书——《有限和无限的游戏》,在这本书中,纽约大学宗教历史系教授詹姆斯·卡斯将世界上的游戏分为两种类型:有限的游戏和无限的游戏,前者的目的在于赢得胜利,而后者则旨在让游戏永远进行下去。

系统仍在运转,游戏还在继续,只是,骑手们对自己在这场无限游戏中的身份,几乎一无所知。他们仍在飞奔,为了一个更好生活的可能。

22.jpeg

(应采访对象要求,文中骑手皆为化名)

参考资料

1. 文森特·莫斯可《数字劳工与下一代互联网》

2. 郑广怀等《“平台工人”与“下载劳动”:武汉市快递员和送餐员的群体特征与劳动过程》

3. 孙萍《“算法逻辑”下的数字劳动——一项对平台经济下外卖送餐员的研究》

4. 孙萍《如何理解算法的物质属性——基于平台经济和数字劳动的物质性研究》

5. 孙萍《订单与劳动:中国外卖平台经济视野下的算法与劳动探究》

6. 姚建华《零工经济中数字劳工的困境与对策》

7. 卢泰宏 杨晓燕《消费者行为学:中国消费者透视》

8. 让·鲍德里亚《消费社会》

9. 潘仁杰《透析数字时代的科技迷思——传播政治经济学家文森特·莫斯可教授访谈录》

10.汪佩洁《算法时代的劳动社会学——评Alex Rosenblat《优步的世界:算法是如何改写工作规则的》》

11. 界面新闻 林子人《专访社会学者沈洋:服务业男女工人以不同方式处于劣势,性别阶层户口不平等彼此交织》

12. 丁晓东《平台革命、零工经济与劳动法的新思维》

13. 陈龙《游戏、权力分配与技术:平台企业管理策略研究——以某外卖平台的骑手管理为例》

14. 蜂鸟配送 《2018外卖骑手群体洞察报告》

15. 比达咨询 《2018年第1季度中国即时配送市场研究报告》

16. 中国物流与采购联合会和美团点评 《2018中国即时配送行业发展报告》

17. 联商网零售研究中心《2019即时配送发展报告》

18. DCCI互联网数据中心《网络外卖服务市场发展研究报告》

19. 极光大数据 《2019外卖行业下沉市场分析报告》

20. 点我达营创实验室《2019众包骑手生存真相报告》

21. 媒报告《2019中国即时配送市场研究报告》

22. Trustdata 《2019年上半年中国外卖行业发展分析报告》

23. 美团研究院《2019年及2020年疫情期间美团骑手就业报告》

24. 美团研究院《2019年及2020年上半年中国外卖产业发展报告》

25. Fastdata极数《2020年1-4月中国本地生活外卖行业发展分析报告》

26. 美团技术团队《即时配送的订单分配策略:从建模和优化》

27. 美团技术团队《美团智能配送系统的运筹优化实战》

28. 美团技术团队《配送交付时间轻量级预估实践》

29. 美团研究院中国饭店协会《中国外卖产业调查研究报告(2019年前三季度)》

30. 雷锋网 AI 研习社《专访美团点评 AI 技术团队负责人何仁清:全球规模最大的智能配送调度系统是如何建成的》


文|赖祐萱,原文转自:https://baijiahao.baidu.com/s?id=1677231323622016633

那些被困在系统里的外卖骑手(上)

科技前线梅川酷子 发表了文章 • 0 个评论 • 66 次浏览 • 2020-09-10 11:28 • 来自相关话题

一系列交警部门公布的数据背后,是外卖员已成高危职业的讨论。一个在某个领域制造了巨大价值的行业,为什么同时也是一个社会问题的制造者?为了找到这个问题的答案,《人物》团队进行了近半年的调查,通过与全国各地数十位外卖骑手、配送链条各环节的参与者、社会学学者的交流,答... ...查看全部

一系列交警部门公布的数据背后,是外卖员已成高危职业的讨论。

一个在某个领域制造了巨大价值的行业,为什么同时也是一个社会问题的制造者?为了找到这个问题的答案,《人物》团队进行了近半年的调查,通过与全国各地数十位外卖骑手、配送链条各环节的参与者、社会学学者的交流,答案渐渐浮现。

文章很长,我们试图通过对一个系统的详细解读,让更多人一起思考一个问题:数字经济的时代,算法究竟应该是一个怎样的存在?

收到

又有两分钟从系统里消失了。

饿了么骑手朱大鹤清晰的记得,那是2019年10月的某一天,当他看到一则订单的系统送达时间时,握着车把的手出汗了,2公里,30分钟内送达——他在北京跑外卖两年,此前,相同距离最短的配送时间是32分钟,但从那一天起,那两分钟不见了。

差不多相同的时间,美团骑手也经历了同样的时间失踪事件。一位在重庆专跑远距离外卖的美团骑手发现,相同距离内的订单,配送时间从50分钟变成了35分钟;他的室友也是同行,3公里内最长配送时间被压到了30分钟。

这并不是第一次有时间从系统中消失。

金壮壮做过三年的美团配送站站长,他清晰地记得,2016年到2019年间,他曾三次收到美团平台加速的通知:2016年,3公里送餐距离的最长时限是1小时,2017年,变成了45分钟,2018年,又缩短了7分钟,定格在38分钟——据相关数据显示,2019年,中国全行业外卖订单单均配送时长比3年前减少了10分钟。

系统有能力接连不断地吞掉时间,对于缔造者来说,这是值得称颂的进步,是AI智能算法深度学习能力的体现——在美团,这个实时智能配送系统被称为超脑,饿了么则为它取名为方舟。2016年11月,美团创始人王兴在接受媒体采访时表示:我们的口号『美团外卖,送啥都快』,平均28分钟内到达。他说,这是一个很好的技术的体现。

而对于实践技术进步的外卖员而言,这却可能是疯狂且要命的。

在系统的设置中,配送时间是最重要的指标,而超时是不被允许的,一旦发生,便意味着差评、收入降低,甚至被淘汰。外卖骑手聚集的百度贴吧中,有骑手写道,送外卖就是与死神赛跑,和交警较劲,和红灯做朋友。

为了时刻警醒自己,一位江苏骑手把社交账号昵称改成了:超时是狗头。一位住在松江的上海骑手说,自己几乎每单都会逆行,他算过,这样每次能节省5分钟。另一位上海的饿了么骑手则做过一个粗略的统计,如果不违章,他一天能跑的单数会减少一半。

骑手们永远也无法靠个人力量去对抗系统分配的时间,我们只能用超速去挽回超时这件事。一位美团骑手告诉《人物》,他经历过的最疯狂一单是1公里,20分钟,虽然距离不远,但他需要在20分钟内完成取餐、等餐、送餐,那天,他的车速快到屁股几次从座位上弹起来。

超速、闯红灯、逆行……在中国社科院研究员孙萍看来,这些外卖骑手挑战交通规则的举动是一种逆算法,是骑手们长期在系统算法的控制与规训之下做出的不得已的劳动实践,而这种逆算法的直接后果则是——外卖员遭遇交通事故的数量急剧上升。

孙萍从2017年开始研究外卖系统算法与骑手之间的数字劳动关系,在与《人物》的交流中,谈及越来越短的配送时间与越来越多的交通事故的关系时,她表示,肯定是(最重要的原因)。

现实数据有力地佐证了这一判断——2017年上半年,上海市公安局交警总队数据显示,在上海,平均每2.5天就有1名外卖骑手伤亡。同年,深圳3个月内外卖骑手伤亡12人。2018年,成都交警7个月间查处骑手违法近万次,事故196件,伤亡155人次,平均每天就有1个骑手因违法伤亡。2018年9月,广州交警查处外卖骑手交通违法近2000宗,美团占一半,饿了么排第二。

大雨

根据系统的设置,在骑手们回复收到之后,它便开始运转。

2019年,在ArchSummit全球架构师峰会上,美团配送技术团队资深算法专家王圣尧介绍了这个智能系统的基本运行——

从顾客下单的那一秒起,系统便开始根据骑手的顺路性、位置、方向决定派哪一位骑手接单,订单通常以3联单或5联单的形式派出,一个订单有取餐和送餐两个任务点,如果一位骑手背负5个订单、10个任务点,系统会在11万条路线规划可能中完成万单对万人的秒级求解,规划出最优配送方案。

但在现实中,想要击碎这种最优,一场大雨就足够了。

对于雨,骑手们的态度都很摇摆,他们喜欢雨,因为雨天订单会变多,但如果雨下得太大,系统会很容易爆单,自己也容易出事儿。

湖南美团骑手庚子遭遇过一个可怕的雨夜。暴雨不停歇地下了一整天,订单疯狂涌入,系统爆单了。站点里每个骑手都同时背了十几单,箱子塞满了,车把也挂满了。庚子记得自己的脚只能轻轻地靠在踏板边缘,边跑边盯着摞在小腿中间的几份盒饭不会被夹坏。

路太滑了,他摔倒了好几次,然后迅速爬起来继续送,直到凌晨两点半,他才把手上所有订单全部送完。几天后,他收到了当月的工资条,数字居然比平时低很多——原因很简单,大雨那天,他送出的很多订单都超时了,因此,他被降薪了。

被扣工资的不只是庚子,还有配送站的站长。

吃数据饭的。美团配送站站长金壮壮这样定义自己。对于一个配送站,最重要的数据包括:承接的单量、超时率、差评率、投诉率,其中,超时率是重中之重,因为,很多差评和投诉的原因,也是超时。

通常,骑手们的超时率不得高于3%,如果达不到,站点的评级将会下降,整个站点的配送单价也会下降,包括站长、人事、质控等在内的所有人,甚至与站点相关的渠道经理、区域经理,收入都会受到影响。

每年年末,站点还要面临美团和饿了么平台的考核,每个区域内考核排名后10%的配送站,会面临淘汰的风险。

在系统的这套评价体系下,超时带给骑手们的不仅是收入的损失,还包括精神上的二次伤害。

他会变成团队中的一根刺。孙萍说,超时严重,不但要扣钱,还要扣大钱,紧接着还有团体荣誉的问题。他给大家拖后腿,站长会找他,站长找完片长会找,片长找完之后,区长找,各种各样的找。大家都不喜欢他。

这会带给骑手巨大的精神压力。和麻辣香锅一同摔在路上的朱大鹤告诉《人物》,自己做骑手的前几个月,每一天都是在沮丧中度过的。

他从小地方来,不熟悉北京的路,更别提那路上巨大的车流人流,他战战兢兢地守着规矩,天天因为超时被扣钱,这让他觉得自己很无能,不是说外卖员收入过万吗?不是人人都送得了外卖吗?为什么我做不好?他说,自己好像不是当外卖员的料。

后来,随着电动车越骑越溜,路越来越熟,他从新手变成了马路上抢时间的高手,那种无能感才渐渐消失,与超时相比,逆行算不了什么。他说,和同行们扎堆逆行的时候,自己甚至能体验到一种顺畅感。

如今,在正常情况下,朱大鹤已经极少超时,但极端的恶劣天气,仍然是他逃不出的魔咒,这种时候,失控的系统会将他一并卷入——背着超量的订单,完全失去对配送时间的控制,还要面临超时的惩罚,且不可以请假。

3.jpeg

在大雨中送餐的外卖骑手

2019年8月,台风利奇马袭击上海,一位饿了么骑士在雨中配送时不慎触电身亡,随后,一张配送站的微信群聊截图被传上了社交网络,截图中,站长@所有人,未来三天不准假……未来三天找不到人直接双倍旷工处罚。收到回复。站长发出的指令下,是一长串骑手们回复的代表收到的1。

这张截图引发了巨大的舆论争议,有网友表示,台风天,为什么盒马、肯德基、麦当劳都可以暂停配送,而外卖平台却不能?

对此,美团站长金壮壮只能表示无奈。每次下暴雨,骑手们都会来找他请假,爆胎了,摔跤了,家里人出事了,各种各样的理由。但面对大量涌入的订单,为了站点的数据,他只好强行规定,除了生老病死,恶劣天气不能请假,请假直接罚款。

暴雨天,也是金壮壮最累的时候,他必须坐在站点的电脑前,时刻监控着每个骑手的位置,背负的单量,送达的时间。他所属的站点,美团规定每个骑手一次最多只能接12单,超过12单,系统便会停止派单。但遇到恶劣天气或重大节日,这远远无法承载涌进来的巨大单量,这种时候,系统也最容易崩溃:有的骑手背着成倍的订单,有的骑手几乎没有单子;有的骑手接到了方向完全相反的单子;距离近的单子配送时间比距离远的还长……

此时,金壮壮需要扮演另一个角色——人工调度。在这个身份下,他可以进入系统,将A骑手的订单移给B骑手,以求运力的平衡。虽然系统封顶12单,人工改派却不受限制,只要有人调控,骑手手中的订单数字可以变成一个非常恐怖的数字——一位骑手最多时同时背着26单;一个配送站的30多个骑手,曾在3小时内消化了1000份订单;还有一位骑手在50万人口的县城跑单,高峰期也同时被分配了16单。

一位饿了么的站长告诉《人物》,这种人工干预并不是来拯救骑手的,而是为了把每一个骑手的潜能和速度挖掘到最大限度。

骑手的潜能被挖到极致,如果还不行,金壮壮便会自己出去跑单,最多的一次拿了15单,(爆单了)先让骑手熬一段时间,熬不了了,只能向美团申请,把配送范围缩小。2018年后,我们站点已经不允许申请了,单子再多,都要跑下去。他说,在爆单时送餐,送到最后,整个人都麻木了,全凭本能在跑,没有了人类的情绪反应。

去年,因为家人生病,金壮壮离开了这行。他说自己不会再回来,最近有朋友想包下一个外卖站点,也被他劝住了,这个行业给人时间的压迫感,数据的压力,是你想象不到的。今年夏天南方大雨,金壮壮一边庆幸自己脱身了,同时也担忧,不知道又有多少站点爆单,又有多少骑手需要拼了命地把数据追回来。

4.jpeg

外卖小哥在暴雨中涉水而行

导航

为了完成课题研究,孙萍在近4年的时间里接触了近百名外卖骑手,其中很多人都曾抱怨过系统给出的送餐路线。

为了让骑手更专注地送餐,这个智能系统会最大限度地取代人脑——帮骑手规划多个订单的取送餐顺序,并为每一单提供送餐路线导航,骑手们不需要自己动脑,只需要根据系统的提示去完成,也同时承担被带入歧途的风险。

有时,导航会显示一条直线。一位骑手曾愤怒地对孙萍说:它(算法)基于直线距离预测时间长短。但我们送餐不是这样,需要绕路,还要等红绿灯……昨天,我送了一个单子,系统显示五公里,结果,我开了七公里。系统当我们是直升机,但我们不是。

有时,导航还会包含逆行的路段。

2019年10月,贵州骑手小刀在知乎发帖称,美团有引导骑手逆行的情况。在同《人物》的交流中,他说,自己刚刚做了半年骑手,已经遇到过好几次指引他逆行的导航。其中一次是送餐去一家医院,正常行驶需要掉头,而美团导航上的路线则是横穿马路后逆行,根据他提供的截图,逆行路线接近2公里。

还有更厉害的,小刀说,有些地方不方便逆行,如果有过街天桥,系统导航会让你从天桥过去,包括那种不允许电动车上去的天桥。还有围墙,它会让你直接穿墙过去。

在北京,短视频博主曹导也遇到了同样的状况。为了职业体验,她做了不到一周的美团骑手,令她惊诧的是,当她接单后,系统导航出现的居然是步行模式——步行没有正行逆行之分,而系统给出的配送时间,则根据最短的路线计算,其中包含大量的逆行路段。

在小刀看来,无论是直线还是逆行,系统的目的都达到了——系统会依据导航计算出的送餐距离和时间支付配送费,路程短了,时间少了,既为外卖平台黏住了更多的用户,还压缩了配送成本。

2017年年底,美团技术团队在一篇介绍智能配送系统优化升级的文章中,也提到了成本。该篇文章指出,优化算法让平台降低了19%的运力损耗,过去5个骑手能送的餐,现在4个骑手就能送了。最后,成本作为文章的结语出现,效率、体验和成本,将成为平台追求的核心指标。

事实上,美团也因此获得了极大的收益。

根据美团公布的数据显示,2019年第三季度,美团外卖的订单量达到25亿,每单收入比2018年同时期增加了0.04元,而与此同时,每单成本则同比节省了0.12元——这也帮助美团在2019年Q3,多赚了整整4亿元。

只是,在平台巨额盈利的背后,是骑手个人收入的减少。小刀说,每当系统导航出现逆行路段时,他都会面临一种无从选择的困境,要么放弃逆行、跑更远的路面临超时的风险,要么跟着导航承担安全风险,只是,无论哪种选择,钱都实实在在地少了。

每一个骑手要自己在安全和收入之间衡量。作为一个临时参与的局外人,曹导点出了骑手们的困境,所有外送平台都在追逐利益最大化,最后,它们都把风险转嫁到了最没有议价能力的骑手身上。

5.jpeg

小刀手机里的导航路线图,送餐路线斜着穿过了马路

在同《人物》的交流中,数位骑手都表达过同一句话,他们不担心没人来跑,你不干,有的是人来干。

在成为美团骑手之前,阿飞是肯德基的外送员,一人一个月最多也就送六、七百单,因为店里有限制,品牌能够给配送公司12、13块的高单价,因此,外送员得到的配送费也一直维持在9块钱没有变过。他用最规范的来形容那份工作,只是,收入不高,每个月最多能赚5000多。最终,在外卖员收入过万的感召下,他决定离开肯德基,去送外卖。

在美团和饿了么,骑手分为两类——专送与众包。

专送是隶属于配送站的全职骑手,有底薪,有规定的上下班时间,接受系统的派单,以好评率和准时率作为考核标准。众包则是兼职骑手,准入门槛极低,一人、一车、一个app,注册通过后可以立刻上岗,他们没有底薪,可以自由抢单,可以拒绝系统派单,但多次拒绝会被限制抢单。众包骑手不受差评和投诉影响,但超时会面临更重的惩罚,超时一秒钟,配送费直接扣一半——无论专送还是众包,没有任何一位骑手与外送平台存在劳动雇佣关系。

阿飞最终选择加入美团,成为一名众包骑手。那是2017年前后,他每天工作9小时左右,专跑远距离配送,每个月都能赚一万左右,最多时一个月赚过一万五——低门槛,高收入,这被认为是外卖平台不怕没人来的重要原因。

而在社会学学者看来,外卖员收入过万只不过是平台初创阶段的特殊存在——在对武汉地区的快递员与外卖员劳动过程进行了长期调研后,华中师范大学社会学院郑广怀团队发现,随着平台补贴的结束、越来越多骑手的加入,收入过万正在变成一个虚幻的梦想。

该团队发布的研究报告显示:月收入在一万元以上的外卖骑手仅占比2.15%,而有53.18%的受访者反映,目前的收入并不能满足家庭开支。

阿飞告诉《人物》,在北京送了一段时间外卖后,因为个人原因,他去了重庆,收入有所降低,特别是疫情之后,越来越多的人加入,他甚至一度很难抢到订单,有时月收入不足7000元。

据美团研究院发布的《2019年及2020年疫情期美团骑手就业报告》显示,疫情期间,美团平台新注册的有单骑手数达到 33.6万人。新增骑手来源中,排名第一的为工厂工人,其次为销售人员。

至于现在什么时候赚得最多,阿飞给出的答案是,只有特别冷和特别热的时候。因为,这种时候,一般人都不愿意出门。

6.jpeg

电梯

根据外卖平台对外的公开说法,系统在预估送餐时间时,等电梯会被当做重点因素纳入考量范畴。

在接受36氪采访时,美团配送算法团队负责人何仁清也着重提到了电梯:美团的送餐系统会特别关注骑手的上下楼时间,甚至专门研究骑手去低楼层和高楼层时的时间速度。

只是,现实的复杂远远超过AI的预估能力。等电梯真的是我们的一个痛点,超级痛。已经无法月入过万的阿飞说。

在很多骑手的印象中,医院的电梯最难等。

当骑手四年,阿飞遇过最可怕的,是北京大学第三医院的电梯。当时是中午用餐高峰,他拿着七八个订单,去北医三院外科楼,超级恐怖,他说,我记得清清楚楚,电梯口,外卖,病人,医生,家属全挤在一起,场面不要太壮观了。等了好几趟,终于挤上去了,所有人都贴在一起,根本喘息不开。那天,送完这一单,阿飞后面的6个订单全超时了。

后来,他去了重庆,电梯依然是痛中之痛。

网红楼红鼎国际,特别魔幻,一共48层,里面全都是那种小工作室,密密麻麻的,一层能有三四十个工作室,你想多可怕。尽管楼内有七八部电梯,但到了用餐高峰,排队等电梯的人和排队进景区没什么区别,而且一等就是半个小时左右。

还有重庆环球金融中心。这栋建筑总高74层,全楼只有唯一的一部货梯对外卖员开放,一来,用餐高峰期,电梯资源本身就紧张,二来,也可能是写字楼的形象问题。阿飞分析道,我们只能在电梯外等着,里面的人轰隆隆地下来,外面的人轰隆隆地进去。等上去的电梯需要十几分钟,送完餐下来又是十几分钟。一单才多久时间啊,这不超时怎么可能?

写字楼不允许骑手上客梯——北京、上海、深圳、重庆、湖南等地的多位骑手都告诉《人物》,这种状况,极为常见。

2020年7月11日,曹导发布了自己做外卖骑手的职业体验视频,其中,北京SKP商场拒绝外卖员进入的话题上了热搜,引发了全网关于职业歧视的讨论。在曹导看来,在系统性地对外卖服务行业的歧视中,SKP只是冰山一角,在那段长度不到10分钟的视频中,还有一部没有被注意到的电梯。

我印象特别深,曹导说,我去取餐,那个楼里有非常多商铺,而且都是主要靠外卖的那种,楼里有别的电梯,但保安就是不让上,它只开放一部电梯给外卖员使用。她是新手,仅仅是找到这部电梯,就花费了不少时间,然后就是和几十位骑手一起,排队等电梯,所有的外卖员都自动排成两排,把中间空出来给从电梯里出来的外卖员。那天,仅仅是等电梯,就花了她十几分钟的时间。

7.jpeg

微博博主@曹导体验外卖骑手工作,送餐时被拒绝进入商城

除了写字楼,一些高级住宅区也是骑手心中的电梯雷区。在这里,上电梯需要刷卡,而客户又大多不愿意下楼,他会让我们站在电梯里,他在上面摁,但不是都能上得去。阿飞说,遇到这样的客户,很多专送骑手会为了不被差评直接爬20多层,而阿飞跑众包,不怕差评,他的解决方案是,那个人住在14层,让我爬楼,我合计不行,最后商量的是我爬7层,他下来7层,这样比较合理。

在电梯口,阿飞看过无数骑手情绪崩溃,急哭的、吵架的,太多了,因为毕竟就差最后一步了,挤上去了,你就送到了,只是现实中,骑手们只能站在电梯口等着,你啥都干不了,就是干等着。

为了不超时,有的骑手会在等电梯时提前点击送到,但这是系统不允许的,如果被顾客投诉提前点送达,一扣就是500元。一位甘肃的美团骑手告诉《人物》。

在这一点上,饿了么要稍微人性化一点。一位贵州的骑手说。据他介绍,在饿了么的系统中,有一个报备功能,骑手到了楼下,要等电梯,就差一两分钟了,你可以点一下报备,记录你到这个楼下的时间,然后送完下楼了再点送达。

郑州骑手张虎跑过饿了么专送,也跑过美团众包,对比在两个平台的工作经历,他觉得,美团的确更有狼性,美团骑手就是一群跑单机器。饿了么在当地市场份额没那么大,单量没那么多,所以会显得相对温柔客气一些。

现实数据也可以佐证他的判断。

根据移动互联网数据监测平台Trustdata的调查显示,2019年上半年,在全国外卖市场份额中,美团占比达到64.6%,具体到单量,美团骑手平均每天会比饿了么骑手多跑20单左右。

无论骑手多拼尽全力拉满速度,平台还是觉得不够快。张虎忍不住抱怨美团,但他最终还是选择离开饿了么,加入美团,因为在郑州,美团能给他难以想象的单量。

这也是阿飞最终选择美团的原因。尽管疫情期间收入有所下降,但他的心情还算不错——那段时间,很多小区不让进,写字楼不让上,他也不用再跟电梯较劲,但随着疫情的缓解,越来越多的小区和写字楼解禁,电梯的痛点,又开始了新的疼痛。

新一轮的电梯大战再次上演时,曹导也完成了外卖骑手职业体验视频的最终剪辑,她把那个等电梯的画面剪进了正片,7月中旬,再次向《人物》回忆起那一幕时,她说,当时等在电梯口的自己,像工蚁一样。

守门

2019年,家在郑州的李雷从饿了么跳槽到美团,从站长变成一名商务拓展,主要职责是为配送站开拓更多的合作商家。为了让更多热门商家与自己管辖的配送站合作,他经常去扫街,一家一家地维护关系。到了周末用餐高峰,他还会搬把椅子守在商家的门口——这并不是为了拓展合作,而是为了催促商家出餐。

比起等电梯,商家出餐慢是外卖骑手更痛的痛点。

系统以智能之名不断优化升级,一次次缩短送餐时间,但商家出餐慢的问题依旧是老大难——美团资深算法专家王圣尧曾在公开文章中表示,即便分析历史已完成订单,也很难获得商家出餐时间的真值。只要商家出餐时间不确定,这个随机变量就永远存在。

但在送餐时间这个定量面前,去承担和消化这个变量的,只有骑手。

根据骑手们的讲述,商家出餐慢的原因有很多。有些门店名气大、生意火爆,用餐高峰时,堂食出餐已经自顾不暇,但仍不愿意暂停外卖订单。有些小地方的小店,店主比较随性,没什么时间观念,有时骑手已经赶到店里取餐,老板才拎着刚买的菜从外面回来。还有一部分店家,为了保障食物口感,会特意等骑手到店后才开始制作,尤其是面馆。

尤其遇上三大难,烤鱼,炖汤和烧烤。一位骑手告诉《人物》,上次我接到炖汤,我都到店里了,他们还没开始炖呢,我就守着那里看他们炖了40分钟。另一位骑手则直接喊起了爷爷,都急疯了,心里想的都是,爷爷们,赶紧炒吧!但商家依旧不慌不忙,他们真的一点都不担心,反正钱到了,就算因为超时扣钱也不会扣他们钱。

商家出餐慢的问题,是无解的。前美团配送站站长金壮壮说。在系统设置的评价体系中,商家可以对骑手进行差评和投诉,但骑手无权评价商家。有时,骑手还要为商家背锅,太辣了、盐放少了、忘记放醋了……这些对于商家的吐槽经常会出现在骑手差评区里。为此,很多骑手都向系统申诉过,但无一申诉成功。

为了解决这个难题,骑手们只有自己想办法,金壮壮的经验是:出餐慢单多的小饭馆,骑手要常去拉关系,递根烟唠唠嗑,跟老板开开玩笑,最后他们都能给我插队做。大商家,得跟前台小妹或者打包人搞好关系,聊多了,他们会用对讲机帮你催一催,总是有用的。

但这并不能解决根本问题,骑手和店员的矛盾仍频频发生。因为出餐问题,一位济南的外卖骑手曾与喜茶店店员大打出手,而在武汉,一位骑手则在争执中将店员刺伤,后者因抢救无效身亡。

8.jpeg

武汉被外卖骑手刺伤的店员 图源网络

因为等餐和商家发生冲突,甚至喊来警察的状况,骑手们见得太多了,至于如何解决这个问题,一位骑手表示,延长一些送餐时间,时间充裕了,大家也就不会这么急了。

但现实中,送餐时间越来越短,而在骑手们面临的各种催促声中,消耗骑手时间的主角之一——商家,也是重要的发声者。

在与商家谈合作的过程中,李雷发现,商家说得最多的,就是骑手的速度。只要骑手速度没有达到商家心中预期,商家就会跟李雷提出,换掉配送站骑手,或者解除合作关系——通常,热门大商圈附近会有两家同平台的配送站,商户可以自由选择同哪一个站点合作,至于合作的条件,李雷说,很简单,一是配送站的配送能力,二是骑手到店速度。

为了拿下单量大的商家,李雷会去配送站督促骑手,快一点,再快一点,但如果因为商家出餐慢导致骑手超时,影响了站点数据,他能做的也只是去商量,或者自己直接去蹲点,但这不是谁都能去的,能在门店催单,也得看私下的关系铁不铁。

坐在店门口的李雷,会死死地盯着商家外卖订单接收机器的屏幕,一刻都不敢走神。叮,一个订单进来了,他的声音会和订单同时到达,美团来了。我们美团的单子来了。他说,要从第一秒就战胜对手。

9.jpeg

正在取餐的外卖骑手


文|赖祐萱,原文转自:https://baijiahao.baidu.com/s?id=1677231323622016633

手把手教学实现消息通信

技术交流王叫兽 发表了文章 • 2 个评论 • 63 次浏览 • 2020-09-09 10:09 • 来自相关话题

一、背景作为一名 Web 开发者,在日常工作中,经常都会遇到消息通信的场景。比如实现组件间通信、实现插件间通信、实现不同的系统间通信。那么针对这些场景,我们应该怎么实现消息通信呢?本文阿宝哥将带大家一起来学习如何优雅的实现消息通信。好的,接下来我们马上步入正题... ...查看全部

一、背景

作为一名 Web 开发者,在日常工作中,经常都会遇到消息通信的场景。比如实现组件间通信、实现插件间通信、实现不同的系统间通信。那么针对这些场景,我们应该怎么实现消息通信呢?本文阿宝哥将带大家一起来学习如何优雅的实现消息通信。

好的,接下来我们马上步入正题,这里阿宝哥以一个文章订阅的例子来拉开本文的序幕。小秦与小王是阿宝哥的两个好朋友,他们在阿宝哥的 “全栈修仙之路” 博客中发现了 TS 专题文章,刚好他们近期也打算系统地学习 TS,所以他们就开启了 TS 的学习之旅。

时间就这样过了半个月,小秦和小王都陆续找到了阿宝哥,说 “全栈修仙之路” 博客上的 TS 文章都差不多学完了,他们有空的时候都会到 “全栈修仙之路” 博客上查看是否有新发的 TS 文章。他们觉得这样挺麻烦的,看能不能在阿宝哥发完新的 TS 文章之后,主动通知他们。


好友提的建议,阿宝哥怎能拒绝呢?所以阿宝哥分别跟他们说:“我会给博客加个订阅的功能,功能发布后,你填写一下邮箱地址。以后发布新的 TS 文章,系统会及时给你发邮件”。此时新的流程如下图所示:

在阿宝哥的一顿 “操作” 之后,博客的订阅功能上线了,阿宝哥第一时间通知了小秦与小王,让他们填写各自的邮箱。之后,每当阿宝哥发布新的 TS 文章,他们就会收到新的邮件通知了。

阿宝哥是个技术宅,对新的技术也很感兴趣。在遇到 Deno 之后,阿宝哥燃起了学习 Deno 的热情,同时也开启了新的 Deno 专题。在写了几篇 Deno 专题文章之后,两个读者小池和小郭分别联系到我,说他们看到了阿宝哥的 Deno 文章,想跟阿宝哥一起学习 Deno。

在了解他们的情况之后,阿宝哥突然想到了之前小秦与小王提的建议。因此,又是一顿 “操作” 之后,阿宝哥为了博客增加了专题订阅功能。该功能上线之后,阿宝哥及时联系了小池和小郭,邀请他们订阅 Deno 专题。之后小池和小郭也成为了阿宝哥博客的订阅者。现在的流程变成这样:

这个例子看起来很简单,但它背后却与一些设计思想和设计模式相关联。因此,接下来阿宝哥将分析以上三个场景与软件开发中一些设计思想和设计模式的关联性。

二、场景与模式

2.1 消息轮询模式

在第一个场景中,小秦和小王为了能查看阿宝哥新发的 TS 文章,他们需要不断地访问 “全栈修仙之路” 博客:

这个场景跟软件开发过程中的轮询模式类似。早期,很多网站为了实现推送技术,所用的技术都是轮询。轮询是指由浏览器每隔一段时间向服务器发出 HTTP 请求,然后服务器返回最新的数据给客户端。常见的轮询方式分为轮询与长轮询,它们的区别如下图所示:

这种传统的模式带来很明显的缺点,即浏览器需要不断的向服务器发出请求,然而 HTTP 请求与响应可能会包含较长的头部,其中真正有效的数据可能只是很小的一部分,所以这样会消耗很多带宽资源。为了解决上述问题 HTML5 定义了 WebSocket 协议,能更好的节省服务器资源和带宽,并且能够更实时地进行通讯。

WebSocket 是一种网络传输协议,可在单个 TCP 连接上进行全双工通信,位于 OSI 模型的应用层。WebSocket 协议在 2011 年由 IETF 标准化为 RFC 6455,后由 RFC 7936 补充规范。

既然已经提到了 OSI(Open System Interconnection Model)模型,这里阿宝哥来分享一张很生动、很形象描述 OSI 模型的示意图:

(图片来源:https://www.networkingsphere.com/2019/07/what-is-osi-model.html)

WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就可以创建持久性的连接,并进行双向数据传输。

介绍完轮询和 WebSocket 的相关内容之后,接下来我们来看一下 XHR Polling 与 WebSocket 之间的区别:

对于 XHR Polling 与 WebSocket 来说,它们分别对应了消息通信的两种模式,即 Pull(拉)模式与 Push(推)模式:

场景一我们就介绍到这里,对轮询和 WebSocket 感兴趣的小伙伴可以阅读阿宝哥写的 “你不知道的 WebSocket” 这一篇文章。下面我们来继续分析第二个场景。

2.2 观察者模式

在第二个场景中,为了让小秦和小王能及时收到阿宝哥新发布的 TS 文章,阿宝哥给博客增加了订阅功能。这里假设阿宝哥博客一开始只发布 TS 专题的文章。

针对这个场景,我们可以考虑使用设计模式中观察者模式来实现上述功能。观察者模式,它定义了一种一对多的关系,让多个观察者对象同时监听某一个主题对象,这个主题对象的状态发生变化时就会通知所有的观察者对象,使得它们能够自动更新自己。

在观察者模式中有两个主要角色:Subject(主题)和 Observer(观察者)。

在第二个场景中,Subject(主题)就是阿宝哥的 TS 专题文章,而观察者就是小秦和小王。由于观察者模式支持简单的广播通信,当消息更新时,会自动通知所有的观察者。因此对于第二个场景,我们可以考虑使用观察者设计模式来实现上述的功能。接下来,我们来继续分析第三个场景。

2.3 发布订阅模式

在第三个场景中,为了让小池和小郭能及时收到阿宝哥新发布的 Deno 文章,阿宝哥给博客增加了专题订阅功能。即支持为阿宝哥博客的订阅者分别推送新发布的 TS 或 Deno 文章。

针对这个场景,我们可以考虑使用发布订阅模式来实现上述功能。在软件架构中,发布 — 订阅是一种消息范式,消息的发送者(称为发布者)不会将消息直接发送给特定的接收者(称为订阅者)。而是将发布的消息分为不同的类别,然后分别发送给不同的订阅者。同样的,订阅者可以表达对一个或多个类别的兴趣,只接收感兴趣的消息,无需了解哪些发布者存在。

在发布订阅模式中有三个主要角色:Publisher(发布者)、 Channels(通道)和 Subscriber(订阅者)。

在第三个场景中,Publisher(发布者)是阿宝哥,Channels(通道)中 Topic A 和 Topic B 分别对应于 TS 专题和 Deno 专题,而 Subscriber(订阅者)就是小秦、小王、小池和小郭。好的,了解完发布订阅模式,下面我们来介绍一下它的一些应用场景。

三、发布订阅模式的应用

3.1 前端框架中模块/页面间消息通信

在一些主流的前端框架中,内部也会提供用于模块间或页面间通信的组件。比如在 Vue 框架中,我们可以通过 new Vue() 来创建 EventBus 组件。而在 Ionic 3 中我们可以使用 ionic-angular 模块中的 Events 组件来实现模块间或页面间的消息通信。下面我们来分别介绍在 Vue 和 Ionic 中如何实现模块/页面间的消息通信。

3.1.1 Vue 使用 EventBus 进行消息通信

在 Vue 中我们可以通过创建 EventBus 来实现组件间或模块间的消息通信,使用方式很简单。在下图中包含两个 Vue 组件:Greet 和 Alert 组件。Alert 组件用于显示消息,而 Greet 组件中包含一个按钮,即下图中 ”显示问候消息“ 的按钮。当用户点击按钮时,Greet 组件会通过 EventBus 把消息传递给 Alert 组件,该组件接收到消息后,会调用 alert 方法把收到的消息显示出来。

以上示例对应的代码如下:

main.js

Vue.prototype.$bus = new Vue();

Alert.vue


<script>
export default {
  name: "alert",
  created() {
    // 监听alert:message事件
    this.$bus.$on("alert:message", msg => {
      this.showMessage(msg);
    });
  },
  methods: {
    showMessage(msg) {
      alert(msg);
    },
  },
  beforeDestroy: function() {
    // 组件销毁时,移除alert:message事件监听
    this.$bus.$off("alert:message");
  }
}
</script>

Greet.vue


<template>
  <div>
    <button @click="greet(message)">显示问候信息</button>
  </div>
</template>
 
<script>
export default {
  name: "Greet",
  data() {
    return {
      message: "大家好,我是阿宝哥",
    };
  },
  methods: {
    greet(msg) {
      this.$bus.$emit("alert:message", msg);
    }
  }
};
</script>

3.1.2 Ionic 使用 Events 组件进行消息通信

在 Ionic 3 项目中,要实现页面间消息通信很简单。我们只要通过构造注入的方式注入 ionic-angular 模块中提供的 Events 组件即可。具体的使用示例如下所示:

import { Events } from 'ionic-angular';
 
// first page (publish an event when a user is created)
constructor(public events: Events) {}
createUser(user) {
  console.log('User created!')
  this.events.publish('user:created', user, Date.now());
}
 
 
// second page (listen for the user created event after function is called)
constructor(public events: Events) {
  events.subscribe('user:created', (user, time) => {
    // user and time are the same arguments passed in `events.publish(user, time)`
    console.log('Welcome', user, 'at', time);
  });
}

介绍完发布订阅模式在 Vue 和 Ionic 框架中的应用之后,接下来阿宝哥将介绍该模式在微内核架构中是如何实现插件通信的。

3.2 微内核架构中插件通信

微内核架构(Microkernel Architecture),有时也被称为插件化架构(Plug-in Architecture),是一种面向功能进行拆分的可扩展性架构,通常用于实现基于产品的应用。微内核架构模式允许你将其他应用程序功能作为插件添加到核心应用程序,从而提供可扩展性以及功能分离和隔离。

微内核架构模式包括两种类型的架构组件:核心系统(Core System)和插件模块(Plug-in modules)。应用逻辑被分割为独立的插件模块和核心系统,提供了可扩展性、灵活性、功能隔离和自定义处理逻辑的特性。


对于微内核的核心系统设计来说,它涉及三个关键技术:插件管理、插件连接和插件通信,这里我们重点来分析一下插件通信。

插件通信是指插件间的通信。虽然设计的时候插件间是完全解耦的,但实际业务运行过程中,必然会出现某个业务流程需要多个插件协作,这就要求两个插件间进行通信;由于插件之间没有直接联系,通信必须通过核心系统,因此核心系统需要提供插件通信机制。

这种情况和计算机类似,计算机的 CPU、硬盘、内存、网卡是独立设计的配置,但计算机运行过程中,CPU 和内存、内存和硬盘肯定是有通信的,计算机通过主板上的总线提供了这些组件之间的通信功能。

下面阿宝哥将以基于微内核架构设计的西瓜播放器为例,介绍它的内部是如何提供插件通信机制。在西瓜播放器内部,定义了一个 Player 类来创建播放器实例:


let player = new Player({
  id: 'mse',
  url: '//abc.com/**/*.mp4'
});

Player 类继承于 Proxy 类,而在 Proxy 类内部会通过构造继承的方式继承 EventEmitter 事件派发器:


import EventEmitter from 'event-emitter'
 
class Proxy {
  constructor (options) {
    this._hasStart = false;
    // 省略大部分代码
    EventEmitter(this);
  }
}

所以我们创建的西瓜播放器也是一个事件派发器,利用它就可以实现插件的通信。为了让大家能够更好地理解具体的通信流程,我们以内置的 poster 插件为例,来看一下它内部如何使用事件派发器。

poster 插件用于在播放器播放音视频前显示海报图,该插件的使用方式如下:


new Player({
  el:document.querySelector('#mse'),
  url: 'video_url',
  poster: '//abc.com/**/*.png' // 默认值""
});

poster 插件的对应源码如下:


import Player from '../player'
 
let poster = function () {
  let player = this; 
  let util = Player.util
  let poster = util.createDom('xg-poster', '', {}, 'xgplayer-poster');
  let root = player.root
  if (player.config.poster) {
    poster.style.backgroundImage = `url(${player.config.poster})`
    root.appendChild(poster)
  }
 
  // 监听播放事件,播放时隐藏封面图
  function playFunc () {
    poster.style.display = 'none'
  }
  player.on('play', playFunc)
 
  // 监听销毁事件,执行清理操作
  function destroyFunc () {
    player.off('play', playFunc)
    player.off('destroy', destroyFunc)
  }
  player.once('destroy', destroyFunc)
}
 
Player.install('poster', poster)

(https://github.com/bytedance/xgplayer/blob/master/packages/xgplayer/src/control/poster.js)

通过观察源码可知,在注册 poster 插件时,会把播放器实例注入到插件中。之后,在插件内部会使用 player 这个事件派发器来监听播放器的 play 和 destroy 事件。当 poster 插件监听到播放器的 play 事件之后,就会隐藏海报图。而当 poster 插件监听到播放器的 destroy 事件时,就会执行清理操作,比如移除已绑定的事件。

看到这里我们就已经很清楚了,西瓜播放器内部使用 EventEmitter 来提供插件通信机制,每个插件都会注入 player 这个全局的事件派发器,通过它就可以轻松地实现插件间通信了。

提到 EventEmitter,相信很多小伙伴对它并不会陌生。在 Node.js 中有一个名为 events 的内置模块,通过它我们可以方便地实现一个自定义的事件派发器,比如:


const EventEmitter = require('events');
 
class MyEmitter extends EventEmitter {}
 
const myEmitter = new MyEmitter();
 
myEmitter.on('event', () => {
  console.log('大家好,我是阿宝哥!');
});
 
myEmitter.emit('event');

3.3 基于 Redis 实现不同系统间通信

在前面我们介绍了发布订阅模式在单个系统中的应用。其实,在日常开发过程中,我们也会遇到不同系统间通信的问题。接下来阿宝哥将介绍如何利用 Redis 提供的发布与订阅功能实现系统间的通信,不过在介绍具体应用前,我们得先熟悉一下 Redis 提供的发布与订阅功能。

3.3.1 Redis 发布与订阅功能

Redis 订阅功能

通过 Redis 的 subscribe 命令,我们可以订阅感兴趣的通道,其语法为:SUBSCRIBE channel [channel …]。


➜  ~ redis-cli
127.0.0.1:6379> subscribe deno ts
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "deno"
3) (integer) 1
1) "subscribe"
2) "ts"
3) (integer) 2

在上述命令中,我们通过 subscribe 命令订阅了 deno 和 ts 两个通道。接下来我们新开一个命令行窗口,来测试 Redis 的发布功能。

Redis 发布功能

通过 Redis 的 publish 命令,我们可以为指定的通道发布消息,其语法为:PUBLISH

channel message。
➜  ~ redis-cli
127.0.0.1:6379> publish ts "
pub/sub design mode"

当成功发布消息之后,订阅该通道的客户端就会收到消息,对应的控制台就会输出如下信息:


1) "message"
2) "ts"
3) "pub/sub design mode"

了解完 Redis 的发布与订阅功能,接下来阿宝哥将介绍如何利用 Redis 提供的发布与订阅功能实现不同系统间的通信。

3.3.2 实现不同系统间的通信

这里我们使用 Node.js 的 Express 框架和 redis 模块来快速搭建不同的 Web 应用,首先创建一个新的 Web 项目并安装一下相关的依赖:


$ npm init --yes
$ npm install express redis

接着创建一个发布者应用:

publisher.js


const redis = require("redis");
const express = require("express");
 
const publisher = redis.createClient();
 
const app = express();
 
app.get("/", (req, res) => {
  const article = {
    id: "666",
    name: "TypeScript实战之发布订阅模式",
  };
 
  publisher.publish("ts", JSON.stringify(article));
  res.send("阿宝哥写了一篇TS文章");
});
 
app.listen(3005, () => {
  console.log(`server is listening on PORT 3005`);
});

然后分别创建两个订阅者应用:

subscriber-1.js


const redis = require("redis");
const express = require("express");
 
const subscriber = redis.createClient();
 
const app = express();
 
subscriber.on("message", (channel, message) => {
  console.log("小王收到了阿宝哥的TS文章: " + message);
});
 
subscriber.subscribe("ts");
 
app.get("/", (req, res) => {
  res.send("我是阿宝哥的粉丝,小王");
});
 
app.listen(3006, () => {
  console.log("server is listening to port 3006");
});

subscriber-2.js


const redis = require("redis");
const express = require("express");
 
const subscriber = redis.createClient();
 
// https://dev.to/ganeshmani/implementing-redis-pub-sub-in-node-js-application-12he
const app = express();
 
subscriber.on("message", (channel, message) => {
  console.log("小秦收到了阿宝哥的TS文章: " + message);
});
 
subscriber.subscribe("ts");
 
app.get("/", (req, res) => {
  res.send("我是阿宝哥的粉丝,小秦");
});
 
app.listen(3007, () => {
  console.log("server is listening to port 3007");
});

接着分别启动上面的三个应用,当所有应用都成功启动之后,在浏览器中访问 http://localhost:3005/ 地址,此时上面的两个订阅者应用对应的终端会分别输出以下信息:

subscriber-1.js


server is listening to port 3006
小王收到了阿宝哥的TS文章: {"id":"666","name":"TypeScript实战之发布订阅模式"}

subscriber-2.js


server is listening to port 3007
小秦收到了阿宝哥的TS文章: {"id":"666","name":"TypeScript实战之发布订阅模式"}

以上示例对应的通信流程如下图所示:

到这里发布订阅模式的应用场景,已经介绍完了。最后,阿宝哥来介绍一下如何使用 TS 实现一个支持发布与订阅功能的 EventEmitter 组件。

四、发布订阅模式实战

4.1 定义 EventEmitter 类


type EventHandler = (...args: any[]) => any;
 
class EventEmitter {
  private c = new Map<string, EventHandler[]>();
 
  // 订阅指定的主题
  subscribe(topic: string, ...handlers: EventHandler[]) {
    let topics = this.c.get(topic);
    if (!topics) {
      this.c.set(topic, topics = []);
    }
    topics.push(...handlers);
  }
 
  // 取消订阅指定的主题
  unsubscribe(topic: string, handler?: EventHandler): boolean {
    if (!handler) {
      return this.c.delete(topic);
    }
 
    const topics = this.c.get(topic);
    if (!topics) {
      return false;
    }
    
    const index = topics.indexOf(handler);
 
    if (index < 0) {
      return false;
    }
    topics.splice(index, 1);
    if (topics.length === 0) {
      this.c.delete(topic);
    }
    return true;
  }
 
  // 为指定的主题发布消息
  publish(topic: string, ...args: any[]): any[] | null {
    const topics = this.c.get(topic);
    if (!topics) {
      return null;
    }
    return topics.map(handler => {
      try {
        return handler(...args);
      } catch (e) {
        console.error(e);
        return null;
      }
    });
  }
}

4.2 使用示例


const eventEmitter = new EventEmitter();
eventEmitter.subscribe("ts", (msg) => console.log(`收到订阅的消息:${msg}`) );
 
eventEmitter.publish("ts", "TypeScript发布订阅模式");
eventEmitter.unsubscribe("ts");
eventEmitter.publish("ts", "TypeScript发布订阅模式");

以上代码成功运行之后,控制台会输出以下信息:

收到订阅的消息:TypeScript发布订阅模式

五、参考资源

维基百科 - 发布/订阅

Ionic 3 - Events

implementing-redis-pub-sub-in-node-js-application

原文地址https://blog.csdn.net/qiwoo_weekly/article/details/108250534


你收到GeekOnline加油包了吗

活动江南孤鹜 回复了问题 • 7 人关注 • 7 个回复 • 167 次浏览 • 2020-09-08 17:35 • 来自相关话题

【领取见面礼】限量 100份 GeekOnline加油包!等你来拿

活动雨山 回复了问题 • 61 人关注 • 62 个回复 • 1775 次浏览 • 2020-09-08 17:35 • 来自相关话题

活动赠票 | 我们诚邀20位开发者线下探讨攻克DevOps的落地实践大法

活动梅川酷子 发表了文章 • 0 个评论 • 49 次浏览 • 2020-09-08 14:04 • 来自相关话题

号外号外!中国 DevOps 社区 & CODING 深圳第九届Meetup 来啦!本次以「DevOps 转型与实践」为主题的技术沙龙活动,由腾讯云旗下一站式 DevOps 开发平台 CODI... ...查看全部

号外号外!中国 DevOps 社区 & CODING 深圳第九届Meetup 来啦!

本次以「DevOps 转型与实践」为主题的技术沙龙活动,由腾讯云旗下一站式 DevOps 开发平台 CODING 和中国 DevOps 社区主办,邀请了四位来自世界 500 强或国内外知名企业的技术大咖,共同探讨在 DevOps 的大潮流中,各公司如何攻克常见的企业痼疾根源,实现转型与落地实践 DevOps,提高研发效能。

海报详情及报名方式如下图:

图片1.png

Attention

融云作为本次活动的深度合作伙伴,为大家争取了20张免费票,扫描以下二维码获得赠票。

 图11.png 

扫描二维码即可领取

奖品

除了大咖演讲分享,活动现场还有惊喜抽奖环节~幸运观众可以获得的奖品包括:

DevOps 阅读系列包括:

1)《DevOps实践指南》x 5本

2)《敏捷无·敌之DevOps时代》x 2本

3)《京东敏捷实践指南》x 5本

4)《敏捷转型》x 3本

5)《绩效跃升地图》x 3本

6)《DevOps成长地图》x 3份

图片3.png

CODING 及合作伙伴纪念品包括:

7)CODING 猴子抱枕纪念品及活动贴纸

8)猫爪杯,挂脖风扇

图片4.png

还在等什么,赶快扫描海报里的二维码报名吧!

主办方

图片5.png

中国 DevOps 社区在全国的 17 个城市定期举办 Meetup 活动,每年会选定一个社区年会举办城市,每个月举办两次线上分享技术交流活动。社区正在逐渐发展更多的 Meetup 举办城市,致力于通过打造最优的线下交流社区,推动 DevOps 运动在国内的发展。

图片6.png

腾讯云旗下一站式 DevOps 开发平台 CODING.net,成立于 2014 年,致力于 DevOps 工具链产品的标准化。CODING 长期关注开发者社区建设,主办全国 20 余场专题技术活动。

友情链接