流量控制闸门——LimitLatch套接字连接数限制器

简介: Tomcat作为web服务器,对于每个客户端的请求将给予处理响应,但对于一台机器而言,访问请求的总流量有高峰期且服务器有物理极限,为了保证web服务器不被冲垮我们需要采取一些措施进行保护预防,需要稍微说明的此处的流量更多的是指套接字的连接数,通过控制套接字连接个数来控制流量。
Tomcat作为web服务器,对于每个客户端的请求将给予处理响应,但对于一台机器而言,访问请求的总流量有高峰期且服务器有物理极限,为了保证web服务器不被冲垮我们需要采取一些措施进行保护预防,需要稍微说明的此处的流量更多的是指套接字的连接数,通过控制套接字连接个数来控制流量。其中一种有效的方法就是采取流量控制,它就像在流量的入口增加了一道闸门,闸门的大小决定了流量的大小,一旦达到最大流量将关闭闸门停止接收直到有空闲通道。
 
创建一个流量控制器没思路?还是考虑下并发框架AQS吧,通过控制同步器的状态即可实现,如果忘了AQS框架相关知识请移步到前面多线程章节,具体思路是先初始化状态值,然后每到来一个socket就将状态加1,每关闭一个socket将状态减1,如此一来一旦状态值小于0则由AQS机制将停止对socket的接收,直到某个socket处理完释放。我们把思路拆成两部分,一是创建一个支持计数的控制器,另一个是将此控制器嵌入处理流程中。
控制器,整个过程是根据AQS推荐的自定义同步器的做法进行,但并没有使用AQS自带的状态变量,而是另外引入一个AtomicLong类型的count变量用于计数,其本质是一样的,不必过于纠结。控制器主要通过countUpOrAwait和countDown两个方法实现控制效果。
public class LimitLatch {
    private class Sync extends AbstractQueuedSynchronizer {
        public Sync() {}


        @Override
        protected int tryAcquireShared(int ignored) {
            long newCount = count.incrementAndGet();
            if (newCount > limit) {
                count.decrementAndGet();
                return -1;
            } else {
                return 1;
            }
        }


        @Override
        protected boolean tryReleaseShared(int arg) {
            count.decrementAndGet();
            return true;
        }
    }


    private final Sync sync;
    private final AtomicLong count;
    private volatile long limit;


    public LimitLatch(long limit) {
        this.limit = limit;
        this.count = new AtomicLong(0);
        this.sync = new Sync();
    }


    public void countUpOrAwait() throws InterruptedException {
        sync.acquireSharedInterruptibly(1);
    }


    public long countDown() {
        sync.releaseShared(0);
        long result = getCount();
        return result;
    }
}
流程嵌入控制器,伪代码如下,在接收socket前累加计数器,对socket的数据处理则交由另外的线程,它处理需要一段时间,假如这段时间又有1000个请求socket,则第1000个请求会导致停止程序阻塞,而唤醒的条件是线程池中的工作线程处理完其中一个socket并执行countDown操作。tomcat默认的大小为1000。
LimitLatch limitLatch = new LimitLatch(1000);
创建ServerSocket;
limitLatch.countUpOrAwait();//这里可能阻塞
Socket socket = ServerSocket.accept();

从线程池中获取一个空闲工作线程处理socket,处理完关闭socket并执行limitLatch.countDown();


点击订购作者《Tomcat内核设计剖析》



目录
相关文章
|
4月前
|
负载均衡 网络协议 Linux
探索服务端进程的TCP连接极限,一个服务端进程最多能支持多少条 TCP 连接?
探索服务端进程的TCP连接极限,一个服务端进程最多能支持多少条 TCP 连接?
158 4
|
10月前
|
网络协议 数据库
09 tcp长连接和短连接
09 tcp长连接和短连接
99 0
|
1月前
|
网络协议 算法 网络性能优化
TCP流量控制
【8月更文挑战第19天】
23 1
|
3月前
|
存储 网络协议 数据处理
【Socket】解决UDP丢包问题
UDP(用户数据报协议)是一种无连接的传输层协议,因其不保证数据包的顺序到达和不具备内置重传机制,导致在网络拥塞、接收缓冲区溢出或发送频率过快等情况下容易出现丢包现象。为应对这些问题,可以在应用层实现重传机制、使用前向纠错码等方法。这些方法在一定程度上可以缓解UDP通信中的丢包问题,提高数据传输的可靠性和效率。
|
3月前
|
网络协议 NoSQL 算法
TCP协议:超时重传、流量控制、keep-alive和端口号,你真的了解吗?
【6月更文挑战第2天】本文探讨了TCP协议的关键机制,包括超时重传计算(基于SRTT和RTT),流量控制(使用滑动窗口适应接收方处理能力),TCP keep-alive(通过定期探测保持连接活性),以及端口号的作用(区分不同服务和应用)。这些内容对于理解TCP的工作原理和面试准备至关重要。
|
4月前
|
网络协议 Linux
TCP中两种保活方式
【4月更文挑战第7天】两种保活方式:Keep Alive和心跳包
|
监控 网络协议 算法
TCP 拥塞控制详解 | 6. 主动队列管理
TCP 拥塞控制详解 | 6. 主动队列管理
466 1
TCP 拥塞控制详解 | 6. 主动队列管理
|
缓存 网络协议 算法
TCP 流量控制和拥塞控制
TCP 流量控制和拥塞控制
301 0
TCP 流量控制和拥塞控制
|
网络协议 API 数据库
TCP长连接与短连接的区别
TCP长连接与短连接的区别
412 0
|
网络协议 Unix 网络安全
socket跟TCP/IP 的关系,单台服务器上的并发TCP连接数可以有多少
常识一:文件句柄限制 在linux下编写网络服务器程序的朋友肯定都知道每一个tcp连接都要占一个文件描述符,一旦这个文件描述符使用完了,新的连接到来返回给我们的错误是“Socket/File:Can'topen so many files”。
4293 0