需求来源
现有采集数据平台:主要是通过snmp协议等各种协议从不同的系统中获取数据,并将数据发送到kafka中。
最近在和项目经理聊天的过程中发现现有一个客户数据量不大,数万级别,这样的客户还不少,使用ActiveMQ或者RabbitMQ就可以支撑,但是采集数据平台现在只能对接kafka,所以需要对数据采集平台进行改造,让采集平台可以通过配置的方式就可以达到消息队列之间的切换。
需求分析和设计
对接不同厂商的数据,它们之间都会有这样的共性。
共性1:通过一种方式获取厂商的数据。
共性2:将厂商的数据发送到消息队列中。
共性3:消息队列客户端的连接初始化和获取。
这样我们就能够将以上三点抽象成一个接口,叫做厂商生产者接口,将以上3个共性作为厂商生产者接口中的方法。未来对接任何一个厂商,只需要实现这个接口即可。厂商生产者接口代码设计如下。
/** * @author : zhangqing * @Description: 消息队列生产者策略,ActiveMQ,Kafka,RabbitMq等等 * @date : 2020年06月08日 16:33 */public interface ProducerStrategy { /** * 获取来自不同厂商类型的数据,将数据进行处理,作为生产者数据的来源 */ public void produceData(); /** * 数据发送到队列 * @param data */ public void sendRecordToQueue(String data); /** * 获取消息队列生产者的客户端 * @return */ public T getProducerClient();}
为了满足需求,使用策略模式 + 反射的技术,可以做到根据配置文件中设定的参数,就可以指定当前项目使用哪个消息队列。策略模式设计如下:
UML类图可能会不太严谨
解释一下以上的策略模式:
1、项目为SpringBoot构建,在DynamicSnmpClient中有一个queueType属性,当前属性是获取项目启动的时候指定的消息队列类型。
2、QueueContext为策略模式中的环境类,主要是封装动作或者算法的行为,在这里是封装了发送厂商数据的行为。
3、左图的Abstract抽象类,主要是进一步对消息队列进行抽象,我们将初始化消息队列和发送消息队列的行为,直接在抽象类中实现,因为这两个行为是每个消息队列必须要实现的行为。
4、最下面为具体的实现,最终的实现只有发送数据这个行为,也就是不同系统对接,需要我们自己去实现,消息队列的初始化和发送行为已经被实现,开发人员就可以更加专注于各个厂商对接代码的开发。
反射技术的实现:用反射技术主要就是根据配置文件中的类型去实例化消息队列。
public ProducerStrategy getQueueType(String queueProducerClass) throws Exception{ Class> clazz = Class.forName(queueProducerClass); ProducerStrategy producerStrategy = (ProducerStrategy)clazz.getMethod("getInstance").invoke(null,null); return producerStrategy; }
配置消息队列的类型
通过 抽象出厂商接口 + 策略模式 + 反射技术可以做到以下两点。
1、灵活性:不用修改代码就可以切换消息队列的类型,只需启动项目指定类型即可。
2、扩展性:如果在增加一个消息队列,我们只需要增加对接厂商的代码,不用修改原本的代码,做到设计模式中的开闭原则:对扩展是开放的,对修改是关闭。