Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1965050
  • 博文数量: 498
  • 博客积分: 2078
  • 博客等级: 大尉
  • 技术积分: 1645
  • 用 户 组: 普通用户
  • 注册时间: 2008-11-18 22:43
个人简介

安大

文章分类

全部博文(498)

文章存档

2017年(1)

2016年(2)

2015年(21)

2014年(90)

2013年(101)

2012年(267)

2011年(16)

分类: 架构设计与优化

2016-02-17 16:02:27

前言

广告业务是属于多读少写的模型,写操作由后台运营人员发起,读操作由用户客户端发起。此文是讨论HTTP读接口的灰度方案,总体层次架构如图1所示。

图1

该系统有以下几个特点:

(1) RPC调用服务化,实现了High Availability与Load Balance策略;

(2) 网关层具有简单过载保护、参数校验、转发请求等作用。

灰度需求

随着业务的不断发展,需求变更,接口迭代越来越频繁,便有了灰度的需求,比如历史接口A,在上线新功能后,希望将线上历史接口A的部分请求转发到新功能模块上,来验证新功能代码是否可靠,也就是说灰度目的如下:
减低全线升级引起的潜在故障危害,采用灰度升级,根据结果反馈接口质量。
在软件设计层面较为抽象,就是:
客户端调用接口和参数不变,需要将满足条件的请求转发到对应的新方法,也就是我们所说的新接口。
最简单粗暴的实现直接在业务代码处理,来个:


If 满足灰度条件

业务代码1

Else

业务代码2


当然这样的代码是让人"忧伤"的,可读性和维护性都差评。

通过图1,我们发现可以在两个软件层动工来满足我们的需求,一是在Nginx层做灰度规则判断,二是在网关层做灰度规则判断。

灰度方案

1. Nginx层做灰度方案


Nginx支持嵌入Lua脚本,这让Nginx插上了飞翔的翅膀。Lua脚本可查询业务数据,然后根据业务灰度逻辑,让请求转向对应upstream,即HTTP 接口。

这个方案存在的问题:

开发/运维工种分离的约束,如果没有修改Nginx配置的系统平台工具,这个工作需要运维人员配合处理上线。 这里不是广告业务采用的灰度方案,就不多阐述。


2.网关层做灰度方案


我司KIEV框架接口支持版本定义,即可指定调用的版本接口,也就说一个接口A可存在多个版本,而调用客户端默认调用版本为0的接口,若指定版本字段,便可调用指定版本的接口。这里主要的问题就是如何设计灰度规则匹配,让整个链路调用如下图:

图2

图2和图1的区别就是上图红色部分,也就是说KIEV调用需要指定版本,而且这个版本字段是从我们业务灰度规则中获取的。比较图2和图1,我们主要做了以下改造:

(1) 网关层加入灰度规则;

(2) 网关层灰度规则等数据支持热加载;

(3) 后端KIEV SEVER接口新增接口等升级,网关无需改动代码;

(4) 防止后端KIEV部分接口hang住,网关层支持接口级别粒度管理。


3. 网关层具体实现方案


(1) 灰度规则设计

a) 比例放量:指定接口版本,根据灰度比例到某个新版本接口,比如V1请求的用户,需要放量20%到V2接口,如果是全量灰度,只需将比例改为100%

b) 指定IMEI:指定IMEI(或IMEI通配)的用户灰度到某个新版本接口 ,比如 IMEI=123456或IMEI=123456*, 需要调用V2接口。

c) 全局规则:广告业务中有这样的一个优先级高的灰度需求,就是比如某些IMEI(或IMEI通配)需要返回特定的数据,而不能走正常业务逻辑处理流程。而且 目前IDC调用接口已有多个版本,不能针对每个版本配置一条规则,所以我们引入了全局规则记录,灰度规则的匹配流程如下:


图3

(2)抽象层网关的RPC处理


灰度规则的设计相对比较简单的,主要满足几种常规的业务。这里会衍生出一个问题,就是广告Web层抽象成网关后(以下描述,统一为网关层)该如何做到尽可 能改动少,即后端KIEV服务有新接口或者改动时,网关层无需升级代码也无需发布,便可支持。 如果网关层不能做到配置自动化的话,那通常我们会遇到这些问题:


a)KIEV服务端修改接口或者新增接口时,网关层(作为KIEV的客户端) 需要依赖KIEV服务端的定义接口代码,重新打包发布;


b)KIEV服务端的改动,网关层也需要跟着改动;


上面的问题显然不是我们想碰到的,想要解决上述问题,做到网关层可根据配置,自动构造RPC请求。这里需要提下RPC框架存在的好处之一:RPC框架让开 发人员调用远程服务就像调用本地方法一样简单便捷,免去数据序列化、网络传输通信等因素考虑。但为了达到图3的目的,显然一个通用的网关层需要做到自行构 造RPC请求,而不依赖KIEV服务端接口定义代码。感觉为了这个目的,生产力又回到了解放前。但细想,也不能如此考虑,如果有更好的办法,欢迎交流。


为此,一个通用的网关层就这样诞生了:


a ) HTTP接口对应RPC接口关系,RPC方法名,RPC参数等都通过配置中心存储(后期数据量考虑DB存储,应用本地缓存)


b)RPC方法参数类型约定不能使用自定义类,原因是为了让网关层不依赖服务端定义代码,否则网关层无法序列化或模拟序列化成本更大)系统最终调用链路如下


当然系统目前还是有很多可以优化的地方:

a)各大接口质量的监控

b)服务治理,目前属于手动方式,需往自动化或半自动化治理发展

c)配置中心数据繁多,不方便管理问题

阅读(1446) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~