从0开始学架构: 3. 微服务网关源码剖析

一、微服务网关层的整体架构思考

先回顾下网关层的功能:

1.请求鉴权

发布商品,登录鉴权。

2. 数据完整性检查

数据定长Header,变长body

3. 协议转换

JSON-> HashMap(string,obj)
如果value不支持json嵌套的话,就string就可以。hashmap(string,string)

4. 路由转发

根据CMD转发到不同业务逻辑层

5. 服务治理

限流,降级,熔断等。

其中最核心的是1和4.
1涉及到session存到哪,
4涉及到如何把众多的HTTP请求路由到逻辑层的RPC接口。新上一个业务(逻辑层),网关不需要的重启的情况下如何发现它。

二、自研网关的各个关键点

2.1 自研网关需求剖析

打造一个高性能的分布式网关(SaaS),实现HTTP请求转发到RPC服务、接口请求鉴权、反作弊(风控、antispam)等相关功能。

要实现如下功能:

  1. 高性能分布式模块(这里模块指的Process)
  2. 鉴权功能
  3. 路由能力
  4. 简单实用的反作弊

落实到技术层面,解决方案如下:

  1. 无状态设计
  2. 过滤器责任链设计(拦截器)
  3. 反作弊设计(拦截器)
    可以理解为责任链的一部分
  4. 路由方案设计

架构参考

整体架构基于Spring boot框架。


image.png
  • 网关本质上是一个websever。

  • 注意上面的Filter责任链模式。 跨域问题
    比如,访问www.baidu.com,调用的js中有www.iqiyi.com。那么到了iqiyi的网关层,它发现主域名是来自于其他网站,就会考虑让不让它访问iqiyi,这就是一个跨域问题。

  • 网关属于高并发模块
    所以要逻辑简单,业务逻辑剥离到logic层

  • 缓存设计、异步线程设计
    反作弊模块,希望有一个黑名单缓存,比如map或set。(因为和外部交互影响性能)。黑名单应该是由数据分析得到的,比如放到redis里。那么我如何在进程内缓存呢?
    这时就要一个异步加载机制,比如每隔5s从redis里读出来覆盖set。(最终一致性),即进程内和进程外通讯。

  • 进程外缓存,配置平台
    进程外缓存就指的redis集群
    配置平台是路由逻辑用的,后面详解。

image.png

上面的图不对,需要换一下

2.2 跨域问题

从一个源(www.baidu.com)加载的文档或脚本(js),不能访问另一个源(www.iqiyi.com)的资源。

image.png

  • Access-Control-Allow-Origin
    栗子:
    比如baidu的网页想嵌入iqiyi的一个url资源,那么它会先去iqiyi的网关层探测我能不能访问你的资源,如果iqiyi允许的话,会在网关层建立一个豁免清单(允许哪些第三方的域名访问)。

  • 跨cookie Access-control-allow-credentials
    cokie是种在url里的,比如种在api1.baidu.com里的,那么api2.baidu.com就不行了。如果设置为允许跨cokie,那么cokie在任何一个二级域名里都可以(*.baidu.com).

  • 允许哪些方法进行跨域访问

2.3 Session设计

image.png

2.3.1 session绑定

本质就是将uid hash到固定的节点。
问题是高可用怎么保证呢? session一般是没必要持久化的。
思路是网关冗余,模仿数据库主从复制。


image.png

但是,网关间的数据复制如何设计呢?(要考虑vip、主从复制等,简单问题复制化了)。所以session绑定在工业界很少用。
所以一般用session绑定

2.3.2 session 复制

image.png

而且是最终一致性的,存在session重写。这种方案也是不合理的。

2.3.3 session共享

image.png

这里的redis是redis cluster。
使用缓存服务Redis,统一存储Session。

优点

  • 网关层无状态
  • 缓存服务本身高可用

缺点

  • 多一次服务调用IO
    思考如果减少IO调用,且网关是无状态化的。很自然的想到session存在客户端。

2.3.4 Session 客户端缓存

image.png

可以存在app的sqlite里
优点:

  • 简单高性能
  • 网关层无状态
    缺点:
  • 依赖客户端Cookie(session)存储
    每次带cookie,消耗一些app端的流量。

这个用的比较多,因为响应延迟低,且高可用。

2.3.5 session 生成算法

