初次接触氛围系统架构,聊聊我这三个月的理解

news2024/10/6 0:32:43

2c0e3f64732b7c63db46bdf8b4a786a0.gif

本文主要介绍了作者对于氛围中心的业务理解。从氛围的概念出发,阐述了氛围系统的必要性,然后展示了配置端的数据写入、调用端的配置读取等氛围系统的架构细节,最后作者提出了一些对于氛围中心未来的想法和思考。

a25ba4a8c6ca35d51abaa3e0341c1be5.png

概述

  氛围的概念

氛围是能够刺激消费者购买欲望的一类视觉表达。氛围一般与优惠、价格相关,其目的在于烘托当前商品所处的营销氛围,促进消费者的购买欲望。

c203d7088cc3bea94c62aceb357474d6.png

  氛围的概念

  1. 从产品的角度,氛围中心提供了一个操作台,在配置规则之后,就可以在不同位置设定不同的氛围文案

  2. 从开发者的角度,调用氛围中心的接口,将商品的信息和要展示的位置等参数输入进去,就会输出需要展示的氛围结果

  3. 从用户的角度,氛围中心使得商品在页面上的不同位置展示了一些不同的营销氛围。

e02cf054d6e357fe466fbc523a2d9091.png

氛围中心的主要工作就是决定在什么位置经过某些规则后展示什么内容。

举个例子,在淘宝App的购物车页面,如果满足访问用户是88VIP用户的规则,就展示与88VIP相关的文案,同时屏蔽掉其他氛围。

  为什么需要氛围中心?

  1. 从用户体验上:导购、交易等全链路需要进行统一的氛围表达和规则管控,以保证营销活动整体氛围的完整性,促进成交转化

  2. 从开发成本上:由氛围中心统一收口,能够减少团队之间的沟通成本,屏蔽各方差异性,提高开发效率。如果没有氛围中心,单个团队推动耗费精力较大:每新增一类营销优惠工具(例如卡券)需要对接搜索、详情、下单等多条链路;每开辟一条新的渠道链路(例如新的搜索页)需要确认是否涵盖原有工具、协调新渠道的透出优先级等等。

4ee71705e74a9f3a9fbc5bffbca4dc3a.png

氛围中心的整体架构

与一般业务系统不同,氛围系统涉及淘宝和其他App的各种位置,QPS非常高。任何的外调、DB/Tair查询都会导致RT急剧上升,所以采取本地调用的方式进行接入。在业务方的应用中,氛围二方包通过中间件Diamond读取并同步配置信息,并为业务方提供本地接口。

Diamond 是在阿里巴巴集团中广泛使用的配置中心,提供持久化管理和动态配置推送服务。

氛围中心的整体架构如下图所示,以氛围二方包为中心,红线左侧为前端界面,红线右侧为后端逻辑;以蓝线为划分,上方为配置端逻辑,下方为实际业务方调用链路。

ba6e17cd02daeee0318538b96583e0ff.png

从图中可以看出,配置端的操作会经由“前端—应用M—应用B”的链路最终影响到Diamond配置,业务方应用通过二方包进行配置同步并更新配置。

此外,氛围中心还通过应用S提供了HSF接口。除了用以集成测试和用例回归外,对于一些QPS不是很高的业务方,HSF调用也是一种远程接入的方式。

HSF(高速服务框架,High-speed Service Framework)是在阿里巴巴集团中广泛使用的分布式RPC服务框架。

  为什么有两套配置端?

如果观察氛围中心的架构图,你会发现其实氛围中心有两套配置端,这其中有一部分是历史的原因,但很大程度上也是必然的结果。

我们回顾一下氛围中心的核心任务:决定在什么位置经过某些规则后展示什么内容

似乎看起来责任很清晰,只需要将位置、规则和内容抽象出来,就生成了一套对应的氛围逻辑。配置端A正是如此:在配置端A里,我们将规则抽象为利益点,位置抽象为渠道,每一个利益点在一个渠道配置有相应的氛围内容,由此实现了规则到位置的 NxN 映射关系。但是在实际中,因为大促活动的存在,我们还有能够随着活动时间快速配置、但透出位置和规则(活动标)却相对固定的需求,即为一种 MxNxN 的一种映射关系,这里的M特指活动时间,由此形成了配置端B。

