HBuilderX

HBuilderX

极客开发工具
uni-app

uni-app

开发一次,多端覆盖
uniCloud

uniCloud

云开发平台
HTML5+

HTML5+

增强HTML5的功能体验
MUI

MUI

上万Star的前端框架

正在流行的盲盒交友源码

盲盒交友 1元相亲

前端:uniapp
后台接口:java springboot
重点:暂无后台管理系统 稍后会完善 管理系统使用vue全家桶

加v zwb584223358 获取源码

扫码体验:

继续阅读 »

盲盒交友 1元相亲

前端:uniapp
后台接口:java springboot
重点:暂无后台管理系统 稍后会完善 管理系统使用vue全家桶

加v zwb584223358 获取源码

扫码体验:

收起阅读 »

hbuilder这么多bug,球球你们测试人员开发人员自己测测行么.............................已经被气到了

有时点击运行 运行到内置浏览器 没反应;需要运行到浏览器,把网址复制下来,粘贴到内置浏览器上,
新建一个目录,淦!!!!!!!!!!!!提示创建目录,服了,球球你们自己测一测!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!服了服了,要不是有个uniapp项目维护!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
我肯定不是第一个提出来这个问题的人, 点击运行到内置浏览器 上半年就有这个问题!!!!!!!!!!!!!!!!!!!!!!!!!

继续阅读 »

有时点击运行 运行到内置浏览器 没反应;需要运行到浏览器,把网址复制下来,粘贴到内置浏览器上,
新建一个目录,淦!!!!!!!!!!!!提示创建目录,服了,球球你们自己测一测!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!服了服了,要不是有个uniapp项目维护!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
我肯定不是第一个提出来这个问题的人, 点击运行到内置浏览器 上半年就有这个问题!!!!!!!!!!!!!!!!!!!!!!!!!

收起阅读 »

百亿级日志流分析实践 | 剖析个推后效分析功能实现原理

消息推送作为用户促活的有效利器,具有低成本、高效率的明显优势,已成为App运营中最重要的用户触达方式之一。为帮助开发者有策略地提升 消息推送的效果,增加消息的到达率和点击率,个推消息推送SDK于今年初重磅上线了后效分析功能,旨在为开发者和运营人员科学调整推送策略提供有效支撑。

后效分析功能上线后,我们结合产品目标和用户建议,进行了多次迭代。本文就开发和迭代过程中沉淀的经验与大家做分享,也欢迎感兴趣的开发者们通过企业微信和我们交流。

后效分析功能的开发背景

消息推送过程中,从服务端推送消息、消息到达客户端,到用户点击推送、打开应用的各阶段,都可能存在消息折损的情况。

以往,消息系统通过简单对比下发、到达、展示、点击等四个维度的数据,来计算消息的折损程度。但这样的消息折损计算方式不够准确,运营人员较难深入了解消息的折损原因,也就无法对推送参数、推送设置做出科学有效的改进。此外,以往客户遇到消息推送的问题时,会直接与技术支持人员联系解决,沟通和时间成本较高。

因此,我们需要设计出一种自动化方式,来帮助开发者清晰了解推送消息的各项后效数据,并能够自主、高效地找出消息折损的原因。

后效分析功能的开发思路

我们的解决思路是:

1.推出后效数据报表功能。通过将消息在服务端下发过程中的折损情况以及客户端回执数据进行梳理、统计,形成各环节后效数据的清晰报表,以帮助开发者和运营人员透过数据表象,快速定位出消息折损原因,找到提升推送效果的关键环节。

2.自动采集各推送模块日志并形成后效分析报告。通过不同模块获取推送日志:以类似人工查询日志的方式,将一些含有原因标识的日志进行统一存储和梳理,从而梳理出某条任务下发时产生的所有异常和折损原因。这其中就包含“目标正处于黑名单”“请求受到频控(或流控)限制”等原因。与人工技术支持相比,这样不仅能提高后效分析的效率,还能从一些以往可能被忽略的折损中自动提炼出问题,帮助用户自检并规避一些使用不当的情况。

后效分析功能的开发难点

在开发后效分析功能的过程中,我们也遇到了如下一些技术上的难点:

难点一:日志的聚合归类和后效原因提炼

在通过日志进行消息折损原因排查和分析的过程中,我们首先需要从海量日志数据中筛选出有效的部分,并对该部分日志数据进行归纳,根据我们预先设置的日志解析策略,对全链路的日志数据打上对应标记,以帮助我们分析消息在各阶段的折损原因。

为此,我们对消息推送的整个链路做了一次大梳理,从推送阶段入手,将推送模块区分为入口层、处理层、下发层、客户端等四层,然后对各层可能存在的消息折损原因进行了提炼:

✦在入口层,我们主要关注服务端收到的请求内容是否通过格式校验,以及各类目标参数是否设置无误,比如“CID是否有效”“鉴权信息是否异常”等。

✦在处理层,我们关注目标客户端是否符合下发条件,例如可能因为推送策略限制,导致服务端无法给部分客户端进行后续推送。

✦在下发层,我们关注客户端与服务端的网络连接是否正常,比如,在线通道是否有效等。

✦最终在客户端收到推送、用户点击消息时,客户端也会将回执汇报到服务端模块。这一阶段的消息折损原因可能是“通知开关没有打开”等。

基于以上业务层次区分,我们可以更清晰地看到消息推送的整体业务流程。我们将各阶段可能存在的异常关注点提炼出来,以便于我们梳理相对应的日志模块。最终我们将后效异常原因总结为12类,分别对应消息推送各阶段中可能遇到的折损情况。

难点二:TB级别日志数据的处理和准确计算

基于上述各场景,我们筛选出相关日志,通过前期的标记来提炼消息折损原因。

