为什么使用线程池
- 因为频繁地创建和销毁线程开销太大;
- 当你需要限制你应用程序中同时运行的线程数时,线程池非常有用。因为启动一个新线程会带来性能开销,每个线程也会为其堆栈分配一些内存等。为了任务的并发执行,我们可以将这些任务任务传递到线程池,而不是为每个任务动态开启一个新的线程。
数据库连接池连接数开多少比较合适
- 与线程池里的线程的个数一致,项目里设置线程数是8个
- 一般:连接数 = ((核心数 * 2) + 有效磁盘数)
reactor和proactor有什么区别
- reactor是同步IO,proactor是异步IO。
- reactor注册的是文件描述符的就绪事件,proactor注册的是完成事件。
- reactor实现较为简单,对于耗时短的处理场景高效,proactor性能更高,逻辑复杂,能够处理耗时长的并发场景。
主从reactor结构
- Acceptor不再是一个线程,而是一组NIO线程;IO线程也是一组NIO线程,这样就是两个线程池去处理接入连接和处理IO。
web服务器怎么设计一个限流器
令牌桶法
:一个令牌允许接口发送或者接收 k bit的数据,当接口通过了 k bit的数据后,同时也要移除一个令牌,当桶中有令牌时才能允许数据通过,为了保证接口随时有数据通过,那么就必须不断地往里面添加令牌,令牌添加的速度就是数据通过接口的速度,即控制了用户流量的带宽。
可以使用生产者消费者模型来实现。
日志系统为什么是单例
- 因为单例模式和日志类的应用场景很相似,因为日志文件只能被一个进程打开。所以使用单例模式获取日志文件的实例对象,避免一个文件被多次打开造成的异常。
同步i/o模拟的proactor比单纯的reactor好在哪里
- 单纯的reactor本质属于同步IO,处理耗时长的操作(如文件I/O)会造成事件分发的阻塞,影响后续事件的处理。而同步i/o模拟的proactor解决了上面的问题,同时也避免了proactor模式的逻辑复杂,实现困难的问题。
你的项目的瓶颈在哪
单线程listener/accept,多个工作线程接受任务分发,虽然CPU工作负载不再成为问题,但是仍然存在问题:
(1)单线程listener(图一),在处理高速率海量连接的时候,一样会成为瓶颈
(2)cpu缓存行丢失套接字结构现象严重。
优化就是改成主从reacter结构
如果同时1000个客户端进行访问请求,线程数不多,怎么能及时响应处理每一个呢?
- 线程池动态扩容。
- 数据库缓存?缓存数据是为了让客户端很少甚至不访问数据库,减少磁盘IO,提高响应速度,进而提高并发量。数据库缓存还会缓解数据库压力。
- 消息队列,让请求等待在那,等线程池线程处理完毕之后从消息队列中取。