集信达总结

系统设计

1. 在集信达平台为什么要拆分出api服务server服务manager服务三个服务?这三个服务分别对应了什么功能?

答:因为需要采用分布式设计需要拆分成3个服务,采用单体架构需要拓展的服务会包含manager后台管理功能,而manager没有并发和大数据量不需要横向拓展需要单独抽离
api服务和server服务的业务复杂度不同,api服务仅仅对请求的数据做校验,server服务是真正发送http请求到短信服务商的,承载的数据压力不同,需要单独抽离成两个服务

数据库相关

2. 集信达平台有哪些数据库表数据库表,其中通道和签名表,通道和模板表是什么关系?写出至少5张表

1)黑名单表black_list
2)通道表config
3)通道签名中间表config_signature
4)通道模板中间表config_template
5)签名表signature
6)模板表template
7)人工表manual_process
8)接入平台表platform
9)接收日志表receive_log
10)发送日志表receive_log
11)定时发送任务表timing_push

3. 提供通道id,签名id,如何查询出通道和签名对应的通道

	SELECT 
	  c.* 
	FROM
	  config c 
	  LEFT JOIN config_template ct 
		ON c.id = ct.config_id 
	  LEFT JOIN config_signature cs 
		ON c.id = cs.config_id 
	WHERE c.is_active = 1 
	  AND c.is_enable = 1 
	  AND c.is_delete = 1 
	  AND ct.template_id = '模板id' 
	  AND cs.signature_id = '签名id' 
	ORDER BY c.level ASC 
或
使用模板id查询通道模板表,能够查询出该模板id对应的所有的通道id,通过集合保存
	SELECT 
	  * 
	FROM
	  `config_template` 
	WHERE `template_id` = '' 
	
	使用签名id查询通道签名表,能够查询出该签名id对应的所有的通道id,通过集合保存
	SELECT 
	  * 
	FROM
	  `config_signature` 
	WHERE `signature_id` = '签名id'
	
	两个集合取交集,及取出重复的id,并且根据这些id去查询通道表,去除所有已经停用,禁用,删除的通道
	SELECT 
	  * 
	FROM
	  `config` 
	WHERE id IN (
		取交集后集合里的id
	  ) 
	  AND is_active = 1 
	  AND is_enable = 1 
	  AND is_delete = 1 

业务相关

4. api服务最终将数据保存在了哪里?B

A:mysql中 B:redis中 C:rabbitMQ中 D:通过HTTPClient发送出去

5. 简单介绍api服务的业务逻辑?

答:对调用集信达的请求做校验,其中经过了如下校验
1)校验了ak是否存在
2)判断接入平台是否需要权限校验,如果开起了权限校验则通过ak,sk,时间戳加密对比传入的校验值,如果校验值和加密的密文相同证明身份通过,否则失败
3)判断手机号是否为空,是否合法,是否是很名单手机号
4)判断模板是否为空,判断签名是否为空,判断签名模板是否有对应的通道
5)判断模板参数和模板内容是否匹配

6. manager工程为什么最后要往redis里发送消息

答:由于server服务为了提升性能,在服务启动的时候会主动去将mysql中的数据缓存下来,而manager服务修改了数据库里的内容后,server服务缓存中的数据并没有改变
需要通过redis发送一个同步数据的消息到server服务,server服务重新读取数据库里的内容到缓存中,否则会出现缓存中的内容和数据库中的内容不一致的情况

技术

7. 编写的sdk如何集成到别人的系统中去?

由于springboot在启动的时候只会扫描启动类下对应的包,而我们的sdk的包路径不能和集成sdk的服务适配,需要利用springboot的自动装配
在resource目录下建立MATE-INF目录并编写spring.factory目录
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.itheima.sdk.service.impl.SmsSendServiceImpl----此处为sdk需要注入到ioc容器中去的类的全路径

8. 手写单例模式 建议设计成 饿汉式/枚举/holder内部类方式得一半分 懒汉式+DCL+voliate 满分

饿汉式:
@Data
public class SingleCaseType {

private String name;

private Integer age;

//只要类加载就会创建对象并消耗内存
private static final SingleCaseType single = new SingleCaseType();

private SingleCaseType(String name, Integer age) {
	this.name = name;
	this.age = age;
}

private SingleCaseType() {
}

//对外提供获取实例的方法
public static SingleCaseType getInstance() {
	return single;
}

public static void main(String[] args) {
	SingleCaseType instance1 = SingleCaseType.getInstance();
	SingleCaseType instance2 = SingleCaseType.getInstance();
	System.out.println(instance1==instance2);
}

}

