-
Notifications
You must be signed in to change notification settings - Fork 331
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
wangbin3
committed
Aug 6, 2022
1 parent
135d646
commit 2e33884
Showing
1 changed file
with
229 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,229 @@ | ||
|
||
# 前言 | ||
>文本已收录至我的GitHub仓库,欢迎Star:https://github.com/bin392328206/six-finger | ||
> **种一棵树最好的时间是十年前,其次是现在** | ||
## Tips | ||
开源项目推荐系列是,小六六平时不是会逛逛开源平台嘛!然后就想着把一些项目分享给到大家,给大家说说我对这个开源项目的一些看法,当然,在写的过程中,也可以让自己的知识面更广,希望能给大家带来不一样的东西。 | ||
|
||
## 短信网关 | ||
> 今天分享的项目是短信网关,这个项目呢?是某马在B站上放出来的项目,我也称之它为开源项目吧!哈哈 | ||
![image.png](https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/40614856402d427cb578db358f1d529e~tplv-k3u1fbpfcp-watermark.image) | ||
|
||
![image.png](https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/ba10439e6c5f467a897c0ab5b4e21fad~tplv-k3u1fbpfcp-watermark.image) | ||
|
||
### 为啥要用短信网关 | ||
|
||
随着企业业务扩张、应用成倍的增加、短信规模化使用,传统短信平台的接入方式和单一的信息发送功能,已经不能完全满足现代企业管理的需求,所以统一入口、减少对接成本、同时兼顾多种短信业务、简单易行的操作与维护、高稳定、高可靠的移动信息化应用成为短信平台发展趋势。 | ||
|
||
|
||
![image.png](https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/b236f495b5364839b7b34f3fa53d632e~tplv-k3u1fbpfcp-watermark.image) | ||
|
||
- 服务越来越多,每个服务都有可能发送短信,是否每个服务都需要对接一遍? | ||
- 多应用对接短信,如何做到短信发送服务高效、稳定? | ||
- 短信通道出现异常时,如何快速切换通道? | ||
- 切换通道时,如何做到应用服务无感知? | ||
- 如何统计各服务短信发送情况,以便进行后续营销分析? | ||
|
||
本项目(集信达短信平台)的核心在于保证短信高效、准确的送达、简单易操作的对接方式。通过对服务的解耦、通讯方式的升级来提升系统的吞吐量。同时在多通道的加持下,通过智能动态的通道评级、选举、降级、热插拔,增强了系统的健壮性,摆脱对单一通道的依赖。并且提供多种对接方式,满足企业内部的各种需求。 | ||
|
||
### 平台架构 | ||
集信达短信平台的整体架构如下: | ||
|
||
![image.png](https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/35f56f86f595404ebfdfb320f7dfb161~tplv-k3u1fbpfcp-watermark.image) | ||
|
||
主要有以下几个服务 | ||
- pd-sms-api 给业务用 | ||
- pd-sms-manage 后台管理 | ||
- pd-sms-server 真正发送短信 | ||
|
||
|
||
### 业务架构 | ||
|
||
![image.png](https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/e47f51fc2d0f425a9694e790c0bedd0d~tplv-k3u1fbpfcp-watermark.image) | ||
|
||
通过上面的业务架构可以看到,短信接收服务(pd-sms-api)提供3种方式供业务系统调用: | ||
|
||
- HTTP接口 | ||
- TCP | ||
- SDK形式 | ||
|
||
短信接收服务通过资质验证(可开关)、短信内容校验后将短信信息发送到对应中间件中(Redis、MySQL)。 | ||
|
||
短信发送方式分为两种类型: | ||
|
||
- 定时发送短信:将短信内容存储到MySQL数据库中,由短信发送服务通过定时任务获取并发送 | ||
- 普通短信:将短信内容推送到Redis队列中,由短信发送服务异步接收并发送 | ||
|
||
|
||
|
||
|
||
### 项目结构 | ||
|
||
![image.png](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/4da9ecaec1cf474caaa4142df4c87f28~tplv-k3u1fbpfcp-watermark.image) | ||
|
||
集信达短信平台,项目整体工程结构和模块功能如下: | ||
|
||
|
||
```js | ||
|
||
pd-sms-backend # 集信达 短信平台父工程 | ||
├── pd-sms-entity # 短信平台实体 | ||
├── pd-sms-manage # 系统管理服务 | ||
├── pa-sms-api # 短信接收服务,应用系统调用接口、发送短信 | ||
├── pd-sms-server # 短信发送服务,调用短信通道、发送短信 | ||
└── pd-sms-sdk # 短信SDK,应用系统引入、发送短信 | ||
``` | ||
集信达短信服务有三个:后台管理服务,短信接收服务,短信发送服务: | ||
|
||
应用 | 端口 | 说明 | 启动命令 | | ||
| ------------- | ---- | ------ | ----------------------------- | | ||
| pd-sms-manage | 8770 | 后台管理服务 | java -jar pd-sms-manage.jar & | | ||
| pd-sms-api | 8771 | 短信接收服务 | java -jar pd-sms-api.jar & | | ||
| pd-sms-server | 8772 | 短信发送服务 | java -jar pd-sms-server.jar & | | ||
|
||
### 业务方调用处理流程 | ||
**调用方式:** | ||
- 业务统调用短信接收服务提供的接口,由短信接收服务将信息保存到消息缓冲区(Mysql、Redis) | ||
- 调用方式:HTTP、TCP(Netty)、SDK | ||
|
||
**处理流程:** | ||
|
||
短信接收服务接收到应用系统请求后,会进行相关的校验处理,校验通过则将信息保存到消息缓存区,具体处理流程如下: | ||
|
||
![image.png](https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/29f303e398764963b60818d1df3bb3ac~tplv-k3u1fbpfcp-watermark.image) | ||
|
||
### 短信发送服务的发送过程 | ||
|
||
**相关功能:** | ||
- 和具体的短信通道对接(例如:阿里云短信、梦网短信等),发送短信 | ||
- 短信定时发送 | ||
- 短信实时发送 | ||
- 服务注册,保证短信发送服务高可用 | ||
- 通道自动选举、降级 | ||
|
||
|
||
**处理过程:** | ||
|
||
![image.png](https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/93be44ec82324cdb9a6756326aef45ab~tplv-k3u1fbpfcp-watermark.image) | ||
|
||
|
||
|
||
## 项目亮点 | ||
|
||
### 架构的设计 | ||
|
||
架构的设计和耦合性还是很好的,代码的风格也很优雅,代码通俗易懂,我随机截取一个类给大家看看 | ||
|
||
|
||
![image.png](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/ac73c4ef93d848a8a592868318f39746~tplv-k3u1fbpfcp-watermark.image) | ||
|
||
|
||
### 短信发送服务核心类 | ||
- ServerRegister:服务注册器,用于将短信发送服务注册到Redis中,定时服务上报,定时服务检查 | ||
- ConfigServiceImpl:通道配置器,用于查询可用通道(阿里短信、华为短信等),通道选举、降级 | ||
- AbstractSmsService:短信发送器抽象父类,子类需要和具体的短信通道对接来完成发送短信的工作 | ||
- SmsConnectLoader:通道实例加载器,根据通道配置,初始化每个通道的Bean对象 | ||
- SmsFactory:短信发送工厂,获取具体的通道实例Bean对象(例如AliyunSmsService)来发送短信, 如果发送出现异常,触发通道选举和通道降级策略 | ||
- SendTimingSmsImpl:定时短信业务处理器,具体负责定时短信的发送 | ||
- SendSmsJob:短信发送定时任务,用于定时短信的发送,调用SendTimingSmsImpl发送定时短信 | ||
- GeneralSmsListener、HighSmsListener:短信接收器,Redis队列的消费者,监听队列中的消息,如果有消息则调用SmsFactory发送实时短信 | ||
- HighServerReceiver:通道消息监听器,通过Redis的发布订阅模式监听通道相关消息,调用SmsConnectLoader初始化通道和更新通道 | ||
- SubscriberConfig:订阅发布模式的容器配置,创建消息监听容器,并将HighServerReceiver加入容器中 | ||
|
||
|
||
### 服务注册器 | ||
大家知道这个是干嘛的吧?哈哈往下看,保证让你觉得有点东西 | ||
|
||
**其实这块的概念和我们服务的注册于发现其实差不多的,但是作用确是不同,为啥这里我们要服务注册呢?原因如下** | ||
|
||
短信发送服务支持分布式集群部署,可以是多个实例,实例越多,发送短信的能力越强。但是对于通道选举、持久化通道等操作,只能有一个服务实例执行,其他服务实例通过redis的广播机制获得通道变化。 | ||
|
||
如果要实现这一功能,需要将所有短信发送服务实例注册到某个地方,当前实现是将所有服务实例注册到Redis中。并且为了能够监控每个服务实例运行状态,需要每个服务实例定时上报并且定时进行服务检查。 | ||
|
||
**业务逻辑** | ||
|
||
- 服务注册,项目启动时将当前服务实例id注册到redis | ||
- 服务上报,每三分钟报告一次,并传入当前时间戳 | ||
- 服务检查,每十分钟检查一次服务列表,清空超过五分钟没有报告的服务 | ||
|
||
|
||
### 通道实例加载器 | ||
|
||
|
||
通道实例加载器对应的为SmsConnectLoader类。 | ||
|
||
短信发送服务存在多个通道(例如阿里云短信、梦网短信等),这些通道是通过后台管理系统设置的,包括通道的名称、签名、模板、连接方式等信息。当短信发送服务启动时,或者后台管理系统设置通道时,将会初始化短信通道。 | ||
|
||
![image.png](https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/b7e35d7b7c6a46d5aa9c9186ed0328d6~tplv-k3u1fbpfcp-watermark.image) | ||
|
||
通道实例加载器的作用就是根据通道配置,初始化每个通道的Bean对象(例如AliyunSmsService、MengWangSmsService等)。 | ||
|
||
### 真正发送流程 | ||
|
||
``` | ||
/** | ||
* 短信发送工厂 | ||
1. 获取构建好的短信通道 | ||
2. 调用通道方法,发送短信 | ||
3. 如果发送出现异常,触发通道选举和通道降级策略 | ||
4. 当通道选举被触发时:smsConnectLoader.buildNewConnect() | ||
5. 当通道降级被触发时:smsConnectLoader.changeNewConnectMessage() | ||
6. 记录短信发送日志 | ||
*/ | ||
``` | ||
|
||
![image.png](https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/f597377dd25f45c0a2e8bfe6bf14bb98~tplv-k3u1fbpfcp-watermark.image) | ||
|
||
采用do while的模式,直到遍历所有的通道把短信成功发送 | ||
|
||
### 异步通道降级选举 | ||
再真正下发短信的流程中 | ||
|
||
![image.png](https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/ed6aa178bf4d4f2c87dd148d77e7867e~tplv-k3u1fbpfcp-watermark.image) | ||
|
||
在一次真正向第三方发送短信的时候,如果发送失败,就会走进到这个重新排序通道逻辑,判断是否需要重排序 | ||
|
||
在这逻辑中有2个很关键的点 | ||
- 固定阈值 (具体数值) | ||
- 固定因子 (按比例) | ||
|
||
|
||
![image.png](https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/4d49520c51b5464881620b8c8f11037c~tplv-k3u1fbpfcp-watermark.image) | ||
|
||
里面呢?有2个核心逻辑 | ||
- 降级 | ||
- 选举 | ||
|
||
### 异步通道选举流程 | ||
|
||
![image.png](https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/6fe6524996a04260b91c0a3b18239818~tplv-k3u1fbpfcp-watermark.image) | ||
|
||
通道选择,只能再一台通道中选举,所以用分布式锁。 | ||
|
||
**listForNewConnect 选择策略** | ||
|
||
``` | ||
* 通道选举,选举策略: | ||
* 1、剔除掉第一级通道 | ||
* 2、查询最近一小时内通道发送短信数量,按数量排序通道 | ||
* 3、如果最近一小时没有发送短信,按最后发送成功排序 | ||
``` | ||
|
||
具体的逻辑还是有点东西的,哈哈。大家自己去看源码吧 | ||
|
||
|
||
|
||
|
||
## 结束 | ||
我觉得,这个项目的设计,技术,架构都是非常不错的,而且又全是crud,对于个人的帮助还是很不错的,如果有时间大家花点时间去吃透它,对于之后的架构设计,面试等都有很大的帮助,并且这个项目很小,代码量也少,花的时间也不多,我是非常推进的拉。好了,就到这了 我是小六六 三天打鱼,两天晒网。 | ||
|
||
|
||
|
||
## 日常求赞 | ||
> 好了各位,以上就是这篇文章的全部内容了,能看到这里的人呀,都是**真粉**。 | ||
> 创作不易,各位的支持和认可,就是我创作的最大动力,我们下篇文章见 | ||
>微信 搜 "六脉神剑的程序人生" 回复888 有我找的许多的资料送给大家 |