本文转载自公众号:永辉云创技术

该号由我参与维护,欢迎大家关注支持!!!

案例背景

目前的互联网应用几乎都会使用外部供应商的短信接口来实现一些验证、确认或是推广营销的行为。其中,对于验证、确认类的操作是与业务逻辑直接串联相关的,所以短信发送是否成功非常重要。

由于短信的发送接口是一个外部服务,我们自身无法控制它的可用性,当供应商端内部故障或网络故障等其他外在原因出现推送服务调用延迟过高的时候,我们的内部服务频繁调用对接短信接口的通知服务时,这些调用线程会因为外部资源的延迟高导致资源释放不及时,有导致通知服务资源耗尽的风险。

实现方案

首先,为了让通知服务不因为依赖资源的故障导致自身资源的耗尽,而影响到其他渠道通知服务的正常使用,因此引入Hystrix来保护对短信接口的调用,保护主要分几个方面:

  • 资源隔离:使用线程池来隔离对外部资源的调用,就算外部资源出现问题,在高并发情况下,资源的占用也有上限,不会挤压该服务实例的其他接口

  • 快速失败:通过熔断器在抛出异常的时候进行计数,在固定时间窗里错误情况达到一定百分比,就将熔断器打开。打开之后,在一定时间窗内所有请求将快速失败,而不是等待超时。

  • 自动恢复:在熔断器打开的状态下,将启动一个计时器,这个计时称为休眠时间。当休眠时间耗尽之后,熔断器再次闭合,重新尝试极光推送,如果这次调用成功,将恢复正常服务;如果调用失败,熔断器重新打开,继续休眠。

其次,准备多个短信供应商渠道,在当主要使用的供应商接口故障的时候可以切换到备用供应商来实现短信的发送(用备用供应商接口作为降级逻辑,而不是快速失败,保障短信更高的送达率)。

代码实现

第一步:引入Hystrix的依赖

  1. <dependency>

  2.    <groupId>org.springframework.cloud</groupId>

  3.    <artifactId>spring-cloud-starter-hystrix</artifactId>

  4. </dependency>

第二步:在应用主类中使用@EnableCircuitBreaker或@EnableHystrix注解开启Hystrix的使用,比如:

  1. @EnableCircuitBreaker

  2. @EnableDiscoveryClient

  3. @SpringBootApplication

  4. public class Application {

  5.    public static void main(String[] args) {

  6.        new SpringApplicationBuilder(Application.class).web(true).run(args);

  7.    }

  8. }

第三步:编写短信发送的服务,并使用Hystrix来包装实现资源隔离、服务降级和自动恢复:

  1. public class MessageService {

  2.    @HystrixCommand(

  3.        fallbackMethod = "sendMessageSecondary",

  4.        commandProperties = {

  5.            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1000")

  6.        },

  7.        threadPoolProperties = {

  8.            @HystrixProperty(name = "coreSize", value = "20"),

  9.            @HystrixProperty(name = "maximumSize", value = "50"),

  10.            @HystrixProperty(name = "allowMaximumSizeToDivergeFromCoreSize", value = "true")

  11.        }

  12.    )

  13.    public void sendMessagePrimary(MessagePush messagePush){

  14.        // 调用供应商A的短信接口

  15.    }

  16.    public void sendMessageSecondary(MessagePush messagePush){

  17.        // 调用供应商B的短信接口

  18.    }

  19. }

运行原理

具体的代码配置实现很简单,但是其中蕴含了很多内容逻辑,下图描述了本次整合案例的具体实现原理:

如上图,通过Hystrix对GJPushHandler的 sendMessagePrimary方法做了保护。它的保护逻辑主要分为下面几个部分:

线程隔离

如上图蓝色区域是通知服务中两个发送函数的调用关系。其中, sendMessagePrimary方法由于加上了@HystrixCommand注解,所以该方法的调用已经得到了线程池的资源保护。

