Kitex 在森马电商场景的落地实践

案例介绍

semir


近些年电商行业高速发展,森马电商线上业务激增,面临着高并发、高性能的业务场景需求。森马通过使用 Kitex 接入 Istio,极大地提高了对高并发需求的处理能力。

本文将从四个方面为大家讲解 Kitex 在森马电商场景下的落地实践:

  1. 森马电商订单流转中心——天枢所面临的业务挑战;
  2. 项目的技术选型过程;
  3. 项目上线性能压测对比;
  4. CloudWeGo 团队的技术支持。

森马电商订单流转中心——天枢

业务增长

第一部分给大家介绍订单流转中心——天枢。天枢的主要功能是对接各大电商平台,把订单、商品、退单等信息统一处理后流转到下游系统,是下游系统和平台对接的中间枢纽。 目前森马电商在运营的电商平台几十家,如:天猫、抖店、京东、拼多多等,由于每个平台的接口和对接的方式不统一,我们专门开发了这套系统,去统一对接电商平台,然后把数据处理成统一的格式发到下游系统,如:OMS 和 WMS。 该系统在电商活动,如 6·18,双十一等订单峰值流量下发挥了重要作用。

从 2015 年至 2021 年,森马的双十一业务量增长非常迅速。2015 年双十一的业绩有 3 亿+,而去年的双十一业绩为 20 亿+,2021 年商品交易总额(GMV) 更是突破百亿。 随着业务的增长,对订单系统的性能和稳定性要求越来越高。而且随着系统的规模增长,集群内的 Pod 数量和 Service 不断增加,对系统底层架构有很大的考验。 目前从旧系统迁移的平台有:有赞、抖音、拼多多、快手等,集群内的 Pod 数已经超过 200 个,后续会接入京东、唯品会、天猫等平台后,Pod 数会成倍的增长,更需要一个成熟的系统架构作为支撑。

semir1

面临的问题

随着直播行业的兴起,我们请了一些网红主播和流量明星来直播带货。直播期间,订单量经常会出现几秒内突然爆发的情况,订单推送到系统后,如果系统处理较慢,订单就不能及时流入下游系统, 下游系统的 OMS 不知道已经产生如此大的订单量,就会出现不能同步的情况,即超卖现象。在电商行业,超卖是很严重的问题,如果用户下单后不能及时发货,不仅需要大量的人力去跟客户解释道歉, 也要以优惠券等形式赔偿用户遭受的损失,甚至会接到大量投诉,严重影响我们在电商平台的信誉,电商平台也会对我们进行处罚。我们经历过当 GMV 超过千万时,订单系统延迟超过半个小时的情况,对我们造成了极大的影响。 因此,当遇到如双十一,6·18 大促等活动时,特别是在直播时订单量短时间内暴增的情况下,我们原有的系统架构已经无法支撑,不能及时处理订单数据。这影响了我们发货及库存同步,间接地产生了不同类型的资损。

semir2

技术挑战

我们在技术上面临的挑战主要有以下三个方面:

  • 高并发。在电商业务场景下,不管是面向用户,比如秒杀,还是面向业务,比如订单处理,如果实现不了高并发,系统就很难做大,很难适应业务的增长。
  • 高性能。除了用高并发来实现业务的快速处理外,性能也是一个挑战。例如在当前疫情状态下,各行各业都在降本增效,解决不了性能问题,就会不断地增加服务器资源,大大增加企业成本。
  • 技术保障。我们电商行业的公司,大多资源和精力都在销售端,运营端,技术方面投入相对薄弱。因此在技术选型上需要从可靠、安全、支持等维度去考量。

项目的技术选型

如何选择

在开发语言的选择方面,开发语言没有好坏之分,只有这个语言在相关场景下合适不合适的问题。我们从性能、多线程、编译、效率等方面综合考虑,选择了 Golang。

在微服务框架的选择方面,团队分别用 Google 开源的 gRPC 和字节跳动开源的 CloudWeGo-Kitex 做了技术评估和性能压测。经过专业测试同学的压力测试,最终选择了 CloudWeGo-Kitex 作为我们的微服务框架。

选择 Kitex 的原因主要有两点。第一是 Kitex 背后有强大的技术团队提供及时有效的技术支持。第二是经过压力测试,Kitex 的性能优于其他微服务框架。

关于微服务

使用微服务框架,一定会涉及到选择第三方开源的服务注册中心,那么是选择常用的开源注册中心(Zookeeper、Eureka、Nacos、Consul 和 ETCD), 还是直接选择云原生的服务网格(Istio)?那么我从流量转发、服务注册和服务发现维度介绍一下微服务集群的两种形式。

第一种是 Kubernetes Native,Kubernetes 集群中的每个节点都部署了一个 Kube-proxy 组件,该组件与 Kubernetes API Server 进行通信,观测服务和节点中的变化,进行负载均衡的转发。 这种开源注册中心默认使用 TCP 协议,由于 K8s 负载均衡不支持 RPC 协议(HTTP2),因而需要额外的第三方服务注册中心支持。

