背景:在某产品代码,有事件生成的时候会生成一个事件id,产品会拿事件id进行后面的一系列的逻辑处理。
需求:现在有另外一个需求,也要拿到每一次的事件id,然后在另一个类中处理其他的逻辑。由于原来的逻辑处理较多,新需求只能尽量减少对原代码的嵌入。
思路:创建一个类来处理新需求,这个类提供一个方法A()把事件id存到队列中,在原来产品的代码只需要调A()方法把事件id存到队列,然后就可以在新类中进行逻辑处理。
LinkedBlockingDeque简单介绍( 本文只是简单记录一次使用)
- LinkedBlockingDeque是一个由链表结构组成的双向阻塞队列,即可以从队列的两端插入和移除元素。
- 相比于其他阻塞队列,LinkedBlockingDeque多了addFirst、addLast、peekFirst、peekLast等方法
- LinkedBlockingDeque是可选容量的,默认容量大小为Integer.MAX_VALUE。
使用过程
1.先创建一个CommenServiceImpl类,作为处理新需求的类
@Service("GtmcCommenServiceImpl") public class CommenServiceImpl{//省略
}
2.创建LinkedBlockingDeque对象incidentIdList,并新加一个方法来实现往incidentIdList添加事件id
final static BlockingDeque<String> incidentIdList = new LinkedBlockingDeque<>(); private volatile Thread thread = null; //当有事件id添加成功后,起一个线程单独处理新的逻辑 public void SetIncidentIdList(String incidentId) { if (null == incidentId || "".equals(incidentId.trim())) { return; } incidentIdList.offer(incidentId); log.info("事件id入List成功:" + incidentId); if (thread == null) { thread = new Thread(this::setAlarm); thread.start(); } if(!thread.isAlive() || thread.isInterrupted()){ thread = new Thread(this::setAlarm); thread.start(); } }
3.在原来生成事件id的产品代码注入CommenServiceImpl,然后通过SetIncidentIdList方法添加事件id到LinkedBlockingDeque
gtmcCommenService.SetIncidentIdList(incidentId);
4.在新创建的CommenServiceImpl类处理新的需求逻辑
@Slf4j
@Service("CommenServiceImpl")
public class CommenServiceImpl {
protected static ElasticsearchService elasticsearchService;
@org.springframework.beans.factory.annotation.Value("${douc.ex.accountId}")
private String accountId;
@Autowired
private IncidentService incidentService;
@Autowired
private KafkaTemplate<String, String> kafkaTemplate;
@Autowired
protected EsQueryCreator queryCreator;
final static BlockingDeque<String> incidentIdList = new LinkedBlockingDeque<>();
private volatile Thread thread = null;
public GtmcCommenServiceImpl() {
elasticsearchService = ElasticsearchService.getInstance();
}
/**
* 新起一个线程循环处理
*/
void setAlarm() {
while (true) {
try {
List<String> list = new LinkedList<>();
incidentIdList.drainTo(list,20);//一次最多从incidentIdList拿20个出来
for (String evenId : list) {
//省略逻辑处理代码
kafkaTemplate.send(TOPIC, JSONObject.toJSONString(map));
}
} catch (Exception e) {
log.error("监控告警生成和解决,发送事件id和配置项id给kafka发生错误 {}" + (e));
}
}
}
public void SetIncidentIdList(String incidentId) {
if (null == incidentId || "".equals(incidentId.trim())) {
return;
}
incidentIdList.offer(incidentId);
log.info("事件id入List成功:" + incidentId);
if (thread == null) {
thread = new Thread(this::setAlarm);
thread.start();
}
if(!thread.isAlive() || thread.isInterrupted()){
thread = new Thread(this::setAlarm);
thread.start();
}
}