[Android]APP多域名服务高可用方案

负责公司的基础数据扫描采集.
这部分对于系统的可用性基本是100%
所以做了很多高可用的方案

前置准备

在对APP进行高可用实施之前,我们需要准备:

1.核心域名多个降级[一主多备]

最基础的要求,必须!!!
能够支持云端下发 & 本地动态切换(蓝-绿发布 & 灰度 & UAT)

2.多个CDN

每个域名 都使用不同CDN,避免因CDN节点故障导致服务不可用(出现过因CDN节点异常的生产故障)

3.多个部署网络机房

每个域名 部署在不同地域网络机房(出现过主干线因施工被挖断的生产故障)

===========================================================================
核心思想就是: 同城保活、异地灾备再结合服务检测、异常动态切换

以上都是实际生产故障的血泪经验总结.
那么下面简单说一下几种APP的高可用实施方案.


说明

域名的调用优先级是基于云端下发的配置来了
云端下发的多域名配置会缓存在内存.
每次网络请求,都遵循
多域名[0] --> 多域名[1] --> 多域名[2] …


动态多域名下发

这个是必备的,也没什么好说的,略…


CDN节点异常 & CDN选优

启动一个服务,定时对服务进行 ping,出现异常的,直接切换到其他备用域名,直至主服务恢复
贴一下工具类:

public static PingResult customCMD(String host,String command){
        PingResult result = new PingResult();
        try {
            result.host = host;
            Process process = Runtime.getRuntime().exec(command+host);
            process.waitFor();
            result.success = true;
            InputStreamReader reader = new InputStreamReader(process.getInputStream());
            BufferedReader br = new BufferedReader(reader);
            List<String> echo = new ArrayList<>();
            String line;
            while ((line = br.readLine()) != null) {
                echo.add(line);
            }
            PingResultParser.parsePingContent(result, echo);
        } catch (Exception e) {
            e.printStackTrace();
            result.success = false;
            result.ping_time = -1.0;
        }
        return result;
    }

    public static class PingResult {
        public String host;
        public boolean success;
        public double ping_time;

    }

    private static class PingResultParser {

        static void parse(PingResult result, List<String> echo) {
            //          PING www.a.shifen.com (xxx.xxx.xxx.xx) 56(84) bytes of data.
            //          64 bytes from xxx.xxx.xxx.xx: icmp_seq=1 ttl=52 time=21.5 ms
            //
            //           --- www.a.shifen.com ping statistics ---
            //          1 packets transmitted, 1 received, 0% packet loss, time 0ms
            //          rtt min/avg/max/mdev = 21.585/21.585/21.585/0.000 ms
            if (echo.size() == 6) {
                result.ping_time = getPingTime(echo.get(1));
            }
        }

        static double getPingTime(String line) {
            String[] block = line.split(" ");
            String timeStr = block[6].split("=")[1];
            return ValueUtils.parseDouble(timeStr, 0);
        }

        static void parsePingContent(PingResult result, List<String> echo) {
            for (String line : echo) {
                //ping的内容
                if (line.contains("icmp_seq=") && line.contains("ttl=") && line.contains("time=")) {
                    String[] block = line.split(" ");
                    String timeStr = block[6].split("=")[1];
                    Log.d(TAG, "IP:" + result.host + ",耗时为:" + timeStr + " ms");
                }

                if (line.contains("rtt min/avg/max/mdev")) {
                    String timeResult = line.split("=")[1];
                    String[] split = timeResult.split("/");
                    //取平均时间
                    result.ping_time = Double.parseDouble(split[1]);
                    Log.d(TAG,"域名切换检测==="+result.host+",ping为:"+result.ping_time);
                }
            }
        }
    }

开启服务,定期对每个域名跑一边就行,可以使用这个命令
**ping -c 3 -w 2 **
然后基于结果,动态的对retrofit的BASEURL进行切换即可.


请求异常动态切换域名

自定义拦截器,在碰到请求异常时,动态切换至下一个域名自动重新请求,直至所有域名重试完成
如果只需要简单的重试,通过获取**chain.request()**的url,判断host是否为 多域名,是否支持动态切换,然后动态切换,重试就行.
如果不理解的话,建议看一下okhttp的相关源码对于拦截器的实现.

我在这个基础上,额外新增了自定义注解.
主要是用来对于特定服务,实行额外的自定义重试

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface RetryCount {
    int extraCount();
}

不过需要注意的是,需要retrofit版本在2.5.0 及以上才行

request = chain.request();
//获取重试请求的自定义注解
Invocation tag = request.tag(Invocation.class);
Method method = tag != null ? tag.method() : null;
RetryCount retryCount = method != null ? method.getAnnotation(RetryCount.class) : null;

最小化上云

这种方案是另外一个方向了
大概是这样
在这里插入图片描述
通过动态生效的 功能开关进行控制.
当发现主服务异常时.主动将流量切换至 阿里云 / 华为 等云服务.
先保障用户能够正常使用.先把数据上传上来.
再通过 积压监控 + webhook机器人告警等方式.
去进行消费,解析会主服务.

End

好久没写Android方面的博客了.

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android上,实现多App录音需要使用音频录制的权限和合适的录音API。下面是实现多App录音的一种可能方法: 首先,需要在AndroidManifest.xml文件中为应用程序添加录音权限。在`<manifest>`标签内添加以下代码: ``` <uses-permission android:name="android.permission.RECORD_AUDIO" /> ``` 接下来,在应用程序代码中,可以使用`MediaRecorder`类来进行录音。可以创建一个录音管理类,处理不同App之间的录音调用。以下是一个示例: ```java public class RecorderManager { private MediaRecorder mediaRecorder; public void startRecording(String outputFile) { try { mediaRecorder = new MediaRecorder(); mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4); mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC); mediaRecorder.setOutputFile(outputFile); mediaRecorder.prepare(); mediaRecorder.start(); } catch (IOException e) { e.printStackTrace(); } } public void stopRecording() { if (mediaRecorder != null) { mediaRecorder.stop(); mediaRecorder.release(); mediaRecorder = null; } } } ``` 在需要录音的App中,可以实例化`RecorderManager`类并调用其方法来启动和停止录音。例如: ```java RecorderManager recorderManager = new RecorderManager(); recorderManager.startRecording("output_file.mp3"); // ... recorderManager.stopRecording(); ``` 如果需要多个App同时录音,可以将`RecorderManager`类设计为单例类,并在不同的App中共享这个实例。这样,多个App就可以使用同一个录音管理类来进行录音,实现多App同时录音的功能。 需要注意的是,有些机型的系统可能会限制同时进行多个App的录音操作,所以在实际场景中可能需要测试不同的设备和系统版本来确定是否支持多App录音。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值