记一次线程递归中thread.sleep造成的惨案

本文记录了一次由于在递归线程中使用Thread.sleep(15*1000)导致的线程池资源耗尽、消息堆积及数据库挂掉的事故。原本的补偿方案设计不当,造成线程无法复用,进而引发数据库阻塞和其他服务故障,最终导致系统崩溃。临时解决方案是注释掉补偿代码,并通过数据库清理。终极解决办法是采用MQ的延时消息,实现异步补偿,避免线程等待和流量高峰。
摘要由CSDN通过智能技术生成

 

最近为了写socket补偿方案.(一旦消息发送失败,就要进行失败消息存储,并且对失败消息按照消息类型的不同补偿方案进行补偿)

补偿方式就是针对如下图不同的消息主键进行不同次数,不同等待时长进行消息补偿.

然后因为没考虑到线程一定要有开有关.在同一个线程中进行递归补偿.并且递归逻辑中增加了Thread.sleep(15*1000)的逻辑.造成线程池资源耗尽.消息堆积.并且因为过程中有查库操作,将数据库也给搞挂了...

 

下面是具体的代码:

package medicalshare.socketweb.helper;

import com.alibaba.dubbo.config.annotation.Reference;
import com.ctrip.framework.apollo.Config;
import com.ctrip.framework.apollo.spring.annotation.ApolloConfig;
import lombok.extern.slf4j.Slf4j;
import medicalshare.socketweb.vo.MessageConfigVo;
import medicalshare.socketweb.websocket.SocketContext;
import medicalshare.support.constant.SocketSendResultConstant;
import medicalshare.user.api.UserService;
import medicalshare.user.dto.UserMessageDto;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.FastDateFormat;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.BinaryMessage;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.*;

/**
 * Created by sino on 2018/12/7.
 */
@Component
@Slf4j
public class AsyncSocketHelper {

    FastDateFormat fdf = FastDateFormat.getInstance("yyyy-MM-dd HH:mm:ss:SSS");

    @Reference
    private UserService userService;


    @ApolloConfig("Message.yml")
    private Config  messageConfig;


    @Async("socketThreadPool")
    protected void sendText(String message, String account, MessageConfigVo messageConfigVo) {
        try {
            WebSocketSession userSession = SocketContext.getUserSession(account);
            if (userSession != null && userSession.isOpen()) {
                log.info("向{}账户发送WebSocket消息成功:{}", account, message);
                int status=0;
                if (messageConfigVo.getTimes()>0){
                    status=updateUserMessage(message, account, messageConfigVo.getMessageType(), SocketSendResultConstant.SENDSUCCESS,"socketSuccessMessage");
                }else{
                    status=addUserMessage(message, account, messageConfigVo.getMessageType(), SocketSendResultConstant.SENDSUCCESS, "socketSuccessMessage");
                }
                if (status!=0){
                    synchronized (userSession) {
                        TextMessage textMessage = new TextMessage(message);
                        userSession.sendMessage(textMessage);
                    }
               }
            }else {
                log.error("向{}账户发送WebSocket消息失败{}!当前账号不在线,无法发送",account,message);
                makeupMessage( message,  account, messageConfigVo);
            }
        } catch (IOException e) {
            log.error("向{}账户发送WebSocket消息异常:{}", account, e);
            makeupMessage( message,  account,messageConfigVo);
        }
    }

    /**
     * 更新失败消息为成功。
     * @param message
     * @param account
     * @param messageType
     */
    public int updateUserMessage(String message, String account, String messageType,String title,String socketFalg) {
        String codeValue = messageConfig.getProperty("Message.Make_UP."+messageType
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值