HTTP代理
1. 使用场景
问题
前面有提到过http代理这个东西,但很多人不知道这个东西该怎么用,或者说有什么用?以及在什么场景下使用?
移动APP通信场景分析
从使用的链接情况来看,一般可以分为两大类:TCP长链接,HTTP短链接;长链接用于消息推送或IM等场景,HTTP用于业务数据的查询或修改。虽然不是所有的APP都需要IM功能,但大多应用都需要消息推送功能。为了推送消息,APP必须维持一根长链接,但大部分时间除了心跳这根链接上是没多少消息在传输的,特别是非IM类的APP,因为这类应用并没大量的消息要不停的推送,维持长链接只是为了消息的及时到达,这势必造成了很大的资源浪费!
解决方案
针对上述情况MPUSH提供了Http代理方案,目的一是充分利用push通道,而是提高数据传输效率节省电量,节省流量,提供比http更高的安全性。
实现原理
MPushClient 提供了一个叫
sendHttp
的方法,该方法用于把客户端原本要通过HTTP方式发送的请求,全部通过PUSH通道转发,实现整个链路的长链接化;通过这种方式应用大大减少Http短链接频繁的创建,不仅仅节省电量,经过测试证明请求时间比原来至少缩短一倍,而且MPush提供的还有数据压缩功能,对于比较大的数据还能大大节省流量(压缩率4-10倍),更重要的是所有通过代理的数据都是加密后传输的,大大提高了安全性!
2. 使用方式
服务端
修改
mpush.conf
增加mp.http.proxy-enabled=true
启用http代理修改
mpush.conf
增加dns-mapping
配置,示例如下mp.http.dns-mapping={//域名映射外网地址转内部IP "api.jituancaiyun.com":["10.0.10.1:8080", "10.0.10.2:8080"] }
说明:因为
mpush server
要做http代理转发,而客户端传过来的一般是域名比如http://api.jituancaiyun.com/get/userInfo.json
为了不到公网上再绕一圈建议把mpush server 和业务服务(api.jituancaiyun.com)部署到同一个局域网,并增域名api.jituancaiyun.com到提供该服务的集群机器内网ip之间的一个映射,这样mpush server
就可以通过局域网把请求转发到具体到业务服务,效率更高!
客户端
设置
ClientConfig.setEnableHttpProxy(true)
来启用客户端代理。通过
Client.sendHttp(HttpRequest request)
方法来发送请求。AndroidSDK通过
com.mpush.android.MPush#sendHttpProxy(HttpRequest request)
来发送比较合适。
3. 流程分析
3.1. 流程图
3.2. 说明
Client
代表App业务比如查询用户信息的接口MPushApiProxy
是一个工具类用于负责处理当前请求是使用普通的HTTP还是使用MPush长链接通道,这个类在SDK中说不存在的,是我们公司内部的业务,实现起来也很简单,建议Android工程中增加这么一个角色,而不是到处直接去依赖Mpush的代码,方便以后解耦。MPushClient
这个SDK已经提供,用于把Http协议打包成mpush协议。HttpProxyHandler
包括后面的几个组件都是服务端业务组件。用于接收客户端传过来的请求并反解为Http协议,然后通过DNSMapping找到域名对应的局域网IP,再通过内置的HttpClient,把请求转发给业务WEB服务,并把业务服务的返回值(HttpResponse)打包成MPush协议发送到客户端。DNSMapping
负责通过域名解析成局域网IP,并具有负载均衡以及简单的健康检查功能(针对所配置的WEB服务)HttpClient
目前使用的是用Netty
实现的全异步的一个HttpClient
,负责通过http的方式请求业务服务。- Nginx是业务服务,也可以是Tomcat,特别需要建议的是链接超时时间配置长一些。
3.3. 补充
为什么要这样实现?因为这样做对原有的业务系统侵入特别低,如果MPushApiProxy
这个组件设计的好,对于最两边的业务组件/服务(Client,Nginx),对请求方式应该是无感知的,这个角色是无法区分到底请求是通过普通的Http方式发送出去的还是通过长链接代理的方式发送的!!!
另附上通过Http Proxy 实现双向通信交互图