image.png

session=AES(uid + TTL + checksum)
用户第一次登录时,网关生成session,然后返回给客户端,之后每次登录时带着这个session。
本地算法,AES解密看TTL是否过期,checksum是否正确。

远程校验,是因为session在很多公司是在业务逻辑层生成的(因为更多的是业务逻辑的判断),而不在网关层生成。TTL过期后要到业务逻辑层去校验,业务逻辑层返回给GW一个新的session,GW返回给APP。这个可能很少概率。

2.3.6 session 拦截器

image.png

拦截器中会生成logid,logid是app请求的唯一标识。

以上主要两部分功能,1 是session校验,2是生成logid。

2.4 网关层反作弊需求

  • 针对恶意流量,从网关层面进行拦截,防止对后端服务造成高并发压力
  • 为了防止误伤,对于黑名单数据定期释放能力


    image.png

分析:

  1. 初期阶段
    数据量小的时候,可以内存中local cache。

  2. 高可用设计
    进程内缓存解决不了高可用

  3. 黑名单
    持久化怎么做

image.png

上面是数据量比较小的时候,那么数据量大的时候怎么做,几十G的话进程内缓存不了。
风控挖掘的时候可以存在redis里,但是为了这种小概率的事读redis会导致耗时增加。
所以可以用布隆过滤器。

思考

  • 数据量大怎么做(布隆过滤器)
    如果每次读redis,为了这小概率事件开销太大
    但是布隆过滤器具体怎么做?后面详解
  • 实时性怎么破?
    如果5s拉一次可能不够实时,如果实时性要求高,可以改成redis有更新然后push的方式。

2.5 自研网关各个击破:之路由

image.png

RPC客户端比如Dubbo,用来和网关后面的业务逻辑层的RPC services通信。

架构设计原则

  1. 初期阶段约定大于配置:
    url什么规范,接口的约定。

  2. 服务端简洁化设计

  • 功能够简单
  • 使用用够方便

负载均衡和服务发现

  • RPC框架实现

熔断设计

Hystrix

协议约定

  • 网关和APP间的数据协议是JSON
  • 网关层调用业务逻辑层入参统一为Map<string,string>
  • 业务逻辑层返回统一的Result对象{code,data,msg}
    code:0, data:xxx, msg: success
    网关层拿到后再转化成json,然后返回给APP。

2.5.1 路由设计

image.png

上图其中Sevrice比如分别对应用户、商品、交易的logic。
其中RPC框架比如是Dubbo的RPC客户端,调用Dubbo的RPC服务端(即后端的logic)。

uri->Service(比如User logic),Method对应User logic中的get user方法。
这块主要做两件事:

  1. 建立url和服务间的映射关系(服务启动初始化,内存里建立映射)
  2. RPC通过反射实现远程调用。(反射生成对应的对象供调用)

25.2 具体实现:

image.png
image.png
image.png

上面讲的其实网关1.0的路由实现,有如下几个问题:

  1. 启动耗时大
    比如有几百个业务逻辑,都去网关建立路由映射关系,那么服务启动初始化的时候就会非常耗时。

  2. 业务升级需要重启,耦合严重,降低开发效率。
    比如新加个服务,需要重新到网关层注册(建立路由映射),那么网关就需要重启进程。

那么2.0就需要解决这两个问题。

2.6 网关2.0

image.png
image.png
  • 路由到通用接口。接口再去路由到具体的服务。
    这样就不需要引入service,不需要重启。基于接口编程。
    proxy每增加一个服务的时候,需要上报CLASS和Method给存储层(Mysql),网关层每隔5s扫描存储层加载到内存里。这样网关层根据CMD对应的Class和Method拿到Service IP,然后调用固定的接口。
image.png
image.png

思考 网关3.0的演进

  • 进一步解耦如何做?
    一定需要mysql作为存储层吗? 可否用注册中心或配置中心来做?
  • 泛化调用的逻辑?

三、开源框架推荐

image.png
image.png
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,012评论 4 359
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,589评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 106,819评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,652评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,954评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,381评论 1 210
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,687评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,404评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,082评论 1 238
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,355评论 2 241
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,880评论 1 255
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,249评论 2 250
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,864评论 3 232
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,007评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,760评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,394评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,281评论 2 259

推荐阅读更多精彩内容