Golang在京东列表页实践总结

作者:张洪涛

10余年软件开发和设计经验,曾就职于搜狐、搜狗、前matrixjoy公司联合创始人、甘普科技CTO。

目前线上状态

  • 基于搜索实现;

  • 全量数据,搜索结果不理想;

  • 接口响应时间长,影响了用户体验;

  • 没法针对数据做二次优化;

  • 转化率相对较低;

基于以上原因,需要做出改变,所以就需要对老进行重构,如下

重构版本

  • 非全量数据,线下异步根据数据模型进行进行筛选部分最优数据;

  • 要求时时过滤计算,接口相应时间要快,保证用户体验;

  • 数据进行优化,提高转换率,提搞GMV;

为何选择golang

  • golang语言强大的并发能力;

  • 与C相媲美的性能,新版对cpu计算要求较高;

基于以上两点,所以选择了golang语言作为服务端计算使用的语言。

重构后的架构图

解释下架构图各个模块功能

  1. Nginx+Lua: 用来渲染页面,拿到go计算服务的json数据渲染到页面端,最终呈现给终端用户;

  2. Config Center 是用来协调worker、lua服务以及go计算服务的控制中心;

  3. Score Worker、Data Worker 是一个用来线下异步计算数据的2个worker,从数据平台拿到数据加上各种数据模型计算最优数据,计算完成后会通知 Config Center,同时数据会进入DB,进行持久化;

  4. 深 黄色部分是go计算服务,只要分2个集群,一个线上集群、一个线下集群,异步计算服务根据配置中心选择一个线下集群进行数据计算,计算完成后会通知 Config Center,然后相应的线下集群会进行数据预加载到分片的redis以及go计算服务的各个节点中,然后线下集群准备就绪,可以随时切到线上提供服务;

  5. MQ Worker是一个处理消息的服务,主要包括sku上架、下架、库存变动、以及价格变动等消息;

  6. Msg Receiver 接受到MQ worker的消息后进行消息处理,然后发送的go计算服务的各个节点中;

线上部署的多个机房,避免单机房故障;

数据处理流程如下图所示:

上图是一个完整的数据处理流程,整个流程中最核心的部分是架构图中的Config Center,数据流程中的每一步操作都依赖于配置中心。所以整个架构中配置中心非常重要。

内存计算模型图

简单介绍下计算过程:

  1. 解析页面传过来的参数,整理成相应的结构体;

  2. 格式化的结构体,比如品牌、价格、sku属性、库存、产品标签、排序类型等;

  3. 通过格式化的结构体进行内存中计算,包括过滤、排序等计算操作;

  4. 计算完成后会拿到当前页面需要的产品ids;

  5. 然后通过id列表获取到产品的详细信息,并对产品属性过过滤;

  6. 最终把结构化的json数据返回给lua,进行页面渲染;

内存计算数据结构

如下图所示:

以 上结构是go的一个结构体,包括了页面上所有要进行计算的属性,后续所有的内存中计算过滤、排序都是基于此结构体进行,每个商品对应一个相应的结构体,每 个分类大约有几万个商品,内存中也有对应的结构体。这些结构体是在数据异构完成后,数据预先加载内存,避免在提供服务的时候再去初始化。

开发过程中遇到的问题

遇到2个比较严重的问题:

  • Golang自身序列化性能低下

  • GolangGC困扰

针对第一个序列化、反序列化问题,我们尝试过golang内置的encoding/json、encoding/gob两种方式,但是效果都特别不理想,耗费cpu过多,qps 一直上不去。

后来请教beego作者的谢大同学,给推荐了ffjson,也亲自写了一些测试ffjson的代码,最终ffson以3倍优势完胜golang内置json序列化,所以最后采用了ffjson。

第二个问题,golang GC问题,相信不少同学在开发的过程中也遇到过这个问题,其实我们认真分析,发现GC时候很大部分时间是浪费的Marking阶段,所以我们可以从以下几个点优化我们的代码:

减少内存中对象数量

尽量重复内存申请,采用对象池,避免重复申请、释放内存,可以非常有效的减少GC;

开启GODEBUG=gctrace=1,可以非常清晰的看到内存中对象数量、内存使用情况。以及各个阶段的时间开销;

另外可以使用golang内置的性能监控工具pprof包,可以方便得监控到内存、cpu的是使用情况。

