java消息失败重发_消息推送异常重发需要注意的点(上篇)

本文总结了在Java中实现消息推送异常重发机制的经验,主要包括基于WebSocket的主动推送。文章详细介绍了WebSocket服务端和客户端的实现,包括连接控制、离线消息处理、在线人数统计等,并提到了使用Redis进行消息处理和异常重试的策略。
摘要由CSDN通过智能技术生成

消息重发中需要注意的问题

由于最近工作中接触了比较多关闭消息推送以及异常重发机制的问题,终于得空总结一下经验

目前接触的消息推送分为两种

主动推送:一般为websocket建立长连接实现,此处网上多有各种实现方式。下面贴出本人结合实际应用场景使用的长连接方式。

websocket服务端代码

import com.google.common.collect.Lists;

import lombok.extern.slf4j.Slf4j;

import org.apache.commons.lang3.StringUtils;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Component;

import redis.clients.jedis.Jedis;

import javax.annotation.PostConstruct;

import javax.websocket.*;

import javax.websocket.server.PathParam;

import javax.websocket.server.ServerEndpoint;

import java.io.IOException;

import java.util.List;

import java.util.concurrent.ConcurrentHashMap;

@ServerEndpoint(value = "/websocket/{id}")

@Component

@Slf4j

public class WebSocket {

// 静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。

private static int onlineCount = 0;

// concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。

private static ConcurrentHashMap webSocketSet = new ConcurrentHashMap<>();

// 保存允许建立连接的id

private static List idList = Lists.newArrayList();

private String id = "";

/**

* 这里使用AutoWired注入的bean会出现无法持续保存而出现null的情况。

* 具体原因暂时没有深究,如果有需要时,可以再init初始化方法中手动将临时的beanTmp类存入static常量中即可正常使用该bean类。

* @Autowired

* private RedisCacheUtil redisTmp;

* private static RedisCacheUtil redis;

*

*/

// 与某个客户端的连接会话,需要通过它来给客户端发送数据

private Session session;

public void closeConn(String appId) {

// 关闭连接

try {

WebSocket socket = webSocketSet.get(appId);

if (null != socket) {

if (socket.session.isOpen()) {

socket.session.close();

}

}

} catch (IOException e) {

System.out.println("IO异常");

e.printStackTrace();

}

idList.remove(appId);

}

/**

* 连接/注册时去重

*/

public void conn(String appId) {

// 去重

if (!idList.contains(appId)) {

idList.add(appId);

}

}

/**

* 获取注册在websocket进行连接的id

*/

public static List getIdList() {

return idList;

}

/**

* 初始化方法

* @author caoting

* @date 2019年2月13日

*/

@PostConstruct

public void init() {

try {

/**

* TODO 这里的设计是在项目启动时从DB或者缓存中获取注册了允许建立连接的id

* 然后将获取到的id存入内存--idList

* // 从数据库获取idList

* List ids = wsIdsServiceTmp.selectList(null);

*/

// TODO 初始化时将刚注入的对象进行静态保存

// redis = redisTmp;

} catch (Exception e) {

// TODO 项目启动错误信息

}

}

/**

* 连接启动时查询是否有滞留的新邮件提醒

* @param id

*

* @author caoting

* @throws IOException

* @date 2019年2月28日

*/

private void selectOfflineMail(String id) throws IOException {

// 查询缓存中是否存在离线邮件消息

Jedis jedis = redis.getConnection();

try {

List mails = jedis.lrange(Constant.MAIL_OFFLINE+id, 0, -1);

if (CommomUtil.isNotEmpty(mails)) {

for (String mailuuid : mails) {

String mail = jedis.get(mailuuid);

if (StringUtils.isNotEmpty(mail))

sendToUser(Constant.MESSAGE_MAIL + mail, id);

Thread.sleep(1000);

}

// 发送完成从缓存中移除

jedis.del(Constant.MAIL_OFFLINE+id);

}

} catch (InterruptedException e) {

// TODO Auto-generated c

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值