之家云API网关的前世今生
总篇126篇 2022年第1篇
前言
从用户层API网关是服务的统一入口,是各种协议的中转站,是对上游服务的保护,是对API全生命周期的管理,是对东西流量和南北流量的集中治理。从集群层API网关属与分布式集群可横向扩展来处理高并发的请求,从服务层API属于源站的保护伞,路由器,防火墙,对访问服务的流量进行分发,治理和转换。
01
历程
如何从0到1,如何从1到100的构建API网关,下面讲述下整体的历程。
从开源协议和部署方式综合考虑选型为KONG,之家云网关在2019年6月上线,当时APISIX还未开源(2019 年 10 月份在Apache 开源),不与做对比。
02
架构
1)MOCK:不请求源站,从网关层返回http状态码,http 头,http数据。
2)跨域:描述:可在网关开发跨域功能,解决前端到服务端的同源策略,字段:
-
允许的域:Access-Control-Allow-Origin的值(多个以逗号分隔),值可以是字符串或者PCRE的正则表达式。 如果希望允许所有源, 请将 * 作为单个值添加到此配置字段中。 -
请求方法: Access-Control-Allow-Methods的值(以逗号分隔的字符串)。GET, HEAD, PUT, PATCH, POST中的一个或者多个。 -
请求头: Access-Control-Request-Headers 的值(以逗号分隔的字符串)。 例如: Origin, Authorization。 -
响应头: Access-Control-Expose-H eaders的值(以逗号分隔的字符串)。 -
缓存时间: 设置preflight request结果缓存的时间,须为大于零的整数。 -
响 应凭据: 控制Access-Control-Allow-Credentials头,是否以true作为此header的值。 -
预检请求: 是否将OPTIONS代理信息发送给后端源服务器。
03
核心技术
1)BasicAuth:使用用户名和密码,为你的apis接口集增加基本认证。该插件通过header头中的Authorization信息,校验用户有效认证信息。首先,将用户名密码已 username:password 的格式进行base64加密,例如:用户名为devtest密码为devtest,则加密后的字符串为 base64(devtest:devtest) = ZGV2dGVzdDpkZXZ0ZXN0然后,将加密后的账号信息加到HTTP请求头中进行访问,Header头信息为Authorization: Basic ZGV2dGVzdDpkZXZ0ZXN0
2)HMAC:hmac是Hashing for Message Authentication的简写,可以用来保证数据的完整,客户端把内容通过散列/哈希算法算出一个摘要,并把算法和内容以及摘要传送给服务端,服务端按照这个算法也算一遍,和摘要比一下如果一样就认为内容是完整的,如果不一样就认为内容被篡改了。首先,拿到自己的hmac公钥私钥,然后,通过指定算法计算生成签名最后,将签名及当前时间(GMT格式)分别加入到请求头中,发起请求及签名算法,如下面所示 X-Date: Thu, 06 Dec 2018 11:51:06 GMT Authorization:hmac username="test",algorithm="hmac-sha256",headers="X-Date",signature="bwksn8/MV6UMhwWv9vD546sUQVxphopgOqoPHVLWBm4="。
public class Main {
public static void main(String[] arg) throws Exception {
String url = "http://dev.test.com";
String username = "dev_test";
String secret = "dev_test";
String auth = "hmac username=\"{1}\", algorithm=\"hmac-sha256\", headers=\"X-Date\", signature=\"{2}\"";
// 获取当前GMT时间(X-Date)
DateFormat dateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss 'GMT'", Locale.US);
dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
String now = dateFormat.format(Calendar.getInstance().getTime());
System.out.println(now);
// 计算签名字符串
String hash_string="X-Date: " + now;
String signature = Base64.getEncoder().encodeToString(sha256_HMAC(hash_string,secret));
System.out.println(signature);
//组装请求头信息
auth = auth.replace("{1}",username).replace("{2}",signature);
Map<String,String> headers = new HashMap<>();
headers.put("X-Date",now);
headers.put("Authorization",auth);
// or headers.put("Proxy-Authorization",auth);
String ret = sendGet(url,"",headers); //http的GET方式请求
System.out.println(ret);
}
/**
* sha256_HMAC加密
* @param message 消息
* @param secret 秘钥
* @return 加密后字符串
*/
private static byte[] sha256_HMAC(String message, String secret) {
try {
Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
SecretKeySpec secret_key = new SecretKeySpec(secret.getBytes(), "HmacSHA256");
sha256_HMAC.init(secret_key);
return sha256_HMAC.doFinal(message.getBytes());
} catch (Exception e) {
System.out.println("Error HmacSHA256 ===========" + e.getMessage());
}
return new byte[0];
}
-
授权码(authorization-code) -
隐藏式(implicit)
-
密码式(password) -
客户端凭证(client credentials)
04
818实战
背景:之家云需承接公司活动期间百万以上的QPS。
挑战:大并发的情况,如何保证服务的高可用,面对突增流量如何处理,面对恶意流量如何清洗,等等问题。
数据:活动期间大约10W的 QPS,压测需要达到100W。
网关支持:
1.根据单台20000QPS的指标横行扩容机器,如果机器从足的情况建议多加;
2.增加备份节点,随时加入集群处理突发情况和流量转移;
3.访问API接口尽量配置限速功能,避免源站被打崩;
4.数据更新要求实时性不高的增加缓存;
5.24小时备战随时处理问题(为了公司拼了)。
压测:
1.共持续了十轮,包括内网和外网压测,对与网关来说是不通集群(建议内网和外网分开搭建物理隔离);
2.实测最高QPS近100万,在用户访问不高的时候开发压测;
3.遇到的问题:
-
BODY过大导致数据落盘影响访问数据(解决:增大运行BODY 大小,调整到合理数据,不易过大); -
日志采集延迟(解决:分集群采集,集中资源处理流量大的接口); -
突发流量(解决:随时增加备份机器,开启限流,流量分发,缓存等网关功能);
05
后续
杨宏岩
任职于云平台部、云开发团队、云开发工程师
阅读更多
▼ 关注「之家技术」,获取更多技术干货 ▼