Go 技术栈选择

  1. web 框架,采用Asta的beego(http://beego.me)里边的orm部分写的很赞,建议大家仔细读读里边的源码,对lua部分的API设计都 是采用beego现成的MVC设计,可以方便得定义接口,并在路由中配置即可提供服务;具体github地址:http://github.com /astaxie/beego

  2. json序列化,https://github.com/pquerna/ffjson,里边有详细的使用说明文档;

  3. redis:http://github.com/go-redis/redis 在这之上我们内部又对主从操作封装了一层;

转载自:http://studygolang.com/articles/4744

Golang在京东列表页实践总结的更多相关文章

  1. Atitit.列表页and查询条件的最佳实践(1)------设定搜索条件and提交查询and返回json数据

    Atitit.列表页and查询条件的最佳实践(1)------设置查询条件and提交查询and返回json数据 1. 1. 配置条件字段@Conditional 1 1 2. 2. 配置条件字段显示类 ...

  2. 列表页url参数格式分析【求指教】

    运营对列表页url制定静态化模式,与区区观点相悖.遂请大家指教点解. 动态参数包含6个,分别是: 1认证(有机),2品类(水果),3地区(丰台),4状态(众筹中),5排序(评分),6分页 使用状态非常 ...

  3. 【京东详情页】——原生js爬坑之放大镜

    一.引言 在商城的详情页中,放大镜的功能是很常见的.这里京东详情页就要做一个仿放大镜的效果,预览如下: 二.实现原理 实际上,放大镜的实现是单纯用几个div,鼠标移入其中一个小图div,触发事件显示另 ...

  4. 6- vue django restful framework 打造生鲜超市 -完成商品列表页(下)

    Vue+Django REST framework实战 搭建一个前后端分离的生鲜超市网站 Django rtf 完成 商品列表页下 drf中的request和response drf对于django的 ...

  5. 谈谈yii2-GridView如何实现列表页直接修改数据

    作者:白狼 出处:http://www.manks.top/yii2_gridview_advanced.html 本文版权归作者,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原 ...

  6. espcms列表页ajax无限加载

    类似百度图片的效果,滚动到底部后,点击加载更多,加载出第二页,第三页... 替代了传统的上一页,下一页,第几页,以达到在某些情况下使得用户体验更好. 二次开发方法: 1.先在模板文件中增加ajax文件 ...

  7. dedecms讲解-arc.listview.class.php分析,列表页展示

    ./plus/list.php - 动态展示栏目列表页(也可能是频道封面)arc.listview.class.php 是dedecms的列表页的相关处理类__construct()         ...

  8. 通过angularjs的directive以及service来实现的列表页加载排序分页

    前两篇:(列表页的动态条件搜索,我是如何做列表页的)分别介绍了我们是如何做后端业务系统数据展示类的列表页以及动态搜索的,那么还剩下最重要的一项:数据展示.数据展示一般包含三部分: 数据列头 数据行 分 ...

  9. DEDECMS之三 首页、列表页怎么调用文章内容

    一.首页调用 百度了很多,没有找到实际的解决方法,对于直接读取数据库,这种写法不会采取. 后来,仔细考虑,这部分解决的内容不会很多,所以直接使用了简介的内容 方法一(默认长度55) [field:in ...

随机推荐

  1. mysql的my.sock不存在问题

    因为是初步学习Linux,所以为了对其更加了解,没有使用yum对mysql进行安装,而是使用xftp6的方式上传然后解压安装 1.在安装过程中,好像如果不安装在usr/local目录下会存在不能启动的 ...

  2. 【Linux命令】解压相关命令

    xxx.tar.gz   :   tar xvzf xxx.tar.gz xxx.tar.bz2 :   tar -vxjf   xxx.tar.bz2

  3. 打印 PRINT

    打印 PRINT 字符串和数值类型 可以直接输出. print(1) #out:1 print('a') #out:a 变量 无论什么类型,数值,字符串,列表,字典...都可以直接输出 n = 1 s ...

  4. promise和async/await的用法

    promise和async都是做异步处理的, 使异步转为同步 1.promise 它和Promise诞生的目的都是为了解决“回调地狱”, promise使用方法: <button @click= ...

  5. 《剑指offer》面试题22 栈的压入、弹出序列 Java版

    (输入两个整数序列,第一个序列是一串数字的压入顺序,判断第二个序列是否是该栈数字的弹出顺序.) 我的方法:压入序列是给定的,每一次弹出操作形成一个弹出序列的值,我们从前往后遍历弹出序列,每一次访问弹出 ...

  6. 跟风Manacher算法整理

    这是上上周天机房一位神仙讲的,\(gu\)了这么久才来整理\(w\),神仙讲的基本思路已经全都忘记了,幸好的是神仙写了\(blog\),吹爆原博浅谈\(Manacher\)算法,以及原博神仙\(ych ...

  7. [LeetCode] 84. 柱状图中最大的矩形

    题目链接 : https://leetcode-cn.com/problems/largest-rectangle-in-histogram/ 题目描述: 给定 n 个非负整数,用来表示柱状图中各个柱 ...

  8. 剑指offer-二叉树中和为某一值的路径-python

    题目描述 输入一颗二叉树的跟节点和一个整数,打印出二叉树中结点值的和为输入整数的所有路径.路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径.(注意: 在返回值的list中,数组长度大 ...

  9. 关于微信小程序 modal弹框组件的介绍

    微信小程序 modal: 这里对微信小程序中 modal组件进行详细解析,我想开发微信小程序的小伙伴可以用到,这里小编就记录下modal的知识要点. modal modal类似于javascript中 ...

  10. 自己写的SqlHelper,提示在调用"Fill"前,SelectCommand 属性尚未初始化.错误

    namespace 操作数据{    class SqlHelper    {        public DataSet SqlTODs(string cmdstring)        {     ...