移动网关最佳实践(Android)
移动网关接入
使用新版配置文件接入网关
前置条件
您已经部署了新版控制台,支持了新版配置文件(tmf-android-configurations.json)下载。
接入移动网关
TMF基础库内置了移动网关实例,具体接入流程请参考《接入指南》
如何切换生产环境与测试环境
集成TMF往往会遇到多套环境并存的情况,如生产环境、测试环境。TMF初始化支持设置不同的配置文件来做环境切换,具体做法如下:
从控制台下载不同环境的配置文件,并修改配置文件名,如:tmf-android-configurations-uat.json/tmf-android-configurations-sit.json。
将不同环境配置文件拷贝至assets目录下。
初始化基础库时,根据不同编译变体传入不同的配置文件。
String configAssetName = isUat() ? "tmf-android-configurations-uat.json" : "tmf-android-configurations-sit.json"; TMFBaseConfig config = new TMFBaseConfig.Builder() .configAssetName(configAssetName) .build(); TMFBase.init(CommonApp.get().getApplication(), config);
如何调整内置shark实例参数
使用旧版配置文件接入网关
如果您还没有部署新版控制台,只能下载到旧版配置文件.java, 那么请参考如下流程接入移动网关。
使用配置文件中的信息创建SharkConfigInfo
说明:sharkConfigInfo请参考SharkConfigInfo 。
示例代码如下:
public static SharkConfigInfo getSharkConfigInfo() {
SharkConfigInfo info = new SharkConfigInfo();
info.keyId = TMFConfigurations.TMF_APP_KEY;
info.productId = TMFConfigurations.TMF_PID;
info.customId = TMFConfigurations.TMF_CUSTOM_ID;
info.pubKey = TMFConfigurations.TMF_GW_SKEY;
info.tcpHost = TMFConfigurations.TMF_GW_TCP_HOST;
info.tcpPort = TMFConfigurations.TMF_GW_TCP_PORT;
info.httpUrl = TMFConfigurations.TMF_GW_HTTP_URL;
//支持ipv6,不是必须的,如果不支持ipv6注释掉如下代码即可
info.supportIPv6 = TMFConfigurations.SUPPORT_IPV6;
info.tcpHostIPv6 = TMFConfigurations.TMF_GW_TCP_HOST;
info.tcpPortIPv6 = TMFConfigurations.TMF_GW_TCP_PORT;
info.httpUrlIPv6 = TMFConfigurations.TMF_GW_HTTP_URL;
return info;
}
创建SharkConfig
使用AbsSharkConfig创建SharkConfig,实现getConfig()方法,返回SharkConfigInfo。示例代码如下:
SharkConfig sharkConfig = new AbsSharkConfig() {
@Override
protected SharkConfigInfo getConfig() {
return getSharkConfigInfo();
}
};
创建ISharkOutlet
定义sharkPkg/instanceName
说明:部分业务在一个APP或一个进程内开启两个长连接,分别连到不同的Server地址、分别注册各自的GUID。为了满足此类需求,引入了SharkPkg的概念,通过SharkPkg+instanceName标识一个Shark实例,同一个SharkPkg下多个的Shark实例共享数据,共有一个GUID。
一般情况下您不会有多实例场景存在,因此SharkPkg记instanceName采用如下实现即可:
String sharkPkg = context.getPackageName() + "_TMF"; String instanceName = "TMF";
使用AbsSharkOutlet创建ISharkOutlet,实现onGetVersionName,onGetBuildNo,onGetChannel
注意:buildno是应用更新、热修复等组件判断版本的重要依据,具体规则请参考应用发布。
ISharkOutlet sharkOutlet = new AbsSharkOutlet(sharkPkg, sharkConfig, SharkCommonConst.SERVER_TYPE_RELEASE) { @Override public String onGetVersionName() { return VERSION_NAME; } @Override public int onGetBuildNo() { return 1000000; } @Override public String onGetChannel() { return CHANNEL; } }
创建IServiceFactory
Shark允许您自定义线程池及加密服务,TMF已经实现了默认的线程池及国密加密,您可以直接使用,IServiceFactory默认实现如下:
IServiceFactory serviceFactory = new ServiceFactoryWrapper();
private static class ServiceFactoryWrapper implements IServiceFactory {
g
/**
* 线程池
*/
@Override
public ISharkThreadPool getSharkThreadPool() {
return new SimpleThreadPool();
}
/**
* 安全信道使用的加解密算法
* 非对称加密使用国密SM2,对称加密使用国密SM4ECB
*/
@Override
public ISharkCryptor getSharkCryptor() {
return new ISharkCryptor() {
@Override
public byte[] encrypt ( byte[] data, byte[] key){
return SmCryptor.sm4EncryptECB(data, key);
}
@Override
public byte[] decrypt ( byte[] data, byte[] key){
return SmCryptor.sm4DecryptECB(data, key);
}
@Override
public byte[] asymmetricEncrypt ( byte[] data, byte[] publicKey){
return SmCryptor.sm2Encrypt(data, publicKey);
}
@Override
public byte[] asymmetricDecrypt ( byte[] data, byte[] privateKey){
return SmCryptor.sm2Decrypt(data, privateKey);
}
};
}
}
创建shark实例
// 创建的Shark实例是否包括TCP长连接通道
// 对于一个Server地址,后台推送的依据是GUID,因此每个GUID最多只能与其建一个长连接,
// 如果APP有多个进程使用Shark,则最多只有其中一个进程的Shark实例开启长连接,
// 一般来说一个就已经足够了。如果非要建立多个长连接,则必须使用不同的sharkPkg区分以免数据冲突。
boolean withTcpChannel = true;
// 是否自动开启长连接
// 只有withTcpChannel为true时才有意义。如果不自动开启,可通过Shark.startTcpChannel()手动开启。
boolean autoStartTcpChannel = true;
// 创建一个Shark实例
Shark shark = SharkFactory.builder(context) // 必填
.logEnable(IS_LOG_ENABLE) // 选填,默认为false
.sharkPkg(sharkPkg).instanceName(instanceName) // 必填
.sharkOutlet(sharkOutlet) // 必填
.serviceFactory(serviceFactory) // 必填
.withTcpChannel(withTcpChannel) // 必填
.build();
// 启动Shark
shark.start(autoStartTcpChannel);
在应用进入前台时自动启动TCP长连接通道
进入前台自动启动TCP长连接可以在进入前台时触发自有通道推送,建议您开启。
//监听ActivityLifecycleCallbacks,进入前台后自动开启半长连接
monitorActivity(app, shark);
/**
* 在进入前台界面的时候开启半长连接(如果此时未连接则会触发连接建立),
* 会增加流量消耗,但可以在进入前台界面的时候触发推送,
* 请根据业务需要自行判断是否需要
*/
private static void monitorActivity(Application application, final IShark shark) {
if (application == null || shark == null) {
return;
}
application.registerActivityLifecycleCallbacks(new Application.ActivityLifecycleCallbacks() {
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
}
@Override
public void onActivityStarted(Activity activity) {
Log.i("SharkService", "[shark_tcp_status]onActivityStarted, startTcpChannel, " + activity);
shark.startTcpChannel();
}
@Override
public void onActivityResumed(Activity activity) {
}
@Override
public void onActivityPaused(Activity activity) {
}
@Override
public void onActivityStopped(Activity activity) {
}
@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
}
@Override
public void onActivityDestroyed(Activity activity) {
}
});
}
将Shark实例设置给基础库
初始化基础库时,将创建的shark实例设置给TMFBaseConfig。
TMFBaseConfig config = new TMFBaseConfig.Builder()
.shark(shark) //必须
.build();
TMFBase.init(application, config);
网关接入测试
- 获取guid,如果成功获取guid则表示接入成功。
TMFBase.getShark().getGuidAsyn(new IGuidCallback() { @Override public void onCallback(int retCode, String guid) { if (!TextUtils.isEmpty(guid)) { Log.d("TMFDemo_test", "guid: " + guid + " 获取成功!!!!"); } else { Log.d("TMFDemo_test", "获取GUID失败,guid: " + guid + " retCode: " + retCode); } } });
- 参考发起HTTP API请求 ,完成API请求测试。
TCP/HTTP双通道收发数据
TMF移动网关支持HTTP/TCP双通道收发数据,TCP通道效率更高且支持自有通道数据推送,HTTP通道更稳定可靠。建议您同时开启双通道收发数据。
TCP通道开启
内置Shark实例默认开启了TCP通道,非内置Shark实例开启方法请参见创建shark实例
使用默认标记发送请求
使用默认标记发送请求会优先选择TCP通道,建议您使用默认标记发送请求。
shark.sendHttpEntity(req, SharkCommonConst.DEFAULT, callback, 100000);
TCP通道大小限制
由于TCP通道是串行通道,在设计之初就不建议发送大数据包,否则容易引起请求阻塞,当请求包或者回包大小超过1MB时,需改用HTTP通道发送请求。
关闭TCP通道
在某些特定网络环境下,您的TCP通道无法正常工作,比较常见的原因是您的WAF设备不支持TCP通道。这种情况下建议您关闭TCP通道,只保留HTTP单通道运行。 关闭方法请参考TCP通道开启与关闭。
开启TCP通道IP透传
在某些特定网络环境下,您可能无法通过TCP通道获取到真实的客户端IP,如果您遇到该问题,通常有两种解决办法:
- 通过TOA选项配置实现客户端透传,具体方法请参见 TOA实现客户端真实IP透传
- 通过客户端IP透传功能上报真实客户端IP,具体开启方法请参见开启TCP通道IP透传
开启IPv6
Shark HTTP通道使用的是系统API, 因此双栈支持依赖系统底层API实现,无需做特殊处理。TCP通道双栈实现采用的是赛马机制,v6和v4在一定延迟规则下并发连接,优先连接成功的会被采用。由于双栈模式性能一定下降,所以默认是关闭的。如果需要开启IPv6,请参见开启TCP通道IPv6
切换应用配置数据迁移规则
从基线1.8.0起(shark 3.x以上版本)TMF支持按照环境隔离框架数据,不同应用配置的框架数据会存储在独立的数据目录中互不影响。由于旧版Shark无法自动检测当前运行环境变化情况,需要您根据实际情况来指定数据迁移规则。具体设置方法请参见切换应用配置数据迁移规则
常见错误码
请参见Android常见错误码