在一条消息的下发过程中,服务端会产生大量日志,单个功能节点一天的日志量就能达到TB级别。如何对亿级别的日志进行过滤和计算,成为我们进行后效数据分析的第一个难题.

我们通过Flume传输日志,将日志数据写入到HDFS,采用Spark作为计算引擎,HDFS存储原始日志数据和维度数据,最后的报表数据存放在ElasticSearch、Hbase和Mysql中。

海量日志数据的清洗和计算

根据对推送业务特性的了解,我们总结出推送日志数据可能存在的问题如下:

✦ 日志重复。例如,用户不断地登录和登出服务,从而产生大量的重复日志。
✦ 请求重复。例如,用户多次发起相同请求,对某个客户端发送同一条消息。客户端最终只会收到一次消息并展示,但服务器会产生多条重复的客户端/消息关联日志。
✦ 回执重复。下游回执中,由于客户端的网络环境复杂,有时会出现重复回执的情况,从而导致服务器重复打印回执日志。
✦ 日志不足。比如,一般情况下,关闭通知、设备活跃等客户端信息,在推送流程中不会有日志产生,这就必须依赖相关数据作为补充,才能综合评估出客户端的状态信息。

针对以上问题,我们提出的解决办法是“人群打标”。我们按照推送流程对日志数据进行划分,将推送任务影响到的人群分为到达人群、下发人群、请求人群等三类。我们根据消息与客户端的关联情况,对客户端进行打标。例如当采集到“在线下发模块”日志时,如果其中包含某消息与客户端的关联信息,那么我们就会给该推送任务下的客户端打上成功下发标记。每个标记只有0或1,不同日志不会重复打标,如此就避免了日志重复统计的情况。

结合上述人群打标逻辑,我们将四个维度的打标数据汇总,最终得到单个推送任务的原始数据。这份数据内,一个客户端会有多个标记,我们只需要按过滤逻辑将这些标记整理并归纳出最终状态,就可区分该条消息对这个客户端的下发流程最终到了哪一阶段,或是在哪一阶段因何种原因折损。

解决数据倾斜问题

在日志数据的计算过程中,我们还遇到了数据倾斜的问题。

我们按照消息下发阶段将整个日志计算任务拆分成四个。根据推送漏斗,这四个任务之间存在上下游关系。在对指标维度进行聚合的时候,会出现维度聚合体量差异过大导致数据倾斜的情况,甚至因为个别任务计算时间过久拖慢整体的计算进度。

为了解决该问题,我们需要在计算前和计算时对Spark任务进行处理,以减少数据倾斜。

我们采取的处理方式有:1.将大文件分割成小文件,或将小文件合并成大文件,以此保证每个任务处理的日志数据量均匀;2.优化分区策略,防止某个较大推送请求下的所有数据全部汇聚到同一节点,使节点计算压力更均衡;3.优化任务的计算链路,保证以最优的计算链路完成数据处理。

至此,基于如上所述的日志数据处理和计算逻辑,我们就可以在HBase中存储每条任务的后效数据,从而供业务层查询、调用。

总结

近期,我们还引入了Flink流式计算引擎来提升后效数据计算的实时性;我们也结合了更多的消息细则日志进一步完善数据,将后效数据报表升级,推出了消息链路查询功能,借此来帮助开发者更好地了解推送消息下发情况,并根据对应建议来快速提升消息的整体到达率。