我们可以看到两套配置端其实侧重点不一样,配置端A主要关注的是规则到位置之间业务映射,而配置端B更关注于如何在大促活动中进行统筹管控。

那么,真的需要同时存在两套配置端吗?

需要,但也不需要。

从现状来看,两套配置端各自有自己特殊的表达,无法单独支撑全部氛围管控任务,需要同时存在:配置端A无法支持大促信息;配置端B的日常氛围管理(即除大促活动外的普通日常氛围)虽然能在一定程度上的等价替代,但是对于位置而言,页面逻辑还是不足以完全表达。

从未来看,两套配置端合并只是时间和成本的问题:第一,两套配置端非常容易引起误解,很多初次接入的应用方会配错位置;第二,两套配置端底层有着相同的输出(二方包、Diamond),改动点只在于前端界面如何从产品角度完整展示位置、规则和内容这三部分的逻辑。

  配置端链路

下面通过简述配置链路来说明氛围配置是如何生产并同步的。

4fb516a2d905b3f190c8d09e1d4e75a8.png

在配置链路中,应用M仅起到了认证和权限控制的作用,不作过多阐述。

在应用B中,氛围中心维护了一个针对TDDL数据库的增删改查模块,而且由于配置端使用人数很少,只有有限个产品和开发使用,不需要考虑高并发场景。氛围中心与一般的后端系统相比特殊之处在于:保存数据库时,会同时保存两份数据。一份是一般的数据表单对象,包含了修改人、更新时间等较为详细的信息,用以向前端输出展示,另一份数据是需要同步到Diamond的配置信息,它以字符串的形式,按照分类保存在数据库中,并通过中间件ScheduleX的定时推送任务周期性同步至Diamond。

TDDL(Taobao Distributed Data Layer):是在阿里巴巴集团中广泛使用的一套分布式数据访问引擎,这里作为数据库使用

ScheduleX:是在阿里巴巴集团中广泛使用的分布式任务调度工具,这里作为定时任务中间件使用

氛围中心选择ScheduleX的推送模式为单机模式,即在应用B的集群中随机选择一台机器执行该任务。同时为了保障手动推送时的数据一致性,氛围中心还使用Redis维护了全局锁,保证了每次操作有且仅有一个线程在运行。

在数据库中,每条Diamond配置是分类型存放的,比如时间、图标、文案等都分别保存在不同的Diamond中,这种保存方式有利于配置读取操作的实现,但是却给保存操作带来了困难。对于普通表单的增删改查,只需要操作DAO层即可,但是如果要同时修改对应的Diamond信息,因为不同场景保存的Diamond各有不同,则需要针对不同业务做定制。氛围中心使用抽象类来实现对基本表单对象的修改;而在不同的继承子类中实现对不同业务的Diamond配置的更新。例如在业务处理器A中,通过定制方法只更新了图标、规则等A业务所需要的配置信息。

3fafa0977ba871f3b582d1a6d33d96c8.png

public abstract class BaseHandler{
  /**
   * 抽象类中add方法示例
   */
  public Result<T> add(Request request, boolean effect) {


    // 使用Maybatis对应的DAO修改普通表单数据
    // ……


    // 走定制逻辑修改Diamond配置
    if (effect) {
      effect(request);
    }
    // ……
  }


 /**
  * 实际继承类单独定制方法
  */
  protected abstract void effect(T t);
}
public class AHandler extends BaseHandler{
 /**
  * 针对业务A的定制
  */
  @Override
  protected void effect(ADTO dto) {
    // 保存与A相关的配置
    // 输入参数已序列化为待保存的对象
    Result<ADTO> result = AManager.saveA2Diamond(dto);


    // ……
  }
}

由上述逻辑可以推测出,在Controller层至少要存在有两个字段才能区分出前端的请求:一个字段指定要操作的处理器,另一个字段要指定进行操作的具体方法(包括增加、删除、修改、生效、推送上线等等)

// 从请求参数中取出识别码获取对应的处理器
Handler handler = HandlerFactory.getHandler(request.getBusinessCode());
handler.check(request);


