APNS推送GolangSDK使用Proxy代理

问题背景

苹果的消息推送是通过请求域名: 实现的,该域名解析结果为美国,这引发了两个问题:

1、接口请求时间长,性能低,而且容易请求超时报错

2、高峰期推送请求错误率升高

方案制定

总体思路:增加一个美国代理服务器,通过代理服务器请求苹果消息推送服务

1、原来流程

APNS推送GolangSDK使用Proxy代理

2、现在流程

APNS推送GolangSDK使用Proxy代理

3、具体方案实施选择

选择一:proxy服务器,部署一个正向代理服务,提供push消息的正向代理,消息通过代理服务器送达苹果服务端

选择二:proxy服务器,独立实现、部署一个标准的apns服务,负责ios消息推送。将需要走美国节点的请求转发到该proxy节点

方案选择

具体情况、具体分析,应思考的点:

问题一、苹果官方提供的SDK中,不支持设置代理服务器。官方SDK不适合更改,对以后系统更新不利

问题二、只有苹果的push服务需要代理,其他例如华为、小米、vivo不应走海外代理

问题三、代理安全性

问题四、代理方案下,有重试逻辑。如何准确定义和判断失败,可能会引起消息重复推送

问题五、实现简单、有效,正向代理方式:只需实现一个实例化对象方法,其他利用原始sdk即可。独立apns服务方式:需要实现一个apns服务,国内、国外均需服务部署,需要增加独立的开发和运营成本,另外还得改造调用服务,实现请求调度,优点服务独立、单一,具备一个单独微服务条件

代理SDK(解决方案前提)

github.com/sideshow/apns2

代理使用

方法一: 修改SDK文件

第一步:设置环境变量

export http_proxy=http://my.proxyserver.com:80 export https_proxy=https://my.proxyserver.com:443

第二步:修改apns2.NewClient方法

func NewClient(certificate tls.Certificate) *Client { tlsConfig := &tls.Config{ Certificates: []tls.Certificate{certificate}, } if len(certificate.Certificate) > 0 { tlsConfig.BuildNameToCertificate() } transport := *http.DefaultTransport.(*http.Transport) transport.TLSClientConfig = tlsConfig err := http2.ConfigureTransport(&transport) if err != nil { panic(err) } return &Client{ HTTPClient: &http.Client{ Transport: &transport, Timeout: HTTPClientTimeout, }, Certificate: certificate, Host:DefaultHost, } }

方法二: 从新定义一个NewClient方法

func NewProxyClient(certificate tls.Certificate) *apns2.Client { proxyUrl, err := url.Parse(":443") if err != nil { return nil } tlsConfig := &tls.Config{ Certificates: []tls.Certificate{certificate}, } if len(certificate.Certificate) > 0 { tlsConfig.BuildNameToCertificate() } transport := &http.Transport{ TLSClientConfig: tlsConfig, ForceAttemptHTTP2: true, Proxy: http.ProxyURL(proxyUrl), } http2.ConfigureTransport(transport) proxyClient := apns2.NewClient(certificate).Production() proxyClient.HTTPClient.Transport = transport return proxyClient }