第二种是基于 Istio 的服务网格,它并不需要额外的注册中心组件支持。Istio 接管了 K8s 的网络,通过 Sidecar Proxy 的方式将 Kubernetes 中的流量控制从服务层中抽离出来, Istio 基于 Enovy 的 xDS 协议扩展了其控制平面,每个 Pod 中放入原有的 Kube-proxy 路由转发功能。Istio 具备了流量管理、策略控制、可观察性等特点,将“应用程序”与“网络”解耦,因此不需要额外使用第三方注册中心。

那么这两种服务注册与发现的流程是怎样的呢? 下图中左侧就是常用的服务注册中心使用流程。目标服务先把实例注册到服务注册中心,客户端从服务注册中心拿到目标实例的数据,根据负载均衡策略去选择一个服务实例,完成整个请求。 右侧是使用了基于 Istio 的服务网格。大概流程是 Client 访问目标服务的时候,流量先进入 Service 的 Proxy,被 Proxy 拦截,Proxy 会从服务发现(Pilot)拿到服务与服务实例的映射关系, 同时会拿到负载均衡的策略,去选择 Service 一个实例。总体来看,这两种流程大致相同,但实现方式有所差别,各有所长。

semir-5-6

天枢系统基本架构

像抖音、快手、拼多多和有赞等这样成熟的平台在产生订单时,都会将订单以消息推送的形式发送到服务网格中。我们先后通过 Ingress Gateway 网格入口管理程序、VirtualService 把订单转发到网格的不同服务中, 内部再通过不同服务之间进行调用。其中,Kitex 作为微服务的 RPC 框架,服务发现和服务注册均是基于云原生的服务网格 Istio。

semir7

Kitex 接入 Istio

那么 Kitex 接入 Istio 是怎么实现的呢?如下图所示,服务端注册服务之后,在创建客户端的时候,客户端的 Server-host 要写实际集群中的内网地址,例如:server-douyin.default.svc.cluster.local,如上文所说,不用再搭配第三方的服务注册中心。

semir8

由于 Kitex 使用 gRPC 协议,在创建客户端的时候需指定使用 gRPC 协议:

semir9

在 Istio 中怎么部署我们的客户端或者服务端呢?有以下两种方式:

  1. 为命名空间开启自动注入:kubectl label namespace default istio-injection=enabled。注入之后会产生两个重要的容器,第一个是 Istio-proxy,负责流量拦截和流量代理,比如做流量转发;第二个是 Server-douyin,是负责开发的应用容器。 semir10
  2. 把 Go 代码打包的镜像部署到集群中: 例如我们创建了一个 Deployment,名为 Server-douyin,另外作为服务端需要创建相应的 Service。

压测对比

我们将 Kitex 和 gRPC 在以下相同服务器硬件资源和网络环境下进行了压测对比:

  • 压测工具:JMeter;
  • 阿里云 ECS (8 vCPU,16 GiB,5 台);
  • 集群:Kubernetes 1.20.11;
  • 服务网格:Istio v1.10.5.39。

semir-11-12

通过对比发现,在指定时间相同的情况下,Kitex 在单位时间内处理订单数量更多。在指定订单数量的情况下,Kitex 对于处理相同数量的订单所需时间更短,且订单量越大,这种性能差别越明显。总体来看,Kitex 在处理大批订单时优势还是非常突出的。

Kitex 产生性能优势的原因

CloudWeGo 团队来森马做技术支持时讲到对自研网络库 Netpoll 做了一些性能优化,比如:

  • 连接利用率;
  • 调度延迟优化;
  • 优化 I/O 调用;
  • 序列化/反序列化优化;
  • …….

更多资料可以查看 CloudWeGo 官网或参考官网博客

CloudWeGo 团队的技术支持

我们选择 Kitex 之后,CloudWeGo 技术团队给予了足够的技术支持,包括现场支持和远程协助。这也让我们对使用 Kitex 有了信心,不管遇到什么样的技术难题,都会有强大的技术团队来协助解决。

semir13

后续规划

Thrift 和 Protobuf 如何选择

我们在项目初期选择 gRPC 协议 Protobuf 是因为选择了 Istio 服务网格,而选择 Istio 服务网格主要是因为它有多流量转发和服务治理等功能,例如在电商场景下, 不同平台的推送消息都可以通过 VirtualService 转发到不同的服务,相当方便。但是目前每个 Pod 中放入原有的 Kube-proxy 路由转发功能,会增加响应延迟。由于 Sidecar 拦截流量时跳数更多,会消耗更多的资源。

而对于 Thrift,它是 Kitex 默认支持的协议,字节官方对它做了很多性能上的优化,如:使用 SIMD 优化 Thrift 编码,减少函数调用,减少内存操作等,还开源了高性能 Thrift 编解码器 Frugal, Frugal 具有无需生成代码、高性能(在多核场景下,Frugal 的性能可以达到传统编解码方式的 5 倍)和稳定性等特点,进一步提升了性能和开发效率。

因此,我们目前也在考虑在下一次系统版本的架构中改用 Thrift 协议。

服务、合作共赢

我们开发的电商相关产品不仅可以为自己电商品牌所使用,产品成熟后还可以服务于其他相似的电商公司。后续我们也希望能够和 Kitex 官方有更深的技术合作,为社区带来更大价值。