提交 a9a8f0c4 编写于 作者: S star

Kafka

上级 484471c6
......@@ -4,6 +4,7 @@ title: "Definition of End to End User Scenarios"
date: 2015-03-31
author: "Hux"
header-img: "img/post-bg-e2e-ux.jpg"
header-bg-css: "linear-gradient(to right, #24b94a, #38ef7d);"
lang: en
tags:
- UX/UI
......
---
layout: post
title: "如何客观地评价「小程序」的体验?"
subtitle: "Wechat Mini-Program vs. the Web, a UX comparison"
author: "Hux"
header-img: ""
header-bg-css: "linear-gradient(to right, #24b94a, #38ef7d);"
tags:
- Web
- Wechat
- UX/UI
---
> 本文首发于我的知乎专栏 [The Little Programmer](https://zhuanlan.zhihu.com/p/24782839),转载请保留链接 ;)
2017 年 1 月 9 号凌晨,看完《星战》回家,发现朋友圈都炸了……原来是「小程序」如约公测(以下简称小程序)。果然贵圈人都睡得晚啊,一个个大半夜了精神得不行。
截图推荐什么的已经漫天都是了,而且连 「推荐小程序的小程序」都已经出现了,我们就直入正题吧,今天笔者不跟你们聊情怀,就聊体验:
### **小程序的体验比 Web 更好吗?**
体验完利益相关微票儿的「电影演出赛事」后,我在朋友圈里怒发了一条「实际体验小程序的感觉就是**完全没有**比普通的 web 体验更好…」,感觉评论里 [@Cheeeee](//www.zhihu.com/people/11b8c6f61424152bd0e6d8a97760df16) 都受惊了 > <。不过在多体验了几个小程序之后,我觉得我应该尝试更客观的回答这个问题。
### 1\. 在「微信」里,小程序的 Engagement 比 Web 更好。
这当然是毋庸置疑的,我的博客在微信里打开至今都是「非微信官方网页,继续访问将转换成手机预览模式」,然后点击「继续访问」就是「params is error」,我 &^\*#.%...
而对于其他在微信中可访问的 web 应用来说,小程序有着自己的搜索入口、抽屉(历史记录),还可以「显示在聊天顶部」,这其实分别对应着 「拉新」、「包活」 与一定的「多任务」支持。尤其是后两者,与 [PWA](https://www.zhihu.com/question/46690207/answer/104851767) 的「添加至主屏」与「出现在 Task Switcher」里异曲同工。
正如 [微信小程序和网页版程序的区别在哪里? - 冯雨的回答 - 知乎](https://www.zhihu.com/question/54148303/answer/138152983) 里所说的,「订阅号、服务号、小程序,就是一个个静态或动态的 Web站点;二维码和消息气泡,一个现实一个虚拟,就是微信提供的超级链接。」
**World Wide Web 在微信里是残废的,取而代之的是 Weixin/Wechat Wide Web。**
值得一提的是,现在微信只会对特定小程序支持模糊搜索,而且据我目测都是诸如京东、滴滴这样的「国家队」。喏,在我地盘这你就得听我的~ ? ?
### 2\. 在「微信」里,小程序的 Capability 比 Web 更好。
当我们在说「小程序的体验是否能比 Web 更接近原生应用」时,我们通常指的就是它的 capability。
先说 UI 性能,截止目前为止,小程序的大部分组件都还是使用 WebView 渲染的,这意味着在大多数组件场景下,小程序的 UI 性能不可能比 Web 更高。但是:
1. **小程序团队非常 tricky 地把力气都用在了刀刃上**:每一个使用原生 UI 渲染、或在自定义 WebView 中优化过的组件都对应着 Mobile Web 中的一个老大难问题。比如在 iOS 上让顶部或底部的 Tab Bar "Fixed",比如视频的自动播放与控制力,比如地图、textarea 等,可以说利用有限的资源显著提高了小程序的可用性。
2. 由于 Web 前端开发者的良莠不齐,小程序通过限定一组 Web 技术的子集,可以很好的约束开发者写出性能与体验不低于基线的代码,这与 Google 的 AMP 异曲同工。(其实这是大家觉得小程序体验比 Web 好的很大一个原因)
3. 由于小程序中的 wxml 与 wxss 都是比较 high-level 的抽象,所以微信团队可以在不影响开发者源代码的情况下,通过升级 Runtime 与组件的实现不断优化小程序的性能,比如完全迁移到类似 React Native 或 Weex 这样的 JS-to-Native 方案。
再说启动性能,这是让大家觉得小程序感知体验比 Web 好的第二个大因素:
1. 由于小程序是打包部署并「安装」的,可以从文件系统中直接启动。以此解决 web 带来的网络延迟与离线时不可访问问题。
最后是 Integration。通过私有的 JS SDK,小程序可以借助微信这座桥梁实现很多以往 Web 并不容易实现的体验。同样,这些改进也非常 tricky,只解决痛点问题:
1. 设备访问能力,文件、系统、网络、GPS、加速计、罗盘……
2. 「第一公民」能力,最明显的莫过于设置导航条和页与页之间的动画。还有 Android 设备上的「添加小程序到桌面」,其实就是个快捷方式。
![](/img/in-post/post-wmu/maoyan.jpg)
(图为猫眼 App 与小程序,因为长得像…感觉不小心给老东家竞争对手打广告了?)
**可惜的是,这些技术里面没有一项是「小程序」首创的,且大都有超过两年的历史:**百度的 Blend UI、阿里的 Hybrid 容器、Google 的 PWA/AMP、Phonegap/Cordova、React Native/Weex……这也是很多技术从业人吐槽小程序在技术上毫无创新的原因。
但平心而论,崇尚「技术服务产品」的腾讯系在产品化上做的真心出色。这也是我为什么在 9 月 21 日知道小程序技术方案时夸赞「兼容并蓄 博采众长 且可持续性发展」的原因,并不是站在技术创新的角度,而是站在微信的角度上,这个决策拿捏在了 sweet point 上。
### 3\. 在「微信」里,小程序不一定比 Web 更好的。
目前我所了解到的(截止 2017 年 1 月 9 日):
1. 小程序对比 Web,只能通过摄像头扫码,不能分享朋友圈,营销难做,这是 Reach。
2. 小程序中没有真正的超链接与 WebView,完全不能外链,这是 Linkability。如果知乎要做小程序,所有答案里的超链接都只能报废。或者只能像轻芒杂志那样,做一层转码,美其名曰阅读模式。
3. 小程序目前的组件虽然 cover 了大部分场景,但是也明显有很多不能 cover 到的 case,这是 Scalability。
这三点都是可以直接影响到目前小程序的产品形态与设计的。当然,对于微信来说,这三点更多的是决策问题。作为 Weixin Wide Web 这个封闭生态的唯一「浏览器」,微信便是生杀大权。手起刀落之间,小程序的缺点随时可以被弥补,而 Web 的优点也随时可以被抹杀。
但是,现实可能并不会这么简单。我们发现,大部分小程序都只提供了其原生应用或 web 应用功能的一个子集。比如文章最早提到的微票儿的「电影演出赛事」小程序,与钱包里的 web 版本相比,UI 体验好了一点,但是功能远没有 web 版本来得丰富,也没有了 web 版本可以分享评论到朋友圈的能力。
![](/img/in-post/post-wmu/wepiao.jpg)
(微票儿小程序与其钱包中的内嵌 web 应用对比,web 版的功能要丰富得多。)
微票儿(娱票儿)作为一家在微信里内嵌 web 服务起家的公司,一是证明了微信流量红利的可怕,二其实也证明了原有 web 的能力。作为「亲腾讯亲微信」的公司之一,其小程序比不上 web 应用可能只是时间关系。但是对于其他公司呢,尤其是未被腾讯「临幸」过的公司?而这其实对应着另一个更难回答的问题:
### **小程序值得接入商花多大的力气?**
笔者自知无法回答这个问题,所以只能抛砖引玉一下:
| N/A | 简单体验(页面) | 中等体验(mini-app) | 核心体验(app) |
| -------- | ----------------- | -------------------- | --------------- |
| 纯微信流 | 公众号 小程序 | 小程序 | 我想要个原生啊 |
| 创业公司 | 公众号 Web 小程序 | Web 小程序 | 拉回原生啊 |
| 中大公司 | 公众号 Web 小程序 | Web 小程序 | 拉回原生啊 |
| 巨头公司 | 公众号 Web | 不跟微信玩 | 不跟微信玩 |
具体到每一个 Web 与小程序 PK 的场景:
* 对于简单体验,小程序的一点点体验提升对比 Web 的跨平台与传播能力没有优势
* 对于中等体验,小程序体验更好,但需要付出额外的人力资源与开发维护成本
* 对于核心体验,大家的目标都是拉回自己的主场
如果说阿里的「让天下没有难做的生意」是把话说开来「双赢」,微信「开放」平台和接入商之间的资源互换关系则更像是「权力的游戏」了:**微信想借接入商来建立自己的垄断帝国,接入商却想玩暗度陈仓。**某种程度上来说,Web 应用是自己的领地,值得在上面建立完整的体验。而小程序,可能会如小程序诞生前的「weixin-specific web」一样,很大程度上沦为拉新立牌坊的工具。
所以我们不妨再加一条:
4\. 对于用户来说,小程序可能并不会「够用」,这是 Feature Set。
### 4\. 不在「微信」里,小程序……
![](/img/in-post/post-wmu/question.jpg)
### 5\. 结论?
回到问题「小程序的体验比 Web 更好吗?」,我觉得各位看官心里应该会有自己的答案。对于不同的公司,不同的业务场景,不同的盈利方式,不同的团队,我相信这个答案都是不一样的。
> But if you trade something off, make sure you get something in return.
> 如果你需要妥协掉一些东西,请务必换回点好处来。
作为一篇「试图做到客观(且非常难)」的文章,如果能对你有帮助,那就算没有白写了。
### 6\. 题外话(这段主观!)
最后说两句题外话吧,上个月给《程序员》杂志交了拖了 N 久的稿,大概在本月底会发吧?
在那篇文章最后我写到,「笔者奢望着本文能对推动 PWA 的国内环境有一定的贡献」。眼见小程序在某种意义上 "polyfill" (大雾)了 PWA,作为一个在技术上略有 [理想主义](https://zhuanlan.zhihu.com/p/22561084) 的程序员,笔者也只能叹一句了:
「这不是我想要的未来。」
会是你们的吗?
\ No newline at end of file
......@@ -1223,7 +1223,7 @@ public class RedisCheck implements ApplicationListener<ApplicationStartedEvent>
#### 10.Redis配置文件
默认安装的 Redis 的配置文件位于 ***/etc/redis.conf***[Example](data/redis.conf)
默认安装的 Redis 的配置文件位于 ***/etc/redis.conf***[Example](../data/redis.conf)
redis.conf 默认单位介绍:单位大小写不敏感。
......@@ -1873,7 +1873,7 @@ Redis 哨兵的作用:
***redis-sentinel.conf*** 配置文件:[Example](data/redis-sentinel.conf)
***redis-sentinel.conf*** 配置文件:[Example](../data/redis-sentinel.conf)
- 网络配置:默认情况下,sentinel 无法通过不同于 localhost 的网络接口进行访问,当 sentinel 与 Redis 集群不在同一台机器上时,sentinel 与 Redis 集群将会出现通信问题,此时需要手动配置一下两个选项之一:
......
......@@ -76,8 +76,8 @@ Kafka 配置文件:配置文件是位于 config 目录下 server.properties
1. 配置 listeners 监听:
~~~properties
listeners=PLAINTEXT://localhost:9092
advertised.listeners=PLAINTEXT://localhost:9092
listeners=PLAINTEXT://192.168.253.136:9092
advertised.listeners=PLAINTEXT://192.168.253.136:9092
~~~
如果这里配置的 localhost 后续命令中则使用 localhost,如果这里配置具体 IP,后面命令则使用具体的 IP 地址。
......@@ -108,7 +108,7 @@ Kafka 基本操作:
>:closed_lock_with_key: Kafka 基本概念:
>
>1. Topic(主题):消息主题,一个消息主题包含多个 Partitions。
>2. Partitions(分区):消息的实际存储单位。
>2. Partitions(分区):消息的实际存储单位,将一个 Topic 的消息按分区进行存储,大大的提高了 Kafka 集群的负载能力
>3. Producer(生产者):消息生产者。
>4. Consumer(消费者):消息消费者。
......@@ -668,6 +668,8 @@ Consumer 端对着三种语义的支持:
> :ear_of_rice: 综上所述:Kafka 默认是保证`至少一次`传递,并允许用户通过禁止生产者重试和处理一批消息前提交它的偏移量来实现`最多一次`传递,而`正好一次`传递需要与目标存储系统合作,但 Kafka 提供了偏移量,实现起来也比较简单。
>
> 附:Producer、Consumer 所有配置项参考[配置项](../data/Kafka配置全解析.pdf)。
......@@ -794,30 +796,183 @@ Kafka 集群特点:
1. Kafka 集群依赖于 Zookeeper 进行协调。
2. Kafka 通过 BrokerId 来区分集群中的各个节点。
Kafka 集群基本概念:
> Kafka 集群基本概念:
>
> 1. Broker(代理):服务器上运行的 Kafka 的实例,在 Kafka 集群中每一个 Broker 对应一个唯一的 ID,即 BrokerId(Interger)。
>
> 2. Leader:负责消息读写的 Partition,所有的读写操作只能发生于 Leader 分区上。
>
> 3. Follower:负责从 Leader 同步消息,Follower 与 Leader 始终保持消息同步。
>
> 4. Replicas(副本):Kafka 将日志复制多份来形成数据冗余,避免单点故障引起数据丢失,默认副本集数量可以在配置文件中进行配置:
>
> ~~~properties
> default.replication.factor=2
> ~~~
>
> 除此之外,在创建 Topic 时也可以单独指定副本集数量。
>
> 5. AR:分区的所有副本列表。
>
> 6. ISR:AR 的一个子集,由 Leader 负责维护,是一个保持一定程度同步的副本集合,如果 follower 落后 leader 太多就会被踢出 ISR 列表。
>
在三台机器上安装 Kafka(不能直接复制文件夹,会有权限问题)并修改配置文件,需要修改的信息如下:
1. `broker.id`:分别修改为 0、1、2。
2. 修改 listener 地址:
~~~properties
listeners=PLAINTEXT://192.168.253.136:9092
advertised.listeners=PLAINTEXT://192.168.253.136:9092
~~~
IP 地址改为本机的 IP 地址(不要使用 localhost)。
3. 修改 Zookeeper 的连接地址:
~~~properties
zookeeper.connect=192.168.253.136:2181
~~~
三个 Kafka 都连接同一个 Zookeeper 会自动组成集群。
1. Broker(代理):服务器上运行的 Kafka 的实例,在 Kafka 集群中每一个 Broker 对应一个唯一的 ID,即 BrokerId。
集群测试:
1. 创建多个分区、副本集的 Topic:
~~~java
public class AdminClientTest {
public static void main(String[] args) throws ExecutionException, InterruptedException {
Properties properties = new Properties();
properties.setProperty(AdminClientConfig.BOOTSTRAP_SERVERS_CONFIG, "192.168.253.136:9092");
AdminClient adminClient = AdminClient.create(properties);
NewTopic cluster = new NewTopic("cluster", 3, (short) 3);
adminClient.createTopics(Collections.singleton(cluster));
adminClient.close();
}
}
~~~
2. 获取 DescribeTopics 信息:
~~~json
(name=cluster,
internal=false,
partitions=
(partition=0, leader=192.168.253.137:9092 (id: 1 rack: null),
replicas=192.168.253.137:9092 (id: 1 rack: null), 192.168.253.135:9092 (id: 2 rack: null), 192.168.253.136:9092 (id: 0 rack: null),
isr=192.168.253.137:9092 (id: 1 rack: null), 192.168.253.135:9092 (id: 2 rack: null), 192.168.253.136:9092 (id: 0 rack: null)),
(partition=1, leader=192.168.253.136:9092 (id: 0 rack: null),
replicas=192.168.253.136:9092 (id: 0 rack: null), 192.168.253.137:9092 (id: 1 rack: null), 192.168.253.135:9092 (id: 2 rack: null),
isr=192.168.253.136:9092 (id: 0 rack: null), 192.168.253.137:9092 (id: 1 rack: null), 192.168.253.135:9092 (id: 2 rack: null)),
(partition=2, leader=192.168.253.135:9092 (id: 2 rack: null),
replicas=192.168.253.135:9092 (id: 2 rack: null), 192.168.253.136:9092 (id: 0 rack: null), 192.168.253.137:9092 (id: 1 rack: null),
isr=192.168.253.135:9092 (id: 2 rack: null), 192.168.253.136:9092 (id: 0 rack: null), 192.168.253.137:9092 (id: 1 rack: null)),
authorizedOperations=null)
~~~
分配了 3 个分区和 3 个副本后,Kafka 将不同的分区 leader 分配在不同的节点上,此外,同一个分区的不同副本也分布在不同的节点下,这样可以最大程度的减少因为节点故障带来的数据丢失。
kafka 节点故障原因:
1. Kafka 未与 Zookeeper 保持心跳。
2. follower 消息落后 leader 太多。
2. follower 消息落后 leader 太多(多的判定可以在配置文件中进行指定)。
> LEO 和 HW 概念
>
> LEO:指的是每个副本最大的 offset;
> HW:指的是消费者能读到的最大的 offset,ISR 队列中最小的 LEO。
>
> ![](../img/43cc8bce55c129453a0e1595b7241193.png)
Kafka 节点故障的故障处理:
1. follower 故障处理:follower 发生故障后会被临时踢出 ISR,待该 follower 恢复后,follower 会读取本地磁盘记录的上次的 HW,并将 log 文件高于 HW 的部分截取掉,从 HW 开始向 leader 进行同步。等该 follower 的 LEO 大于等于该 Partition 的 HW,就重新加入 ISR。
2. leader 故障处理:在 ISR 列表中选择一个最快的节点作为新的 leader。为保证多个副本之间的数据一致性,其余的 follower 会先将各自的 log 文件高于 HW 的部分截掉,然后从新的 leader 同步数据。
注:<u>这只能保证副本之间的数据一致性,并不能保证数据不丢失或者不重复</u>
> 脏选举(unclean leader):在极端情况下,如果 ISR 列表中的副本全部宕机,Kafka 可以通过脏选举的方式从非 ISR 列表中的节点中选出新的 leader,但是此种方式可能造成较大的数据丢失;一般来说,在生产环境中要禁用此功能:
>
> ~~~properties
> unclean.leader.election.enable=false
> ~~~
>
> 此外,最好手动指定最小的 ISR 列表节点个数:
>
> ~~~properties
> transaction.state.log.min.isr=3
> ~~~
Kafka 集群监控:可以通过开源组件`Kafka Manager`进行集群监控。
Kafka 节点故障处理:
Kafka 最佳实践配置:
1. 服务端必要参数:
~~~properties
broker.id=0
log.dirs=/var/log/kafka # 最好不要使用默认的 /tmp/kafka-logs
zookeeper.connect=192.168.253.136:2181
~~~
2. 服务端推荐参数:
1. `advertised.host.name``advertised.port`:如果配置了这两个值,Kafka 将会以这两个值配置的 IP 和端口注册到 zookeeper 而不会暴露自己的真实 IP 和 port,外网环境建议配置。
2. `default.replication.factor`:创建 topic 时默认的副本数量,建议至少为 2。
3. `unclean.leader.election.enable`:是否允许脏选举,建议 false,默认为 true。
4. `controlled.shutdown.enable`:配置为 true 时 broker 关闭之前会尝试转移自己的 leader 到其他的 broker 上;除此之外,我们还可以还可以设置`controlled.shutdown.max.retries``controlled.shutdown.retry.backoff.ms`来控制在执行过程中的最大耗费时间和重试次数;建议配置为 true。
3. 动态调整参数:
1. `num.partitions`:创建 topic 时默认的 partition 数量,默认是 1。
2. `min.insync.replicas`:当 producer 的 ack 为 -1 或 all 时,如果 ISR 列表中的副本数量少于此值,消息生产将不成功,默认为 1。
3. `max.message.bytes`:单条消息的最大长度,此条消息修改后`replica.fetch.max.bytes``fetch.message.max.bytes`也要同步修改。
4. 日志清理相关配置:
~~~properties
# 启用日志清理
log.cleaner.enable=true
# 对符合条件的日志进行删除,还可配置 compact(压缩)
log.cleanup.policy=delete
# 清理超过指定时间的日志
log.retention.hours=16
# 超过指定大小后,删除旧的消息
log.retention.bytes=1073741824
~~~
5. 消息存储的配置:
~~~properties
# 当内存消息达到多少条后,将消息刷新到磁盘
log.flush.interval.messages=10000
# 当间隔时间达到多少 ms 后,将消息刷新到磁盘。如果未设置则使用 log.flush.scheduler.interval.ms 中的值
log.flush.interval.ms=1000
# 日志刷新器检查是否需要将所有日志刷新到磁盘的频率
log.flush.scheduler.interval.ms=3000
~~~
---
#### 9.Kafka 集成微服务
#### 9.Kafka
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册