// 针对不同的操作,调用对应处理器的处理方法
switch (request.getHandleType()) {
  case add:
    return handler.add(request, true);
  case detail:
    return handler.detail(request);
  case list:
    return handler.list(request);
  case copyOnline:
    return handler.copyOnline(request);
  // ... 
  default:
    return Result.buildErrorResult("handle not support");
}

实际上前端的请求也确实包含了这两个字段,一个典型的POST前端请求参数如下

{
    "environment": "pre", // 用以区分线上还是预发
    "businessCode": "业务code", // 指定要使用的Handler
    "handleType": "modefy", // 具体操作方法
    "id": 0, // 主键id
    "content": {
         //JSON对象
    }
}

至此,我们沿着数据库/Diamond—Manager/Handler—Controller—前端的链路了解了氛围中心配置端的整体调用链路。

总结一下配置端的几个特点:

  1. 数据库同时保存两份数据,一份普通表单对象,另一份整理为Diamond配置

  2. 配置通过ScheduleX进行周期性同步,并使用Tair的全局锁保证数据一致性

  3. Handler层使用抽象类封装对普通表单数据的操作,继承子类实现对不同Diamond配置的保存

  4. 前端请求参数中有处理器、处理方法的标识字段

  二方包逻辑

我们再来看一下氛围二方包是如何调用的。

a503da1957d5c8ac200ad5f8b7f18bd4.png

氛围二方包除同步配置之外不进行任何远程调用,应用方如果查询氛围,请求参数除了必备的位置信息(应用名+位置)外,还需要提供商品、优惠等信息。

不同链路依赖的数据源不同,为屏蔽链路之间的差异性,首先需要将输入标准化,构建出统一输入对象。

c55896edb837412bdc27da661be33bb7.png

统一输入对象构建完成后,就是计算有效氛围列表的环节了,首先氛围二方包会从Diamond中获取对应渠道和当前时间的利益点列表,利益点经过一些特制的预处理操作之后,就会循环计算单个氛围是否满足规则条件,最后,通过规则过滤的氛围还会进行互斥等后置处理。

bfc2a17ee991da5dd9649665ec3a5d97.png

验证氛围首先是根据配置中的全局规则、时间等规则进行过滤,再执行用户自定义规则的过滤。

用户自定义规则按照树型结构进行整合,主规则节点定义了条件执行的策略,包含与(And)、或(Or)的关系;叶子节点定义了实际规则,例如{商品标:1234,优惠:abc,取反:true}

b8422a6a6edfbe4a61ff722dc95e7e4e.png

符合条件的氛围会进行素材写入。在素材写入中,除了读取Diamond中配置好的固定内容之外,氛围中心还支持动态文案拼接。动态文案是指在配置端配置诸如满${a}件打${d}折的文案,只需要在请求参数的扩展字段Map中填入相应的内容,例如{a:2,d:75}即可为满足透出逻辑的氛围动态生成,这个功能是通过org.apache.commons.lang3.text.StrSubstitutor#replace(java.lang.Object, java.util.Map<java.lang.String,V>)实现的。

6cc29f0fb6875ab8c972580a793b3ddc.png

f3d2426726ff3135e26896b2a04fc6e2.png

总结与展望

初次接触氛围中心,谈一谈我这三个月来的所见所想。

氛围中心是一个有其自身特性的系统,它经过了不断的迭代和优化,形成了现在的体系。它很好,但是仍有不足:

  1. 整合配置端:同时存在两个配置端确实带来了一些困扰,我们需要通过合理的产品抽象,将位置、规则、时间、活动等信息统一表达,将配置端整合为一个。

  2. Diamond优化:目前氛围中心有四十多条配置,约6MB。一方面超出了Diamond推荐的大小了;另一方面,手工很难去维护和管理如此数量的配置信息。近期的计划是增加过期删除逻辑,先将一部分过期的配置从Diamond中剔除掉,只保留在基本表单中。在开发过程中也在思考是否需要重新组织Diamond的结构,减少Diamond的条数,同时使用分区分片的方式,使得单个应用只读取与自己有关的配置,增强配置的可读性。

  3. 特殊逻辑的代码越来越多:随着开发的不断迭代、修改,层出不穷的预处理器和后置逻辑,还是被不可避免的引入到了代码中。每当个性积累到一定程度,我们就需要对代码进行重构和整理,提取其中的共性加以抽象。这是一个周期性的任务,一个应用只有不断的重构和优化,才能走得更远。

