http api服务网关
http服务网关系统是一个对http服务进行治理的系统,通过该系统可以对调用方进行身份认证、服务授权许可(许可调用方使用某个http服务)、服务鉴权(是否能调用http服务)、请求流控、失败恢复、调用度量数据统计分析、服务依赖视图等。
整个系统架构如下图,分为三大部分:api网关、网关控制台、度量数据采集分析(这个未在图中体现)。
1.api服务网关
api服务网关是一个java web应用,域名:apigw.xxx.com。api服务网关类似企业应用集成中的ESB,为服务调用提供一个统一的访问点。
服务网关实现可采用的技术和组件:
A)mule、camel、servicemix/JBI等中间件
B)nginx+lua脚本、OpenResty
C)spring integration
考虑到代码的维护性和开发技能,没有使用这些技术。
为了提高性能和并发,采用异步方式,上图中的拦截器(过滤器)、servlet、http client均为异步。
2.网关控制台
网关控制台是一个java web应用,域名apiadmin.xxx.com。提供domain管理、应用管理、服务授权、服务监控、统计和度量数据展示、查看服务全局视图等功能。
服务消费者和服务提供者都要在网关控制台进行应用注册,控制台为每个应用分配应用id(appId唯一)和应用密钥(appSecret)。注册时需要提供的信息:应用名称、应用描述、应用负责人、负责人手机&邮箱。
3.服务注册
http服务可用任意语言实现,如ruby、php、java。服务提供者要向服务网关注册其提供的http服务。
服务注册接口url为http://apigw.xxx.com/registry/services,http方法PUT。
服务提供者启动后,调用该接口将其服务注册到服务注册中心,服务注册请求http body为json字符串,格式如下:
{“appId”:”${appId}”,
“httpServices”: {“ endpoint”:[“http://${ip}:${port}?urlPrefixPattern=/xxx”,…],
” services”:[ {“resourceName”:”${resourceName}”,
“version”:”${version}”
”urls”:[{“name”:”${name}”,”url”:”/xxx/xxx”,”method”:”GET”,
”serverTimeout”:${ms}},…
]
},…
]
}
}
说明:appId为服务提供者的应用id;
endpoint为http服务地址,urlPrefixPattern是可选的,为url前缀模式,对java应用,就是servlet url pattern的前缀匹配模式字符串,urlPrefixPattern以/开头,例如/api。
endpoint示例["http://58.1.1.1:8080","http://59.2.61.34?urlPrefixPattern=/api"]
services是包含的http rest资源服务,每个rest资源都有一个resourceName,在整个api服务网关中唯一。每个资源下面可有多个urlOperation(url+http method的组合,url+http method在resourceName内唯一)的组合,urls中的内容就是描述这些组合,其中的name是功能方法的人性化名称,url以/开头,如果根据url中的path和http method已经可以唯一确定一个urlOperation,url可以没有query string,否则要在url中加入queryString的key来限定该url,key放在[]中,如果有多个key,用,分隔,例如/users?qs=[name],name就是queryString中的key。如果url中有模板参数,需要将模板参数放在{}中,例如/users/{name},可以使用/user/abc或/user/u657来匹配该模板。模板参数缺省是字符串,如果要限定是整数,可以在模板参数后面加入@d,例如/users/{id@d},这样只能使用/user/123之类的url来调用。对java spring mvc,url就是controller @RequestMapping中的value值。Method是http方法名称,可取GET、PUT、POST、DELETE、HEAD。serverTimeout是服务提供者推荐的调用超时时间(不考虑跨机房调用延时),单位是毫秒。
服务注册请求头:
Content-Type: application/json; charset=utf-8
register Time:${utc秒数}
registerToken:${token}
registerTime头是注册时的utc秒数。
registerToken用于身份验证,HMAC-SHA1加密,base64(HMAC-SHA1(http body+ registerTime)),密钥为应用注册时分配的appSecret。
服务注册response
注册成功返回200 status code,body为{"result":"success","gwToken":"xxxxxxxx"}
gwToken用于api服务网关调用服务提供者时的身份认证,服务提供者保存该token。
注册失败返回400 status code, body为{"result":"failed","errormsg":"xxxxxxxx"}
4.服务心跳
服务提供者需要提供一个http url,服务网关会每分钟get一次该url来检测服务提供者的存活和健康状况。如果连续三次都调用超时或失败则将该服务提供者设置为offline。在offline状态,连续两次调用成功,则切换为online状态。
心跳检测也可使用etcd集群来实现。
5.服务消费者的服务调用
服务消费者向api网关发起http请求,调用的url为http://apigw.xxx.com/gwapi/${服务提供的url},例如
http://apigw.xxx.com/gwapi/users/2356。api网关收到请求后进行认证鉴权等处理,再由异步httpclient路由转发到服务提供者,httpclient收到服务提供者的响应后,由异步servlet将响应转发到服务消费者。
调用http头
服务消费者在调用服务时,需要如下http头:
invokeId:每请求调用id,通常是uuid生成,在同一应用实例中唯一。
consumerAppId:服务消费者的appId
resourceName:资源名称,主要是为方便进行消息路由。用请求url和http method(GET/POST/PUT/DELETE)也可进行路由。
accessToken用于服务消费者的身份认证。
accessToken的获取
accessToken的有效期为3小时(可配置),其获取流程如下:
服务网关的对服务请求的路由转发
收到服务消费者的服务请求后,服务网关结合服务的健康状况采用round-robin的策略来转发请求到后端的服务节点。
以一个例子为例来描述服务网关的路由转发。
假设有个rest资源服务名称为user.account,其所在endpoint为[”http://23.34.5.6:8080?urlPrefixPattern=/api”,” http://23.34.5.7:8080?urlPrefixPattern=/api”],该资源有个url:/users/{userId},采用GET方法来调用,功能是获取用户账号信息。
服务消费者应用id为store,它调用该功能的http请求如下:
GET /gwapi/users/2356 HTTP/1.1
Host:apigw.xxx.com
Connection: keep-alive
invokeId:1acd-3acb-bca2-ffcc
consumerAppId:store
resourceName: user.account
accessToken: 4fcb-89d3-cbde-aef7
api服务网关收到该请求后,会对该请求进行认证鉴权,通过后对该调用进行路由,假设路由选取的endpoint为http://23.34.5.6:8080?urlPrefixPattern=/api,则调用后端服务时的url为http://23.34.5.6:8080/api/users/2356.
服务网关调用该服务的http如下:
GET /api/users/2356 HTTP/1.1
Host:23.34.5.6:8080
Connection: keep-alive
invokeId: 1acd-3acb-bca2-ffcc
consumerAppId: store
resourceName: user.account
gwToken: 85a7-99df-bc11-653d
转发请求时去掉了accessToken头,增加了gwToken头,gwToken是服务注册时由服务网关生成的,前面对此有说明。服务提供者在注册时,要保存服务网关返回的gwToken,以便用于验证服务网关转发的请求。
api 网关处理请求失败时的响应
当拦截器验证失败时,网关不会将请求转发到后端的服务提供者,而是直接返回响应。
请求不合法时的响应:400 Bad Request。请求中没有规定的http头(invokeId、consumerAppId、resourceName、gwToken)。
认证鉴权失败时的响应:返回http status code 为401 Unauthorized。具体的原因是consumerAppId未注册、accessToken不存在或失效或非法、resourceName非法、服务操作未授权。
流控未通过时的响应:返回http status code 为503 Service Unavailable(flow control)。
路由失败时返回的响应:返回http status code 为503 Service Unavailable(gw route)。具体原因是没有找到可用的endpoint(例如后端服务全部down)。
请求超时时的响应:504 Gateway Timeout(gw)
6.领域模型
7.失败重试
这里的失败重试是指服务提供者返回http 5xx、或服务提供者处理超时、服务提供者返回io exception异常时的重试。当重试时,网关会重新转发。是否重试可以在控制台中对服务授权时,可以设置对urlOperation是否重试,当进行重试转发时,会增加一个http头retryTimes,其值为重试次数。
8.系统部署
为了保证高可用和负责均衡,网关控制台和api服务网关均为多机部署,前面是负载均衡器LVS+keepalived。
9.可选方案
上面的方案是中心化的http服务治理方案,http服务调用要经过api服务网关转发,另一种是去中心化的方法(先前文章中有介绍),服务消费者直接调用服务提供者,前者对目前的代码改动较少,后者改动较多,但性能和可靠性更高。
服务消费者在调用服务之前,要通过服务发现找到可调用服务的endpoint,并到服务中心进行服务授权,获得服务调用token,在调用请求头中带上该token,服务提供者收到请求后,对该token进行认证鉴权。
已有 0 人发表留言,猛击->> 这里<<-参与讨论
ITeye推荐