懒汉式 dcl + volatile:
public class SingleCaseType {

private String name;

private Integer age;

//只要类加载就会创建对象并消耗内存
private volatile static SingleCaseType single;


private SingleCaseType(String name, Integer age) {
	this.name = name;
	this.age = age;
}

private SingleCaseType() {
	
}

//对外提供获取实例的方法--这里采用DCL确认
public static SingleCaseType getInstance() {
	if(single==null) {
		synchronized (SingleCaseType.class) {
			if(single==null) {
				single = new SingleCaseType();
				return single;
			}else {
				return single;
			}
		}
	}else {
		return single;
	}
}

}

9. filter,interceptor,controllerAdvice,aspect,controller的执行顺序 只考虑拦截方向

Filter:过滤器
Interceptor:拦截器,由spring 管理
aspect:切片 我们自定义的切面 这个为来将自定义注解的时候讲
ControllerAdvice:Controller增强,主要是用于全局的异常拦截和处理,这里的异常可以使自定义异常也可以是JDK里面的异常
Controller:我们的控制层

扫描二维码关注公众号,回复: 13242388 查看本文章

filter->interceptor->controllerAdvice->aspect->controller

10. springAOP中的通知类型

@Before				通知方法会在目标方法调用之前执行
@After				通知方法会在目标方法返回或异常后调用
@AfterReturning		通知方法会在目标方法返回后调用
@AfterThrowing		通知方法会在目标方法抛出异常后调用
@Around				通知方法将目标方法封装起来

11. 项目中为什么要搭建这样的一个短信中台

a)将重复的代码剥离,形成中台的组件,因为如果每个服务都要重复的去发送短信的话,这样的重复代码会非常的多。
b)一旦我们的短信服务商不好用了,我么短信平台能够自动的选举出新的通道,不会让我们的系统服务停止

12. 反射原理

首先讲下反射机制:
反射就是在程序运行状态中,对于任何一个类,都能通过特定的方式方法获取到这个类的属性和方法,并且可以对这些属性、方法进行调用。
说白了,反射就是在程序运行时获取和执行某个类属性或方法的功能。

其次讲一些常用的反射相关的API:
比如获取一个Class对象。Class.forName(完整类名)。通过Class对象获取类的构造方法
使用class对象创建一个对象,class.newInstance等。

最后可以说一下反射的优点和缺点:
优点就是增加灵活性,可以在运行时动态获取对象实例。缺点是反射的效率很低,而且会破坏封装,通过反射可以访问类的私有方法,不安全。

13. 接口和抽象类的区别

实现:抽象类的子类使用 extends 来继承;接口必须使用 implements来实现接口。
构造函数:抽象类可以有构造函数;接口不能有。
main 方法:抽象类可以有 main 方法,并且我们能运行它;接口不能有main 方法。
实现数量:类可以实现很多个接口;但是只能继承一个抽象类。
访问修饰符:接口中的方法默认使用 public 修饰;抽象类中的方法可以是任意访问修饰符
Jdk8以后接口中可以使用静态方法
13)请说明集信达项目中,SmsProperties这个类下,messageErrorNum,configLevelFailNum,configBuildScale这三个参数的含义?以及为啥要有这三个参数?

messageErrorNum:消息最大失败次数–》小于消息最大次数进行热切换
configLevelFailNum:通道最大失败次数 ——》 失败次数大于configLevelFailNum的时候进行真正的通道切换
configBuildScale:通道选举算法启动比例–》 失败次数大于configLevelFailNum*configBuildScale的时候进行通道选举

14. 定时短信的实现逻辑

启动一个定时任务:
1)使用redis的分布式锁,为了防止短信重复发送
2)根据时间等值从time-push这张表中查询未处理(status=0)的数据
3)根据查询的结果,依次调用发短信的接口并更新短信发送状态为已处理((status=1)

15. 项目中使用的策略模式?并给出使用策略模式的理由?

1)在项目启动的时候,我们通过实现CommandLineRunner接口初始化每个通道对应的策略类,并且每个策略类都实现共同的抽象类
2)在执行具体发短信的时候,我们通过多态的思想,使用共同的抽象类接收,然后调用对应的方法。

理由:
1)策略模式符合开闭原则,对修改关闭,对扩展开放。
2)避免使用多重条件转移语句,如if…else…语句、switch 语句

猜你喜欢

转载自blog.csdn.net/LiGuanLink/article/details/121137257