c383375166ef716c666729b5ac9f0c92.jpeg

团队介绍

我们是大淘宝技术平台营销工具团队,是营销业务核心支撑团队,承担成交杠杆的职责,通过创新不断帮助业务挖掘新场景新用户、结合商业化能力打造技术引擎。
平台营销工具不断沉淀商业能力、运营支撑能力,例如品类券、购物津贴、会员卡等实现动态加码、混合出资,极大提升了面向竞争的灵活性;前N、买就返等形成大促标配组合拳,稳定支撑全年50+大促活动。

¤ 拓展阅读 ¤

3DXR技术 | 终端技术 | 音视频技术

服务端技术 | 技术质量 | 数据算法

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/37512.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

V5.1.1,新版发布|软件安全大于一切

主要内容&#xff1a;本次版本除了常规的BUG修复&#xff0c;最重要的是对系统安全全面升级&#xff0c;加强了系统安全检测机制&#xff0c;更新了Thinkphp核心版本&#xff0c;强化了密码等安全。 本次新增了在线用户&#xff0c;支持在线用户下强制下线处理。 本次新增的超级…

java项目-第161期ssm弹幕视频网站系统_ssm毕业设计_计算机毕业设计

java项目-第161期ssm弹幕视频网站系统_ssm毕业设计_计算机毕业设计 【源码请到资源专栏下载】 今天分享的项目是《ssm弹幕视频网站》 该项目分为2个角色&#xff0c;管理员、用户。 用户可以浏览前台视频信息、商品信息&#xff0c;并且可以进行购买。 管理员角色拥有的权限最…

基于jquery 实现导航条高亮显示的两种方法

本篇文章是基于jquery实现导航菜单高亮显示&#xff0c;当点击不同导航菜单实现当前点击的菜单是高亮的&#xff0c;有需要的朋友可以关注下本文 实现原理&#xff1a;当选中当前元素时&#xff0c;给当前元素添加样式&#xff0c;同级元素移除样式。 点击不同的导航菜单实现…

基于SpringBoot的校园志愿者管理系统

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SpringBoot 前端&#xff1a;HTML、Vue 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#…

Java23种设计模式之第三弹-工厂模式

说起工厂&#xff0c;我们第一反应是制作什么东西的吧~。在现实生活中&#xff0c;工厂 &#xff0c; 就是用于生成一些特定事物的厂商。 回到我们此处说的工厂模式上&#xff0c;什么是工厂模式呢 &#xff0c; 顾名思义&#xff0c;就是生成我们的对象的类就会称成为工厂。 …

机器学习模型与backtrader框架整合

原创文章第116篇&#xff0c;专注“个人成长与财富自由、世界运作的逻辑&#xff0c; AI量化投资”。 北京疫情似乎还没有到拐点&#xff0c;但这三天结束后应该会到来。 今天重点说说&#xff0c;机器学习模型整合到我们的回测框架中&#xff0c;并与backtrader连接起来回测…

【Python模块】logging 日志模块

当入门一门语言时&#xff0c;最简单最直观的打印日志信息方式就是使用 print() 函数了&#xff0c;而这毕竟是自己练习和测试才会这样做。当参与项目时一定会去使用日志模块实现日志信息的打印和记录&#xff0c;而 Python 提供了内置的日志模块 logging&#xff0c;有必要深入…

解决每次打开pycharm都特别慢的几个方法

Python编写时&#xff0c;通常都会用vscode和pycharm两个工具&#xff0c;使用过程中&#xff0c;发现每次打开pycharm都特别特别慢&#xff0c;有时候要等十来分钟。相信大家可能都有遇到一样的情况&#xff0c;所以分享我自己的解决方法给大家参考。 1&#xff0c;每次需要关…

[附源码]java毕业设计置地房屋租赁信息系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

嵌入式驱动初级-中断