换言之,如果该方法调用逻辑阻塞,那么不断增加调用的话,线程池满之后就会出现拒绝服务的异常。因此该方法的调用得到了资源上的保护,不会出现高并发导致无限制的占用资源上升情况。

熔断机制

如上图蓝色区域的左边部分描述了熔断机制的逻辑:

正常情况下:由于熔断开发默认是关闭的,所以 sendMessagePrimary方法的执行逻辑是一个通路,任何调用都会直接进入到该方法的业务逻辑,即对外部资源的调用。

异常情况下:外部资源出现了问题,此时 sendMessagePrimary方法的调用可能会出现超时或者抛出连接异常等各种非HystrixRequestException异常,这个时候当我们判定这些异常属于熔断统计范围内的异常就进行记住。当一定时间窗(10秒)内出现错误请求百分比超过50%的情况下,认为当前外部资源服务不稳定,需要打开熔断器,进入熔断状态。这个时候,由于熔断器处于打开状态,所以 sendMessagePrimary方法的调用将直接降级为对 sendMessageSecondary方法的调用。

该方案可以有效的帮助在异常情况下,通过熔断器来自动的从故障资源的调用切换到备用资源的调用。

自动恢复

如上图底部左边部分描述了自动恢复的逻辑:

在熔断机制的异常情况逻辑中,当熔断器打开的时候,会自动的启动自动恢复休眠窗(一个计时器,默认10秒),在这个休眠期内,所有请求都会快速失败。但是当休眠期到期的时候,此时熔断器会进入半开状态,让下一次请求继续调用外部资源,而不是快速失败。如果这时候调用成功,熔断开关置为关闭状态。反之,熔断开关继续打开状态,再次进入快速失败的状态,并继续进行休眠,等待下一次尝试恢复。

总结展望

上面介绍的机制虽然已经实现了对多个短信供应商接口的自动切换,这样的保障主要是对于接口调用层面,但是实际上短信是否真正送达更为复杂。如果做的更好,需要做更多努力,可以通过外部的送达率收集来控制上面原理图中的熔断开关,以实现更为精准的自动化控制。

热文推荐

阿里云Redis开发规范

你的微服务敢独立交付么?

JDK 1.5 - 1.8 各版本的新特性总结

Spring Boot快速开发利器:Spring Boot CLI

IntelliJ IDEA 2018.1正式发布!还能这么玩?

消息中间件选型分析

其他推荐

Spring Cloud构建微服务架构:分布式配置中心(加密解密)

Spring Boot使用@Async实现异步调用:线程池的优雅关闭

Spring Boot使用@Async实现异步调用:自定义线程池

Spring Boot 2.0正式发布,升还是不升呢?

Spring Boot 2.0 新特性概览

Spring Boot/Cloud干货汇总

长按指纹

一键关注

深入交流、更多福利

扫码加入我的知识星球


点击 “阅读原文” 看看本号其他精彩内容