“码”上注册和登录个推开发者中心(https://dev.getui.com/),体验个推后效分析功能和最新推出的消息链路查询功能吧!

继续阅读 »

消息推送作为用户促活的有效利器,具有低成本、高效率的明显优势,已成为App运营中最重要的用户触达方式之一。为帮助开发者有策略地提升 消息推送的效果,增加消息的到达率和点击率,个推消息推送SDK于今年初重磅上线了后效分析功能,旨在为开发者和运营人员科学调整推送策略提供有效支撑。

后效分析功能上线后,我们结合产品目标和用户建议,进行了多次迭代。本文就开发和迭代过程中沉淀的经验与大家做分享,也欢迎感兴趣的开发者们通过企业微信和我们交流。

后效分析功能的开发背景

消息推送过程中,从服务端推送消息、消息到达客户端,到用户点击推送、打开应用的各阶段,都可能存在消息折损的情况。

以往,消息系统通过简单对比下发、到达、展示、点击等四个维度的数据,来计算消息的折损程度。但这样的消息折损计算方式不够准确,运营人员较难深入了解消息的折损原因,也就无法对推送参数、推送设置做出科学有效的改进。此外,以往客户遇到消息推送的问题时,会直接与技术支持人员联系解决,沟通和时间成本较高。

因此,我们需要设计出一种自动化方式,来帮助开发者清晰了解推送消息的各项后效数据,并能够自主、高效地找出消息折损的原因。

后效分析功能的开发思路

我们的解决思路是:

1.推出后效数据报表功能。通过将消息在服务端下发过程中的折损情况以及客户端回执数据进行梳理、统计,形成各环节后效数据的清晰报表,以帮助开发者和运营人员透过数据表象,快速定位出消息折损原因,找到提升推送效果的关键环节。

2.自动采集各推送模块日志并形成后效分析报告。通过不同模块获取推送日志:以类似人工查询日志的方式,将一些含有原因标识的日志进行统一存储和梳理,从而梳理出某条任务下发时产生的所有异常和折损原因。这其中就包含“目标正处于黑名单”“请求受到频控(或流控)限制”等原因。与人工技术支持相比,这样不仅能提高后效分析的效率,还能从一些以往可能被忽略的折损中自动提炼出问题,帮助用户自检并规避一些使用不当的情况。

后效分析功能的开发难点

在开发后效分析功能的过程中,我们也遇到了如下一些技术上的难点:

难点一:日志的聚合归类和后效原因提炼

在通过日志进行消息折损原因排查和分析的过程中,我们首先需要从海量日志数据中筛选出有效的部分,并对该部分日志数据进行归纳,根据我们预先设置的日志解析策略,对全链路的日志数据打上对应标记,以帮助我们分析消息在各阶段的折损原因。

为此,我们对消息推送的整个链路做了一次大梳理,从推送阶段入手,将推送模块区分为入口层、处理层、下发层、客户端等四层,然后对各层可能存在的消息折损原因进行了提炼:

✦在入口层,我们主要关注服务端收到的请求内容是否通过格式校验,以及各类目标参数是否设置无误,比如“CID是否有效”“鉴权信息是否异常”等。

✦在处理层,我们关注目标客户端是否符合下发条件,例如可能因为推送策略限制,导致服务端无法给部分客户端进行后续推送。

✦在下发层,我们关注客户端与服务端的网络连接是否正常,比如,在线通道是否有效等。

✦最终在客户端收到推送、用户点击消息时,客户端也会将回执汇报到服务端模块。这一阶段的消息折损原因可能是“通知开关没有打开”等。

基于以上业务层次区分,我们可以更清晰地看到消息推送的整体业务流程。我们将各阶段可能存在的异常关注点提炼出来,以便于我们梳理相对应的日志模块。最终我们将后效异常原因总结为12类,分别对应消息推送各阶段中可能遇到的折损情况。

难点二:TB级别日志数据的处理和准确计算

基于上述各场景,我们筛选出相关日志,通过前期的标记来提炼消息折损原因。

在一条消息的下发过程中,服务端会产生大量日志,单个功能节点一天的日志量就能达到TB级别。如何对亿级别的日志进行过滤和计算,成为我们进行后效数据分析的第一个难题.

我们通过Flume传输日志,将日志数据写入到HDFS,采用Spark作为计算引擎,HDFS存储原始日志数据和维度数据,最后的报表数据存放在ElasticSearch、Hbase和Mysql中。

海量日志数据的清洗和计算

根据对推送业务特性的了解,我们总结出推送日志数据可能存在的问题如下:

✦ 日志重复。例如,用户不断地登录和登出服务,从而产生大量的重复日志。
✦ 请求重复。例如,用户多次发起相同请求,对某个客户端发送同一条消息。客户端最终只会收到一次消息并展示,但服务器会产生多条重复的客户端/消息关联日志。
✦ 回执重复。下游回执中,由于客户端的网络环境复杂,有时会出现重复回执的情况,从而导致服务器重复打印回执日志。
✦ 日志不足。比如,一般情况下,关闭通知、设备活跃等客户端信息,在推送流程中不会有日志产生,这就必须依赖相关数据作为补充,才能综合评估出客户端的状态信息。

针对以上问题,我们提出的解决办法是“人群打标”。我们按照推送流程对日志数据进行划分,将推送任务影响到的人群分为到达人群、下发人群、请求人群等三类。我们根据消息与客户端的关联情况,对客户端进行打标。例如当采集到“在线下发模块”日志时,如果其中包含某消息与客户端的关联信息,那么我们就会给该推送任务下的客户端打上成功下发标记。每个标记只有0或1,不同日志不会重复打标,如此就避免了日志重复统计的情况。

结合上述人群打标逻辑,我们将四个维度的打标数据汇总,最终得到单个推送任务的原始数据。这份数据内,一个客户端会有多个标记,我们只需要按过滤逻辑将这些标记整理并归纳出最终状态,就可区分该条消息对这个客户端的下发流程最终到了哪一阶段,或是在哪一阶段因何种原因折损。

解决数据倾斜问题

在日志数据的计算过程中,我们还遇到了数据倾斜的问题。

我们按照消息下发阶段将整个日志计算任务拆分成四个。根据推送漏斗,这四个任务之间存在上下游关系。在对指标维度进行聚合的时候,会出现维度聚合体量差异过大导致数据倾斜的情况,甚至因为个别任务计算时间过久拖慢整体的计算进度。

为了解决该问题,我们需要在计算前和计算时对Spark任务进行处理,以减少数据倾斜。

我们采取的处理方式有:1.将大文件分割成小文件,或将小文件合并成大文件,以此保证每个任务处理的日志数据量均匀;2.优化分区策略,防止某个较大推送请求下的所有数据全部汇聚到同一节点,使节点计算压力更均衡;3.优化任务的计算链路,保证以最优的计算链路完成数据处理。

至此,基于如上所述的日志数据处理和计算逻辑,我们就可以在HBase中存储每条任务的后效数据,从而供业务层查询、调用。

总结

近期,我们还引入了Flink流式计算引擎来提升后效数据计算的实时性;我们也结合了更多的消息细则日志进一步完善数据,将后效数据报表升级,推出了消息链路查询功能,借此来帮助开发者更好地了解推送消息下发情况,并根据对应建议来快速提升消息的整体到达率。

“码”上注册和登录个推开发者中心(https://dev.getui.com/),体验个推后效分析功能和最新推出的消息链路查询功能吧!

收起阅读 »

从需求到产品,个推消息中心做了多少准备?

消息推送

个推消息中心从解决一个用户痛点需求为起点,经过不断地打磨,已经成为了一款热销的系统平台产品。尤其是在金融行业,个推消息中心帮助银行APP对海量、多渠道的推送消息进行数字化运营管理。前不久,个推消息中心还荣获了“2021中国金融数字科技创新大赛”综合智能平台类银奖。那么,个推消息中心为什么能快速获得客户和行业的认可?在产品设计和架构过程中又有哪些妙思?就让我们通过这份产品经理的独白来了解产品背后的故事。

消息统一管理和运营是未来的趋势

APP想要与用户产生互动就需要消息推送,这是刚需。然而,随着技术的发展,APP对于消息推送也提出了越来越高的要求。消息推送已经不仅仅是用户收到一条信息那么简单,在消息推送之前会有更多连接业务场景的前置需求,因此需要有一个运营和管理系统平台去实现消息的精细化推送。

我们早期合作的一家证券机构,他们的股票交易APP一直使用个推消息推送SDK,每天都要下发海量的用户交易信息、行情信息、服务信息等。然而,随着微信服务号、小程序风口的到来,市场上信息触达的渠道变得越来越多,单一的APP推送通道已经不能满足APP用户触达的需求。此外,随着APP与业务紧密度的加深,APP消息推送的下发条件越来越复杂,下发场景也越来越多样化。为了帮助这家证券机构更好地运营和管理需要下发给用户的消息,我们设想搭建一套消息下发系统平台,对消息进行统一接入、统一管理以及多策略消息智能下发。这就是个推消息中心诞生的初衷。

调研数十家客户,提升产品的应用性

个推消息中心之所以能快速部署,快速应用,且出错率低、兼容性强,是因为在产品架构之初,我们做了充分的调研,从提升应用性的角度出发,梳理出产品的核心需求点。

首先,我们基于对消息中心需求的理解,基于APP对多渠道接入和业务需求的发展方向考虑,制定了个推消息中心最初的核心需求点:

· 统一接口、统一调度、统一对接、统一下发

· 覆盖当时市面上最常用的触达渠道,包括但不限于APP推送、微信、短信、智能外呼等

· 支持自定义策略,配置业务策略实现智能下发

之后,我们细化整理出了一套比较详细的个推消息中心行业解决方案,然后拿着这份方案去找不同的APP客户开展调研。每完成一个APP客户的调研,我们会将该APP客户对个推消息中心的理解,以及提出的实际应用上的新需求进行梳理,对方案进行优化调整,结合其他行业客户的需求点,进行综合考量,并持续调研了十几家APP客户,才最终确认了个推消息中心的实际用户需求,形成了产品雏形。

从消息推送小闭环到智能触达大闭环

从确认需求到形成产品,最大的难题是在各类功能中做出抉择,既能满足用户需求又能体现自身产品的优势。最终经过反复推敲,我们确定了两个核心能力:

· 统一管理消息下发渠道系统

· 智能消息下发策略系统

个推消息中心将上述这两个能力融合在一起,帮助APP快速架构消息推送小闭环,智能升级消息运营大闭环。

小闭环是指消息推送对接、下发、回执的全过程。个推消息中心是以个推消息推送为基础搭建的上层系统,与个推消息推送算是“同胞兄弟”,能够自动对接个推消息推送的所有功能,这样就免去了中间的各种适配和对接流程,甚至包括推送回执、推送数据、后效分析报表等数据的交互都十分顺畅。此外,个推消息中心对下发通道做了全面提升,在保证下发效果的同时,对上游业务层提供统一的调用接口,同时打通下游各渠道的识别ID,协助客户建立统一的用户运营ID,最大限度方便APP做消息对接。

图:消息推送系统图

大闭环指的是与业务端相匹配的消息运营的全生命周期,帮助APP解决消息生成,消息发送,提升下发效果等问题。因此,个推消息中心在设计产品时,在“智能推送”这个功能上花了很多心思,涵盖行业各种经典推送场景,包括并发、补发、分发策略,以实现各种策略灵活可配置,让APP可以多维度地制定下发策略,一站式完成多渠道多用户群的消息下发,清晰呈现完整的业务流程,助力APP开展精细化用户运营。

图:消息运营全生命周期

满足每条消息背后独特的触发条件

智能推送规则引擎是个推消息中心最核心的功能,其包含用户分级规则,通道分级规则,业务场景规则等,最终它将跟APP的精细化运营深度结合。

个推消息中心的规则引擎不仅解决了智能推送和高并发兼容的问题,将智能推送策略对消息下发的影响降到了最低;最重要的是,个推消息中心的规则引擎里,更新上线的每一条策略都经过无数的实战检验,与业务场景匹配度极高。

智能推送的整体逻辑,主要是并发、补发、分发,但是设置并发、补发、分发的事件触发规则往往各不相同。因此,在设计规则引擎的时候,我们对个推消息推送历史样例做了深度分析,总结出公共范式,提取出独立的规则引擎模块,通过规则引擎计算消息应该走哪个渠道,用什么消息模板。

图:规则引擎示意图

在技术上,我们把高频事件触发的逻辑写在了业务代码中,这样就能有效提高业务耦合性。此外,我们还在规则引擎框架、通信层面、线程池、JVM(虚拟机)等方面进行了全面的优化,使规则引擎对业务性能的影响降到了最低,即使面对上亿的下发量需求,也能秒级下发。

规则引擎里的应用场景模板是需要不断迭代优化的,我们在规则引擎中引入了机器学习模型,会对每一次推送的数据进行归集分析、学习优化,不断沉淀和优化下发策略,不断优化各个应用场景模板,提升消息下发的效果。

图:场景模板

深耕金融行业赋能数字化升级

金融行业是个推消息中心率先沉浸的行业。金融行业正处于数字化升级的爆发期,用户体量大,消息推送场景多元化,下发量大,对消息运营整体系统建设的需求十分强烈。个推消息中心的出现不仅能解决金融机构对通道集成、统一推送的诉求,还能轻松对接智能运营中心,满足金融行业数字化升级中的精细化运营诉求。

金融类APP服务多元,为增强这类APP用户的粘性,个推消息中心能够提供一套用户触达的全流程闭环方案。把消息触发生成、消息组装、消息分发、消息触达、消息展示以及后效分析这些环节整合起来,不仅能更清晰地看到消息的整个生命周期,还能提高营销、运营活动的效果,让整个运营流程更加高效。

持续的精心规划、多方实践,为个推消息中心积累了丰富的成功案例和深厚的行业经验。未来,我们将朝着消息运营的整体解决方案持续前进,为各类APP提供更灵活、更高效的服务。APP可根据目前实际业务需求来选择不同等级的服务,从简单的建立推送通道,到无缝升级为消息中心,最终建立起完整的消息运营平台,全面助力APP精细化运营。

扫描二维码,立即咨询

继续阅读 »

个推消息中心从解决一个用户痛点需求为起点,经过不断地打磨,已经成为了一款热销的系统平台产品。尤其是在金融行业,个推消息中心帮助银行APP对海量、多渠道的推送消息进行数字化运营管理。前不久,个推消息中心还荣获了“2021中国金融数字科技创新大赛”综合智能平台类银奖。那么,个推消息中心为什么能快速获得客户和行业的认可?在产品设计和架构过程中又有哪些妙思?就让我们通过这份产品经理的独白来了解产品背后的故事。

消息统一管理和运营是未来的趋势

APP想要与用户产生互动就需要消息推送,这是刚需。然而,随着技术的发展,APP对于消息推送也提出了越来越高的要求。消息推送已经不仅仅是用户收到一条信息那么简单,在消息推送之前会有更多连接业务场景的前置需求,因此需要有一个运营和管理系统平台去实现消息的精细化推送。

我们早期合作的一家证券机构,他们的股票交易APP一直使用个推消息推送SDK,每天都要下发海量的用户交易信息、行情信息、服务信息等。然而,随着微信服务号、小程序风口的到来,市场上信息触达的渠道变得越来越多,单一的APP推送通道已经不能满足APP用户触达的需求。此外,随着APP与业务紧密度的加深,APP消息推送的下发条件越来越复杂,下发场景也越来越多样化。为了帮助这家证券机构更好地运营和管理需要下发给用户的消息,我们设想搭建一套消息下发系统平台,对消息进行统一接入、统一管理以及多策略消息智能下发。这就是个推消息中心诞生的初衷。

调研数十家客户,提升产品的应用性

个推消息中心之所以能快速部署,快速应用,且出错率低、兼容性强,是因为在产品架构之初,我们做了充分的调研,从提升应用性的角度出发,梳理出产品的核心需求点。

首先,我们基于对消息中心需求的理解,基于APP对多渠道接入和业务需求的发展方向考虑,制定了个推消息中心最初的核心需求点:

· 统一接口、统一调度、统一对接、统一下发

· 覆盖当时市面上最常用的触达渠道,包括但不限于APP推送、微信、短信、智能外呼等

· 支持自定义策略,配置业务策略实现智能下发

之后,我们细化整理出了一套比较详细的个推消息中心行业解决方案,然后拿着这份方案去找不同的APP客户开展调研。每完成一个APP客户的调研,我们会将该APP客户对个推消息中心的理解,以及提出的实际应用上的新需求进行梳理,对方案进行优化调整,结合其他行业客户的需求点,进行综合考量,并持续调研了十几家APP客户,才最终确认了个推消息中心的实际用户需求,形成了产品雏形。

从消息推送小闭环到智能触达大闭环

从确认需求到形成产品,最大的难题是在各类功能中做出抉择,既能满足用户需求又能体现自身产品的优势。最终经过反复推敲,我们确定了两个核心能力:

· 统一管理消息下发渠道系统

· 智能消息下发策略系统

个推消息中心将上述这两个能力融合在一起,帮助APP快速架构消息推送小闭环,智能升级消息运营大闭环。

小闭环是指消息推送对接、下发、回执的全过程。个推消息中心是以个推消息推送为基础搭建的上层系统,与个推消息推送算是“同胞兄弟”,能够自动对接个推消息推送的所有功能,这样就免去了中间的各种适配和对接流程,甚至包括推送回执、推送数据、后效分析报表等数据的交互都十分顺畅。此外,个推消息中心对下发通道做了全面提升,在保证下发效果的同时,对上游业务层提供统一的调用接口,同时打通下游各渠道的识别ID,协助客户建立统一的用户运营ID,最大限度方便APP做消息对接。

图:消息推送系统图

大闭环指的是与业务端相匹配的消息运营的全生命周期,帮助APP解决消息生成,消息发送,提升下发效果等问题。因此,个推消息中心在设计产品时,在“智能推送”这个功能上花了很多心思,涵盖行业各种经典推送场景,包括并发、补发、分发策略,以实现各种策略灵活可配置,让APP可以多维度地制定下发策略,一站式完成多渠道多用户群的消息下发,清晰呈现完整的业务流程,助力APP开展精细化用户运营。

图:消息运营全生命周期

满足每条消息背后独特的触发条件

智能推送规则引擎是个推消息中心最核心的功能,其包含用户分级规则,通道分级规则,业务场景规则等,最终它将跟APP的精细化运营深度结合。

个推消息中心的规则引擎不仅解决了智能推送和高并发兼容的问题,将智能推送策略对消息下发的影响降到了最低;最重要的是,个推消息中心的规则引擎里,更新上线的每一条策略都经过无数的实战检验,与业务场景匹配度极高。

智能推送的整体逻辑,主要是并发、补发、分发,但是设置并发、补发、分发的事件触发规则往往各不相同。因此,在设计规则引擎的时候,我们对个推消息推送历史样例做了深度分析,总结出公共范式,提取出独立的规则引擎模块,通过规则引擎计算消息应该走哪个渠道,用什么消息模板。

图:规则引擎示意图

在技术上,我们把高频事件触发的逻辑写在了业务代码中,这样就能有效提高业务耦合性。此外,我们还在规则引擎框架、通信层面、线程池、JVM(虚拟机)等方面进行了全面的优化,使规则引擎对业务性能的影响降到了最低,即使面对上亿的下发量需求,也能秒级下发。

规则引擎里的应用场景模板是需要不断迭代优化的,我们在规则引擎中引入了机器学习模型,会对每一次推送的数据进行归集分析、学习优化,不断沉淀和优化下发策略,不断优化各个应用场景模板,提升消息下发的效果。

图:场景模板

深耕金融行业赋能数字化升级

金融行业是个推消息中心率先沉浸的行业。金融行业正处于数字化升级的爆发期,用户体量大,消息推送场景多元化,下发量大,对消息运营整体系统建设的需求十分强烈。个推消息中心的出现不仅能解决金融机构对通道集成、统一推送的诉求,还能轻松对接智能运营中心,满足金融行业数字化升级中的精细化运营诉求。

金融类APP服务多元,为增强这类APP用户的粘性,个推消息中心能够提供一套用户触达的全流程闭环方案。把消息触发生成、消息组装、消息分发、消息触达、消息展示以及后效分析这些环节整合起来,不仅能更清晰地看到消息的整个生命周期,还能提高营销、运营活动的效果,让整个运营流程更加高效。

持续的精心规划、多方实践,为个推消息中心积累了丰富的成功案例和深厚的行业经验。未来,我们将朝着消息运营的整体解决方案持续前进,为各类APP提供更灵活、更高效的服务。APP可根据目前实际业务需求来选择不同等级的服务,从简单的建立推送通道,到无缝升级为消息中心,最终建立起完整的消息运营平台,全面助力APP精细化运营。

扫描二维码,立即咨询

收起阅读 »

APP自定义tabbar

tabbar uni_app

现在官方的tabbar无法满足根据身份切换tabbar数量的需求,自定义tabbar需要写在一个界面用来避免tababr闪烁的问题。

我的实现思路是这样的:

首先home.vue里面写一个自定义的tabbar

把tabbar的界面分开单独写成组件,放到components里面

然后根据v-if去动态显示封装成组件的界面,这样就避免了tabbar的闪烁,也不需要很复杂的把逻辑写到一个界面

但是组件里面的页面跳转可能需要根据相对路径去跳转

继续阅读 »

现在官方的tabbar无法满足根据身份切换tabbar数量的需求,自定义tabbar需要写在一个界面用来避免tababr闪烁的问题。

我的实现思路是这样的:

首先home.vue里面写一个自定义的tabbar

把tabbar的界面分开单独写成组件,放到components里面

然后根据v-if去动态显示封装成组件的界面,这样就避免了tabbar的闪烁,也不需要很复杂的把逻辑写到一个界面

但是组件里面的页面跳转可能需要根据相对路径去跳转

收起阅读 »

【交流】大家都怎么使用UNIAPP的呢?

混合开发

用了这么长时间的UNI-APP,一直在思考一个问题:怎么使用UNI-APP是最容易对项目进行维护和迭代开发的呢?

不知道大家都是怎么用的:

  • 跨端开发技术应用

    1. 一个项目代码,支持多端应用: 比如同时支持H5、小程序、Android APP、IOS APP,充分使用UNI-APP预编译技术。
    2. 统一技术栈,支持多个项目开发: 比如统一使用Vue框架,以每个端单独建立一个项目为主。
  • 实际项目使用情况

    1. 一个项目代码同时支持了Android APP、IOS APP
    2. 一个项目代码同时支持了Android APP、IOS APP、小程序(weapp、alipay)应用
    3. 一个项目代码同时支持了H5、Android APP、IOS APP
    4. 一个项目代码同时支持了H5、小程序(weapp、alipay)应用
    5. 分别创建不同的项目代码维护H5、小程序、Android APP、IOS APP应用
继续阅读 »

用了这么长时间的UNI-APP,一直在思考一个问题:怎么使用UNI-APP是最容易对项目进行维护和迭代开发的呢?

不知道大家都是怎么用的:

  • 跨端开发技术应用

    1. 一个项目代码,支持多端应用: 比如同时支持H5、小程序、Android APP、IOS APP,充分使用UNI-APP预编译技术。
    2. 统一技术栈,支持多个项目开发: 比如统一使用Vue框架,以每个端单独建立一个项目为主。
  • 实际项目使用情况

    1. 一个项目代码同时支持了Android APP、IOS APP
    2. 一个项目代码同时支持了Android APP、IOS APP、小程序(weapp、alipay)应用
    3. 一个项目代码同时支持了H5、Android APP、IOS APP
    4. 一个项目代码同时支持了H5、小程序(weapp、alipay)应用
    5. 分别创建不同的项目代码维护H5、小程序、Android APP、IOS APP应用
收起阅读 »

nvue中使用swiper的显示问题

nvue

今天遇到一个问题,之前在vue下运行的swiper无论如何都无法正常运行,就是显示不出来。经过反复试验,总算发现了问题所在。

之前的vue写法是

没有问题,然而转到nvue,中间的内容无论如何都无法显示了。很困惑。最后发现不能使用block来做循环,必须直接在swiper-item上进行循环

这样就可以显示了,具体原因没有看,给大家一个参考,避免多花时间。

继续阅读 »

今天遇到一个问题,之前在vue下运行的swiper无论如何都无法正常运行,就是显示不出来。经过反复试验,总算发现了问题所在。

之前的vue写法是

没有问题,然而转到nvue,中间的内容无论如何都无法显示了。很困惑。最后发现不能使用block来做循环,必须直接在swiper-item上进行循环

这样就可以显示了,具体原因没有看,给大家一个参考,避免多花时间。

收起阅读 »

renderjs-echarts-demo 在APP端和H5上的点击事件

demo就是官方提供的demo,
主要就是在main.js中加
//#ifdef H5
window.wx = {}
//#endif
但是加了是否会出现其他的问题,暂时不知道..

解决方案是在CSDN上看到的,具体原因不在解释;看图片
代码部分

<script>  
export default {  
    .......,  
    methods:{  
       onViewClick(options) {  
      console.log(options)  
    }  
    }  
}  
</script>  

<script module="echarts" lang="renderjs">  
    let myChart  
    export default {  
        data() {  
            return {  
                clickData: null  
            }  
        },  
        mounted() {  
            if (typeof window.echarts === 'function') {  
                this.initEcharts()  
            } else {  
                // 动态引入较大类库避免影响页面展示  
                const script = document.createElement('script')  
                // view 层的页面运行在 www 根目录,其相对路径相对于 www 计算  
                script.src = 'static/echarts.js'  
                script.onload = this.initEcharts.bind(this)  
                document.head.appendChild(script)  
            }  
        },  
        methods: {  
            initEcharts() {  
                myChart = echarts.init(document.getElementById('echarts'))  
                // 观测更新的数据在 view 层可以直接访问到  
                let _this = this;  
                myChart.setOption(this.option);  

                myChart.on('click', function(e) {  
                    _this.clickData = e;  
                })  
            },  
            updateEcharts(newValue, oldValue, ownerInstance, instance) {  
                // 监听 service 层数据变更  
                myChart.setOption(newValue);  
            },  
            onClick(event, ownerInstance) {  
                // 调用 service 层的方法  
                let _this = this;  
                ownerInstance.callMethod('onViewClick', {  
                    name : _this.clickData.name,  
                    val : _this.clickData.value  
                })  
            }  
        }  
    }  
</script>
继续阅读 »

demo就是官方提供的demo,
主要就是在main.js中加
//#ifdef H5
window.wx = {}
//#endif
但是加了是否会出现其他的问题,暂时不知道..

解决方案是在CSDN上看到的,具体原因不在解释;看图片
代码部分

<script>  
export default {  
    .......,  
    methods:{  
       onViewClick(options) {  
      console.log(options)  
    }  
    }  
}  
</script>  

<script module="echarts" lang="renderjs">  
    let myChart  
    export default {  
        data() {  
            return {  
                clickData: null  
            }  
        },  
        mounted() {  
            if (typeof window.echarts === 'function') {  
                this.initEcharts()  
            } else {  
                // 动态引入较大类库避免影响页面展示  
                const script = document.createElement('script')  
                // view 层的页面运行在 www 根目录,其相对路径相对于 www 计算  
                script.src = 'static/echarts.js'  
                script.onload = this.initEcharts.bind(this)  
                document.head.appendChild(script)  
            }  
        },  
        methods: {  
            initEcharts() {  
                myChart = echarts.init(document.getElementById('echarts'))  
                // 观测更新的数据在 view 层可以直接访问到  
                let _this = this;  
                myChart.setOption(this.option);  

                myChart.on('click', function(e) {  
                    _this.clickData = e;  
                })  
            },  
            updateEcharts(newValue, oldValue, ownerInstance, instance) {  
                // 监听 service 层数据变更  
                myChart.setOption(newValue);  
            },  
            onClick(event, ownerInstance) {  
                // 调用 service 层的方法  
                let _this = this;  
                ownerInstance.callMethod('onViewClick', {  
                    name : _this.clickData.name,  
                    val : _this.clickData.value  
                })  
            }  
        }  
    }  
</script>
收起阅读 »

【记录】微信支付,调起支付接口,payment微信:-1]General errors

微信支付

ios端可以调起支付 安卓端不能调起支付,会报General errors的错误
原因是在微信开放平台填写应该签名信息的时候使用了大写 用冒号隔开的签名
后来修改成 小写的一串就解决了 修改之后需要稍等一会 清除缓存应该就可以了 。 如果还是报错 那应该是其他原因。

继续阅读 »

ios端可以调起支付 安卓端不能调起支付,会报General errors的错误
原因是在微信开放平台填写应该签名信息的时候使用了大写 用冒号隔开的签名
后来修改成 小写的一串就解决了 修改之后需要稍等一会 清除缓存应该就可以了 。 如果还是报错 那应该是其他原因。

收起阅读 »

uni app环境下解决video无法跟随div滚动条滚动的问题

video

uni app环境下vue文件中,video因为用的是原生组件,所以只能跟随页面的滚动条。

假如你写了一个带滚动条的div,里面写了一个video标签,那对不起,video不会跟着滚动。

废话不多说,解决代码如下:

video组件的代码如下,实现思路就是借助iframe,通信就采用手动去触发事件

<template>  
    <iframe @event1="event1" @event2="event2" :onload="onloadCode" src="about:blank" style="border:1px solid;height: 300px;width: 100%"></iframe>  
</template>  

<script>  
    export default {  
        data() {  
            return {  
                onloadCode: `  
                const url = 'https://vd3.bdstatic.com/mda-mja2qsy47mbyh1xc/sc/cae_h264_clips/1633918903861514556/mda-mja2qsy47mbyh1xc.mp4?auth_key=1634030413-0-0-7898726f7bd328302e2119fdf694fd5e&bcevod_channel=searchbox_feed&pd=1&pt=3&abtest='  
                this.contentWindow.document.body.innerHTML = '<video style="width: 100%;height: 100%" controls="controls" src="'+url+'"></video>';  
                const iframe = top.document.getElementsByTagName('iframe')[0]  
                var evObj = document.createEvent('MouseEvents');  
                evObj.initEvent( 'event1', true, false );  
                iframe.dispatchEvent(evObj)  
                `  
            }   
        },  
        onShow() {  

        },  

        methods: {  
            event1(a) {  
                console.log(a)  
            },  
            event2(a) {  
                console.log(a)  
            }  
        }  
    }  
</script>  

<style>  
</style>  

以下是调用video,解决div滚动时video不跟随的代码

<template>  
    <view class="content">  
        <view class="text-area">  
            <div class="pos">  
                <Video />  
                <div class="zw">占位专用占位专用占位专用占位专用占位专用占位专用占位专用占位专用占位专用</div>  
                <div class="zw">占位专用占位专用占位专用占位专用占位专用占位专用占位专用占位专用占位专用</div>  
            </div>  
            <div class="zw">占位专用占位专用占位专用占位专用占位专用占位专用占位专用占位专用占位专用</div>  
            <div class="zw">占位专用占位专用占位专用占位专用占位专用占位专用占位专用占位专用占位专用</div>  
        </view>  
    </view>  
</template>  

<script>  
    import Video from './video/index.vue'  
    export default {  
        components: {  
            Video  
        }  
    }  
</script>  

<style>  
    .pos {  
        position: fixed;  
        bottom: 0;  
        background: red;  
        left: 0;  
        right: 0;  
        height: 500px;  
        overflow: auto;  
    }  
    .zw {  
        word-break: break-all;  
        height: 800px;  
    }  
</style>

app运行效果图如下,可以看出video是可以跟随div滚动的

继续阅读 »

uni app环境下vue文件中,video因为用的是原生组件,所以只能跟随页面的滚动条。

假如你写了一个带滚动条的div,里面写了一个video标签,那对不起,video不会跟着滚动。

废话不多说,解决代码如下:

video组件的代码如下,实现思路就是借助iframe,通信就采用手动去触发事件

<template>  
    <iframe @event1="event1" @event2="event2" :onload="onloadCode" src="about:blank" style="border:1px solid;height: 300px;width: 100%"></iframe>  
</template>  

<script>  
    export default {  
        data() {  
            return {  
                onloadCode: `  
                const url = 'https://vd3.bdstatic.com/mda-mja2qsy47mbyh1xc/sc/cae_h264_clips/1633918903861514556/mda-mja2qsy47mbyh1xc.mp4?auth_key=1634030413-0-0-7898726f7bd328302e2119fdf694fd5e&bcevod_channel=searchbox_feed&pd=1&pt=3&abtest='  
                this.contentWindow.document.body.innerHTML = '<video style="width: 100%;height: 100%" controls="controls" src="'+url+'"></video>';  
                const iframe = top.document.getElementsByTagName('iframe')[0]  
                var evObj = document.createEvent('MouseEvents');  
                evObj.initEvent( 'event1', true, false );  
                iframe.dispatchEvent(evObj)  
                `  
            }   
        },  
        onShow() {  

        },  

        methods: {  
            event1(a) {  
                console.log(a)  
            },  
            event2(a) {  
                console.log(a)  
            }  
        }  
    }  
</script>  

<style>  
</style>  

以下是调用video,解决div滚动时video不跟随的代码

<template>  
    <view class="content">  
        <view class="text-area">  
            <div class="pos">  
                <Video />  
                <div class="zw">占位专用占位专用占位专用占位专用占位专用占位专用占位专用占位专用占位专用</div>  
                <div class="zw">占位专用占位专用占位专用占位专用占位专用占位专用占位专用占位专用占位专用</div>  
            </div>  
            <div class="zw">占位专用占位专用占位专用占位专用占位专用占位专用占位专用占位专用占位专用</div>  
            <div class="zw">占位专用占位专用占位专用占位专用占位专用占位专用占位专用占位专用占位专用</div>  
        </view>  
    </view>  
</template>  

<script>  
    import Video from './video/index.vue'  
    export default {  
        components: {  
            Video  
        }  
    }  
</script>  

<style>  
    .pos {  
        position: fixed;  
        bottom: 0;  
        background: red;  
        left: 0;  
        right: 0;  
        height: 500px;  
        overflow: auto;  
    }  
    .zw {  
        word-break: break-all;  
        height: 800px;  
    }  
</style>

app运行效果图如下,可以看出video是可以跟随div滚动的

收起阅读 »

vue3编译到微信小程序,报错

bug提交

// 我在设置里面选了vue3版本其他没问题就是使用不了jsx
export default {
setup() {
const msg = ref(123);
const change = param => {
console.log(param);
msg.value ;
};
const dianWo = <button type="primary" onTap={change}>点我</button>

return () => (  
  <view class="index">  
    <view onTap={change.bind(null, 221)}>{msg.value}</view>  
    <button type="primary" onTap={change}>  
      {obj.zxc?.length}  
    </button>  
    {dianWo}  
  </view>  
);  

}
};

继续阅读 »

// 我在设置里面选了vue3版本其他没问题就是使用不了jsx
export default {
setup() {
const msg = ref(123);
const change = param => {
console.log(param);
msg.value ;
};
const dianWo = <button type="primary" onTap={change}>点我</button>

return () => (  
  <view class="index">  
    <view onTap={change.bind(null, 221)}>{msg.value}</view>  
    <button type="primary" onTap={change}>  
      {obj.zxc?.length}  
    </button>  
    {dianWo}  
  </view>  
);  

}
};

收起阅读 »