文章目录前言一、Linux 中断 API 函数二、Linux 中断实现三、中断上半部与下半部四、下半部机制之tasklet ---- 基于软中断五、按键中断下半部机制之tasklet六、下半部机制之workqueue ----- 基于内核线程七、按键中断下半部机制之workqueue前言 记录嵌入式驱动学习笔记 一、Li…

一文带你深入理解【Java基础】· 枚举类

写在前面 Hello大家好&#xff0c; 我是【麟-小白】&#xff0c;一位软件工程专业的学生&#xff0c;喜好计算机知识。希望大家能够一起学习进步呀&#xff01;本人是一名在读大学生&#xff0c;专业水平有限&#xff0c;如发现错误或不足之处&#xff0c;请多多指正&#xff0…

Vision Transformer这两年

作者&#xff5c;Maximilian Schambach OneFlow编译 翻译&#xff5c;胡燕君、杨婷 在NLP领域取得巨大成功后&#xff0c;Transformer架构在计算机视觉方面的作用日渐凸显&#xff0c;成为越来越普遍的CV工具。自2020年10月Vision Transformer模型推出以来&#xff0c;人们开始…

《研究生学术与职业素养讲座》第七讲~第九讲作业答案

第七讲 八千里路云和月—2015年意大利米兰世博会中国馆设计 填空题&#xff08;1分&#xff09;单选题&#xff08;1分&#xff09;判断题&#xff08;1分&#xff09;多选题&#xff08;2分&#xff09;第八讲 从纳米研究看工程创新 填空题&#xff08;1分&#xff09;单…

干货 | 一条语句更新多个表

众所周知&#xff0c;多个服务器命中会减慢应用程序的速度。出于这个原因&#xff0c;开发人员致力于找尋使用最少的语句更新数据的最有效方法。事实证明&#xff0c;SQL UPDATE 语句确实支持使用以下语法设置多个表的字段&#xff1a; UPDATE table1, table2, ...SET column1…

2022-11-14 西安 activiti工作流(01)

语言确实有其局限性&#xff0c;但我相信:一件值得做的事情即使做的不怎么样也是值得的! 概念 1.流程审批以前的实现方式 在没有专门的工作流引擎之前&#xff0c;为了实现流程控制&#xff0c;通常的做法就是采用状态字段的值来跟踪流程的变化情况。通过状态字段的取值来决定…

【数据结构】二叉树优先级队列——堆

文章目录1. 树的概念及结构1.1 树的相关概念1.2 树的表示2. 二叉树的概念及其结构2.1 二叉树的概念2.2 特殊的二叉树2.3 二叉树的性质2.4 二叉树的存储结构3. 堆3.1 堆的概念及结构3.2 堆的实现3.2.1 堆的创建3.2.2 堆的插入3.2.3 堆的向上调整算法3.2.4 堆的删除3.2.5 堆的向下…

javaSE--数据类型(复习)

一、变量和类型 变量 指的是 程序运行时 的 可变的量&#xff0c;相当于开辟一块内存空间来保存一些数据 类型 则是 对 变量的种类 进行了 划分&#xff0c;不同的类型 的 变量 具有不同特性 我们所讨论的"变量"主要 和 我们的"内存"这样的硬件设备密切相关…

value_counts()与count()的简单介绍

文章目录一&#xff0c;value_counts()&#xff08;一&#xff09;用法(二)参数介绍二&#xff0c;count()一&#xff0c;value_counts() &#xff08;一&#xff09;用法 value_counts&#xff08;&#xff09;是针对某一列的数据中存在不同的值进行汇总计算 举例 data[dis…

昨天阅读量900

昨天周五了&#xff0c;阅读量还不错的&#xff0c;超过平均值700的&#xff0c;一看有900多呢

80211 TIM流量指示图 附C语言实现

TIM是什么&#xff1f; TIM&#xff1a;Traffic Indication Map&#xff0c;流量指示图。 在80211协议节能模式中&#xff0c;AP会缓存下行数据&#xff0c;AP就是通过beacon帧中TIM来告知休眠中的STA有数据需要接收。 DTIM&#xff1a;Delivery Traffic Indication Map&#…