Hystrix的应用案例:多短信供应商的自动切换与恢复相关推荐

  1. Android 获取短信验证码并自动填充(踩坑小米、荣耀、OPPO、华为)

    Android 获取短信验证码并自动填充(踩坑小米.荣耀.OPPO) 前言 最近弄了个短信自动填充功能,一开始觉得很简单,不就是动态注册个广播接收器去监听短信消息不就可以了吗?结果没这么简单,问题就出 ...

  2. Android获取短信验证码并自动填充的两种方式

    有些项目为了方便客户操作,减去客户输入短信验证码的时间,会要求安卓app能够获取收到的短信验证码并自动填充到输入框.所以,我整理了安卓获取短信验证码并自动填充输入框的两种方法,而且正式在项目中使用并无 ...

  3. atitit 破解 拦截 绕过 网站 手机 短信 验证码 之自动获取手机短信方式 attilax 总结

    atitit.破解  拦截 绕过 网站 手机 短信 验证码 之自动获取手机短信方式 attilax 总结 1. 自动获取手机短信方式的原理 1 2. 调用api 1 3. ----核心代码 2 4.  ...

  4. php短信接口 案例,php短信接口在美容会所中的运用案例

    都说,爱美是女人的天性.随着生活水平的提升,人们对美丽的需求不断增加,各大美容会所像雨后春笋一样不断冒出,竞争更是激烈.想在行业内取得优势,得到更多客户的支持,给新老客户提供温馨的服务,php短信接的 ...

  5. Android 获取短信验证码,自动填充

    1.申请权限 <uses-permission android:name="android.permission.RECEIVE_SMS" /> <uses-pe ...

  6. python读取手机短信信息_python 自动获取手机短信验证码

    需要一个有权限的 APK 在手机实时存储短信到手机内存 /sdcard/smslog.txt 里(外部SD卡也可以知道能通过adb命令访问到): /***** ...... try { long ti ...

  7. python自动读取短信_自动化测试-自动获取手机短信验证码

    最近在做生产环境自动化测试,碰到一个难题就是短信验证码的获取,生产环境短信验证码是真实的,不能采用测试环境将短信验证码写成固定的方法解决,我的思路是:做一个apk小程序,将手机上的短信验证码实时读取出 ...

  8. iphone转android 短信通知,如何将短信从iPhone转移/切换到Android

    作者:Selena Komez5月27,2017上更新 "我得到了新的华为手机,试用Android系统,我决定放弃旧的iPhone 6. 但是,我不知道如何通过简单的步骤将短信从iPhone ...

  9. python邮件定时发送短信_python实现自动定时给女朋友发手机短信,每天一个笑话!...

    加小编QQ群:832339352 即可自动获取大量Python视频教程以及各类PDF! 大四的生活就是这么无聊,我琢磨着也学了这么多东西了,为啥不能用自己的知识来给生活找点乐子呢?我想反正每天都要给T ...

最新文章

  1. Bi-LSTM-CRF for Sequence Labeling
  2. php 获取时间段 今天昨天本周上周本月上月本季度本年去年
  3. python——time模块实现指定时间触发器
  4. vector与list的区别
  5. 多线程实现生产者消费者
  6. ib课程计算机科学教材,IB国际课程包括哪些学科内容?IB国际课程都有哪些教材?...
  7. 怎么设置html编译报错,doctype html编译出错,提示unexpected character D,这是怎么回事呀?...
  8. BZOJ 2288: 【POJ Challenge】生日礼物 优先队列+贪心+链表
  9. 【Spark】快速简介
  10. mysql批量插入跟更新_Mysql批量插入和更新的性能-问答-阿里云开发者社区-阿里云...
  11. HDU3065 AC自动机
  12. poj2594 Treasure Exploration 二分匹配之最小路径覆盖+传递闭包
  13. 深度学习图像分类(二):AlexNet
  14. 切割钢板计算机软件,板材切割优化软件钢板开料套料软件 V1.0 官方版
  15. 架构之美:教你如何分析一个接口?
  16. MapReduce优缺点
  17. BF算法(Brute-Force)算法原理及C++实现
  18. ubuntu snap 安装的nextcloud 忘记管理员密码,重新设置密码。
  19. 【小米手环7】使用 Zeus + 表盘自定义工具 为小米手环7开发和安装小程序
  20. SAP 折旧在13-16调整期

热门文章

  1. linux libffi 简介 高级语言互调库
  2. python 自定义异常类
  3. 使用Nessus漏扫
  4. VMware虚拟机NAT模式的具体配置
  5. Linux大棚版redis入门教程
  6. Android开发--实现对话框(AlertDialog)
  7. 规格上下限和控制上下限计算_涡街流量计选型时对测量上下限的考虑
  8. 算法 有两个相同大小数组均已按升序排列好 编程计算这两个数组的中位数 C
  9. leetcode287. Find the Duplicate Number
  10. linux centos 6.8svn,CentOS6.8 安装配置以SVNAdmin管理SVN代码库