基于多渠道比价

2023-11-01

目录

背景

流程梳理

技术预研

关键点代码

后记



背景

产品贱兮兮的跑来问:“星哥,我们既然接入了那么多渠道,那么能不能在客户下单的时候做多渠道比价了?”

我:“这是什么骚操作?”

产品:“就是客户下单的时候,我们可以在已经接入的渠道中进行比价,然后选择最便宜的渠道去下单!”

我非常差异:“这样做,能节省多少成本?”

产品:“说出来你可能不信,平均每单能节约1块钱”

我:“然后了?1天能节约几百块钱?”

产品:“是的!boss要求做的!”

我目瞪口呆!

流程梳理

公司最近接入了一大票的渠道商,这些渠道商针对某一个产品提供了统一的产品编码不同的价格,客户在公司所属平台下单,公司可以自行消化或者走不同的渠道商进行比价,然后找最便宜的渠道商下单,不同渠道商的价格大致一致,但是存在少量差异,并且这种差异是实时的,所以需要在客户下单时进行实时比价,然后下单,大致流程如下:

技术预研

1:客户下单之后需要到第三方渠道商处进行比价,时间不可控,而客户需要知道下单结果(这一点跟其他平台的不同,因为我们这个行业的产品价格属于实时价格,客户下单支付的价格,很可能下一刻就发生了变化,如果价格变高,那么平台就会存在亏本情况),所以可以参考作者的另一篇设计(基于rockermq的异步服务

2:渠道商有十几个,虽然每个渠道商的产品编码一致,但是调用的接口是五花八门,有http、https、webserver,而且每个渠道商的协议,通信加密方式都不一样,需要抽象出统一的接口进行管理,设计模式就派上用场啦!

3:多渠道比价,需要尽量在更多的渠道商处进行比价,java多线程的Callable在配合ExecutorService,即可实现!

4:用户体验,多渠道进行比价的同时,也要考虑用户体验问题,所以比价的时间不能太长,根据作者统计,调用渠道商接口的超时时间设置在3s

5:成本问题,由于价格属于实时价格,那么在选出最优价格的同时,需要在对应渠道商处进行下单,并且只有下单成功,才可以返回客户下单成功

6:业务闭环,下单失败?如果下单的时候该渠道商价格发生变化,需要做出决策如何处理?作者这里针对下单失败,直接就是本平台消化,不再进行比价

关键点代码

针对多渠道商统一接口管理

public abstract class SupplierInterface {
    /**
     * 根据产品信息查询对应产品实时价格
     * @param queryProductPriceReq 产品信息
     * @return QueryProductPriceRsp 查询价格结果
     */
    public abstract QueryProductPriceRsp queryProductPrice(QueryProductPriceReq queryProductPriceReq);

}

@Service
public class SupplierJingDongInterface extends SupplerInterface {
    @Override
    public QueryProductPriceRsp queryProductPrice(QueryProductPriceReq queryProductPriceReq) {
        // 具体渠道商调用接口实现
        return null;
    }
}

@Service
public class SupplierTaoBaoInterface extends SupplerInterface {
    @Override
    public QueryProductPriceRsp queryProductPrice(QueryProductPriceReq queryProductPriceReq) {
        // 具体渠道商调用接口实现
        return null;
    }
}

针对多渠道比价

public class SupplierQueryProductPriceTask implements Callable<QueryProductPriceRsp> {

    SupplierInterface supplierInterface;
    QueryProductPriceReq queryProductPriceReq;

    public void SupplierTask(SupplierInterface supplierInterface,
                             QueryProductPriceReq queryProductPriceReq) {
        this.supplierInterface = supplierInterface;
        this.queryProductPriceReq = queryProductPriceReq;
    }

    @Override
    public QueryProductPriceRsp call() {
        return supplierInterface.queryProductPrice(queryProductPriceReq);
    }

}


public class Test {
    public static void main(String[] args) {
        ExecutorService executor = Executors.newCachedThreadPool();

        QueryProductPriceReq queryProductPriceReq = new QueryProductPriceReq();

        SupplierInterface supplierJingDongInterface = new SupplierJingDongInterface();
        SupplierInterface supplierTaoBaoInterface = new SupplierTaoBaoInterface();

        SupplierQueryProductPriceTask supplierJingDongTask = new SupplierQueryProductPriceTask(supplierJingDongInterface,queryProductPriceReq);
        SupplierQueryProductPriceTask supplierTaoBaoTask = new SupplierQueryProductPriceTask(supplierTaoBaoInterface,queryProductPriceReq);
        
        Future<QueryProductPriceRsp> jingDongTaskResult = executor.submit(supplierJingDongTask);
        Future<QueryProductPriceRsp> taoBaoTaskResult = executor.submit(supplierTaoBaoTask);
        executor.shutdown();

        try {
            Thread.sleep(3000);
        } catch (InterruptedException e1) {
            e1.printStackTrace();
        }

        try {
            System.out.println("京东价格:" + jingDongTaskResult.get());
            System.out.println("淘宝价格:" + taoBaoTaskResult.get());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }
}

以上代码均为标识流程的伪代码,无法进行正常运行,渠道商也没有淘宝和京东只是作者举例而已!

后记

针针对不同的业务场景进行设计,大多数的场景其实已经存在完整的解决方案,攻城狮们其实更多需要考虑的是业务完整性和闭环问题,比如作者这里并没有展示关于退单问题的设计,另外线程池这块需要控制,针对具体业务场景进行设置,不然比价线程开的过多,消耗太大,服务会变得不可用!

 

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

基于多渠道比价 的相关文章

  • Java 类查找工具

    任何经常使用 Java 的人都知道类路径中的多个 jar 会给我们带来多少麻烦 我正在寻找一个可以帮助我的工具 在 jar 中搜索类文件类路径 在 jar 中搜索类文件具体位置 也许要求太多 但请告诉我同一个类是否存在于多个罐子中 不用说它
  • Java中如何合并两个数组?

    它不是连接而是合并两个数组 使它们成为名称值对的数组 firstarray a aa aaa secondarray b bb bbb result a b aa bb aaa bbb 最好的方法是什么 in Java public sta
  • Java selenium - 如何在 TimeoutException 之后正确刷新网页?

    ChromeOptions options new ChromeOptions options addExtensions new File extension 6 2 5 0 crx ZenMate options addExtensio
  • 从SQLite列中获取所有数字字符串并进行总和计算

    我是 Android 和 SQLite 的新手 我在 SQLite 中有一个只有数字的 AMOUNT 列 我可以在 ListView 中显示它 但我无法找到任何我理解的方法来将它们全部添加并显示在 TextView 中 这是数据库助手 im
  • Eclipse 与 IntelliJ 热部署

    我的应用程序配置 Tomcat 8 Spring Spring MVC Hibernate 在 Eclipse 中 我创建了 Tomcat 服务器 并将我的应用程序添加到资源中 JSP JS CSS 和 JAVA 类热部署的工作原理就是这样
  • Mediaplayer 播放几次后停止播放

    我有一个按钮 按下它会播放一个随机声音剪辑 然后播放另一个声音剪辑 然后通过一个媒体播放器播放另一个声音剪辑 但是多次按下该按钮 15 20 次 后 所有音频都会停止 我在播放最后一个音频剪辑后释放媒体播放器 所以我不认为这是原因 有什么指
  • 使用 SSL 和代理设置的 Rest 客户端获取连接超时

    我正在使用带有忽略 ssl 的 Rest 客户端 它工作正常 但在将来我尝试使用客户端证书进行的生产中将无法工作 我有 ca 证书和客户端证书 我用它创建了一个客户端 但我收到错误 Exception in thread main com
  • 使用 POJO 仅更新 JOOQ 记录中已更改的字段

    我想使用 POJO 作为源来更新 JOOQ 记录中已更改的字段 Record from Object http www jooq org javadoc 3 8 x org jooq Record html from java lang O
  • 使用 Microsoft REST API - Java 将 Xbox-Live GamerTag 转换为 XUID

    我有一个 Java 应用程序 它需要能够获取用户输入的 Minecraft Bedrock Edition 玩家标签 并将其转换为给定帐户的 XUID 以便我可以将其存储起来以供稍后列入白名单和参考目的 我一直在浏览 Microsoft R
  • Mockito mockStatic 无法解析符号

    我正在使用 Spring Boot 并在单元测试中 我试图模拟Files delete myFile toPath method 为此 我尝试使用Mockito mockStatic 方法 但是当我尝试使用它时 我的 IDE Intelli
  • 在 Java 中生成 LaTeX 输出 [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 是否有用于从 Java 生成 LaTeX 输出的 Java 库 渲染乳胶 JLatex数学 https
  • 对象映射器 - YAMLFactory - 由于缺少 _createContentReference 方法而出现异常

    我正在使用最新的 2 13 0 版本的 jackson 当我尝试解析 YAML 文件时 出现此异常 java lang NoSuchMethodError com fasterxml jackson core io ContentRefer
  • 如何在 PuTTY 中保存并运行 Java 文件?

    我是 AWS 亚马逊网络服务 的新手 所以这可能是一个基本问题 我在 AWS 上创建了一个 EC2 实例 我有一台 Windows 计算机 因此我使用 PUTTY 来连接 Linux 实例 连接到我的 EC2 实例后 我使用以下命令编写 J
  • 覆盖Java中的属性[重复]

    这个问题在这里已经有答案了 在 Java 中 我最近有几个项目 我使用了这样的设计模式 public abstract class A public abstract int getProperty public class B exten
  • java charAt() 和startsWith() 哪个更快? [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 我的问题是 如果我想检查特定索引中字符串的一个字符 仅检查一个字符 哪种方法非常有效charAt or startsWith 我的意思是 据我所
  • 莫基托。验证方法参数是特定类

    我有一个方法 void putObject
  • 尝试通过 Java 8 中的 JDBC-ODBC 连接到 .accdb 文件时出现 ClassNotFoundException

    我正在 Eclipse EE IDE 中的 Java 项目中工作 我必须在其中查询 accdb文件 问题是当我尝试加载驱动程序然后连接到数据库时 它给了我一个异常错误 My code try String filePath myfilepa
  • 可空日期列合并问题

    我在 Geronimo 应用程序服务器上使用 JPA 和下面的 openjpa 实现 我也在使用MySQL数据库 我在更新具有可为空 Date 属性的对象时遇到问题 当我尝试合并 Date 属性设置为 null 的实体时 不会生成 sql
  • Zookeeper 未启动,nohup 错误

    我已经下载了zookeeper 3 4 5 tar gz 解压后我将conf zoo cfg写为 tickTime 2000 dataDir var zookeeper clientPort 2181 现在我尝试通过 bin zkServe
  • 为什么我们不能在函数式接口中重载抽象方法? (爪哇)

    所以我熟悉java中的函数式接口 以及它们与lambda表达式的使用 一个函数式接口只能包含一个抽象方法 当从 lambda 表达式使用这一孤独方法时 您不需要指定其名称 因为接口中只有一个抽象方法 编译器知道这就是您正在引用的方法 Exa

随机推荐

  • [转]Java 线程池的原理与实现

    最近在学习线程池 内存控制等关于提高程序运行性能方面的编程技术 在网上看到有一哥们写得不错 故和大家一起分享 分享 Java 线程池的原理与实现这几天主要是狂看源程序 在弥补了一些以前知识空白的同时 也学会了不少新的知识 比如 NIO 或者
  • SoftwareSerial库的使用——Arduino软件模拟串口通信

    除HardwareSerial外 Arduino还提供了SoftwareSerial类库 它可以将你的其他数字引脚通过程序模拟成串口通信引脚 通常我们将Arduino UNO上自带的串口称为硬件串口 而使用SoftwareSerial类库模
  • 如何开启计算机cpu虚拟化,电脑开启虚拟化设置的方法 如何开启虚拟化设置

    虚拟化设置的开启其实很简单 因为大家没有接触和操作过 所以一开始会不知所措 虚拟化设置的开启其实很简单 因为大家没有接触和操作过 所以一开始会不知所措 小编在这里为广大玩家深度总计虚拟化开启方法 方便大家在电脑端更流畅的体验手机游戏 虚拟化
  • maven工程依赖的jar包,在本地仓库有,但是pom.xml文件却报错找不到jar包

    例如 Missing artifact com ibm db2 db2jcc license cisuz jar 10 1 但在我本地的仓库中却存在这个jar包 查找了很多的资料发现了两种解决方法 第一种 在eclipse中的window
  • 透彻了解inlining的里里外外——条款30

    Inline函数 多棒的点子 它们看起来像函数 动作像函数 比宏好得多 见条款2 可以调用它们又不需要蒙受函数调用所招致的额外开销 你还能要求更多吗 你实际获得的比想到的还多 因为 免除函数调用成本 只是故事的一部分而已 编译器最优化机制通
  • 2021美赛F题

    2021年 问题E 重新优化食物系统 最近的事件向我们表明 我们的全球粮食系统即使在世界的某些地区也是不稳定的 它通常服务于全世界 这些不稳定的部分原因是我们目前的全球气候变化 庞大的国内和国际食品生产商和经销商体系 这个食物系统 使食物的
  • CUDA矩阵乘法优化

    前言 纸上的来终觉浅 绝知此事要躬行 naive写法 一个矩阵的乘法简单如下 C A B 一般用gemm A B C M N K 来表示 其中的m n k代表的位置如下 默认是k表示消失的纬度 上图的红色虚线围起来的是一个block要负责的
  • MySQL存储引擎InnoDB与Myisam的六大区别

    MySQL有多种存储引擎 每种存储引擎有各自的优缺点 可以择优选择使用 MyISAM InnoDB MERGE MEMORY HEAP BDB BerkeleyDB EXAMPLE FEDERATED ARCHIVE CSV BLACKHO
  • MySQL注入绕安全狗脚本 -- MySQLByPassForSafeDog,以及端口爆破工具 -- PortBrute配置使用

    工具介绍 此Tamper仅仅适用于MySQL数据库 在SQLMap使用过程中添加参数 tamper MySQLByPassForSafeDog 安装与使用 1 安装网站安全狗Apache最新版 2 启用安全狗 不加MySQLByPassFo
  • vue.js组件详解

    一 组件的概念及复用 1 1 为什么要使用组件 组件 component 是vue js最核心的功能 用来实现局部 特定 功能效果的代码集合 html css js image 组件是可复用的 Vue 实例 把一些公共的模块抽取出来 然后写
  • anaconda创建和删除环境

    一 创建环境 在菜单栏中打开Anaconda Prompt 它是一个命令行界面 我们输入下面命令创建环境 这里的py37是我随意起的环境名 大家任意取好记为主 后面的python版本也是自由指定 中间只有一个等号 例如我这里是想创建pyth
  • unicode编码表

    unicode编码表 转载于 近來情轉深的博客 http jlqzs blog 163 com blog static 2125298320070101826277 另附一个汉字转化unicode编码的网页工具 http www bangn
  • 使用别人编译的动态库gdb,路径不匹配

    如果你在调试时需要在动态库中打断点 但动态库的路径是别人的路径 可以使用 GDB 的 set substitute path 命令将动态库路径替换为你本地的路径 具体来说 执行以下步骤 启动 GDB 并加载调试目标 使用 info shar
  • WebFlux ServerHttpRequest RequestBody 读取

    MockServerHttpRequest request MockServerHttpRequest post test body test DecoderHttpMessageReader
  • 安卓开发--不走弯路,5步教你快速实现拍照功能(基于安卓13)

    先展示效果 实现基本逻辑很简单 大致5步为 点击按钮 启动相机 拍照 保存相片 展示相片 但是这里面有一些细节对于初次接触安卓的用户并不友好 比如笔者我 折腾了一阵子才梳理出基本流程 下面我将分步骤说明 按着我的步骤即可快速实现拍照功能 目
  • Update function的问题和解决方案

    DN的过账一般使用的是都是 Function WS DELIVERY UPDATE 其实这是一个经常使用到的函数 注意 这不是一个BAPI 只是一个函数 但是这个函数里面有一个update funtion 所以这个函数并没有返回参数 ret
  • 【RK3399】I3399烧写Debian系统详解

    00 目录 文章目录 00 目录 01 驱动安装 02 镜像文件烧写 03 问题讨论 04 附录 01 驱动安装 1 1 没有安装驱动的时候 显示感叹号 1 2 解压DriverAssitant v5 1 1 zip 1 3 双击Drive
  • Tomcat的下载安装及使用

    目录 一 tomcat简介 二 tomcat的下载 1 进入官网界面 2 选择你使用的版本 3 选择下载 4 将下载好的tomcat安装包进行解压 5 Tomcat的目录结构 6 启动tomcat 7 关闭tomcat 8 解决乱码问题 8
  • 动态绑定与静态绑定的小结(改)

    接下来的一段话是我从一位博客大佬那里copy来的 对象的静态类型 对象在声明时采用的类型 是在编译期确定的 对象的动态类型 目前所指对象的类型 是在运行期决定的 对象的动态类型可以更改 但是静态类型无法更改 静态绑定 绑定的是对象的静态类型
  • 基于多渠道比价

    目录 背景 流程梳理 技术预研 关键点代码 后记 背景 产品贱兮兮的跑来问 星哥 我们既然接入了那么多渠道 那么能不能在客户下单的时候做多渠道比价了 我 这是什么骚操作 产品 就是客户下单的时候 我们可以在已经接入的渠道中进行比价 然后选择