数据库连接池到底应该设多大?这篇文章可能会颠覆你的认知

数据库连接池到底应该设多大?这篇文章可能会颠覆你的认知

本文内容95%译自这篇文章:https://github.com/brettwooldridge/HikariCP/wiki/About-Pool-Sizing 我在研究HikariCP(一个数据库连接池)时无意间在HikariCP的Github wiki上看到了一篇文章(即前面给出的链接),这篇文章有力地消除了我一直以来的疑虑,看完之后感觉神清气爽。故在此做译文分享。 接下来是正文 数据库连接池的配置是开发者们常常搞出坑的地方,在配置数据库连接池时,有几个可以说是和直觉背道而驰的原则需要明确。 1万并发用户访问 想象你有一个网站,压力虽然还没到Facebook那个级别,但也有个1万上下的并发访问——也就是说差不多2万左右的TPS。那么这个网站的数据库连接池应该设置成多大呢?结果可能会让你惊讶,因为这个问题的正确问法是: “这个网站的数据库连接池应该设置成多小呢?” 下面这个视频是Oracle Real World Performance Group发布的,请先看完: http://www.dailymotion.com/video/x2s8uec (因为这视频是英文解说且没有字幕,我替大家做一下简单的概括:) 视频中对Oracle数据库进行压力测试,9600并发线程进行数据库操作,每两次访问数据库的操作之间sleep 550ms,一开始设置的中间件线程池大小为2048: 初始的配置 压测跑起来之后是这个样子的: 2048连接时的性能数据 每个请求要在连接池队列里等待33ms,获得连接后执行SQL需要77ms 此时数据库的等待事件是这个熊样的: 各种buffer busy waits 各种buffer busy waits,数据库CPU在95%左右(这张图里没截到CPU) 接下来,把中间件连接池减到1024(并发什么的都不变),性能数据变成了这样: 连接池降到1024后 获取链接等待时长没怎么变,但是执行SQL的耗时减少了。 下面这张图,上半部分是wait,下半部分是吞吐量 wait和吞吐量 能看到,中间件连接池从2048减半之后,吐吞量没变,但wait事件减少了一半。 接下来,把数据库连接池减到96,并发线程数仍然是9600不变。 96个连接时的性能数据 队列平均等待1ms,执行SQL平均耗时2ms。 image.png wait事件几乎没了,吞吐量上升。 没有调整任何其他东西,仅仅只是缩小了中间件层的数据库连接池,就把请求响应时间从100ms左右缩短到了3ms。 But why? 为什么nginx只用4个线程发挥出的性能就大大超越了100个进程的Apache HTTPD?回想一下计算机科学的基础知识,答案其实是很明显的。 即使是单核CPU的计算机也能“同时”运行数百个线程。但我们都[应该]知道这只不过是操作系统用时间分片玩的一个小把戏。一颗CPU核心同一

☕【JVM原理探索】分析堆外内存(Direct Memory)使用和分析

☕【JVM原理探索】分析堆外内存(Direct Memory)使用和分析

这是我参与更文挑战的第19天,活动详情查看: 更文挑战 堆外内存 堆外内存,其实就是不受JVM控制的内存。简单来说,除了堆栈内存,剩下的就都是堆外内存了(当然,这是从Java运行时内存的角度来看),堆外内存直接受操作系统管理,而不是虚拟机。而使用堆外内存的原因, 相比于堆内内存有几个优势: 减少了垃圾回收的工作,因为垃圾回收会暂停其他的工作(可能使用多线程或者时间片的方式,根本感觉不到) 堆外内存是直接受操作系统管理的,而不是JVM,因此使用堆外内存的话,就可以保持一个比较小的堆内内存,减少垃圾回收对程序性能的影响。 就是提高IO操作的效率!这里就涉及用户态与内核态,以及内核缓冲区的概念,如果从堆内向磁盘写数据,数据会被先复制到堆外内存,即内核缓冲区,然后再由OS写入磁盘,但使用堆外内存的话则可以避免这个复制操作。 堆内内存其实就是用户进程的【进程缓冲区】,属于用户态;堆外内存由操作系统管理【内核缓冲区】,属于内核态。 自然也有不好的一面: 堆外内存难以控制,如果内存泄漏,那么很难排查 堆外内存相对来说,不适合存储很复杂的对象。一般简单的对象或者扁平化的比较适合。 因为是操作系统的内存机制,所以需要通过本地方法进行分配,较为复杂和缓慢 直接内存使用 堆外内存通过java.nio的ByteBuffer来创建,调用allocateDirect方法申请即可。 可以通过设置-XX:MaxDirectMemorySize=10M控制堆外内存的大小。 堆外内存的垃圾回收 由于堆外内存并不直接控制于JVM,因此只能等到full GC的时候才能垃圾回收!Full GC,一般发生在年老代垃圾回收以及调用System.gc的时候,这样肯定不能满足我们的需求! 手动的控制回收堆外内存了!其中sun.nio其实是java.nio的内部实现。 package xing.test; import java.nio.ByteBuffer; import sun.nio.ch.DirectBuffer; public class NonHeapTest { public static void clean(final ByteBuffer byteBuffer) { if (byteBuffer.isDirect()) { ((DirectBuffer)byteBuffer).cleaner().clean(); } } public static void sleep(long i) { try { Thread.sleep(i); }catch(Exception e) { /*skip*/ } } public static void main(String []args) throws Exception { ByteBuffer buffer = ByteBuffer.allocateDirect(1024 * 1024 * 200); System.out.println("start"); sleep(5000); c

Springboot 2.0选择HikariCP作为默认数据库连接池的五大理由

Springboot 2.0选择HikariCP作为默认数据库连接池的五大理由

摘要: 本文非原创,是笔者搜集了一些HikariCP相关的资料整理给大家的介绍,主要讲解了为什么sb2选择了HikariCP以及HikariCP为什么这么快。 Springboot2默认数据库连接池选择了HikariCP为何选择HikariCP理由一、代码量理由二、口碑理由三、速度理由四、稳定性理由五、可靠性HikariCP为什么这么快优化并精简字节码更好的并发集合类实现使用FastList替代ArrayListHikariCP与Druid相比哪个更好?Springboot2快速上手参考资料 Spring Boot 2默认数据库连接池选择了HikariCP 默认的数据库连接池由Tomcat换成HikariCP. 如果在一个Tomcat应用中用spring.datasource.type来强制使用Hikari连接池, 则可以去掉这个override. 为何选择HikariCP HiKariCP是数据库连接池的一个后起之秀,号称性能最好,可以完美地PK掉其他连接池,是一个高性能的JDBC连接池,基于BoneCP做了不少的改进和优化。其作者还有另外一个开源作品——高性能的JSON解析器HikariJSON。 它,超快,快到连Spring Boot 2都宣布支持了。 代码体积更是少的可怜,130kb。 https://github.com/brettwooldridge/HikariJSON 为何要使用HiKariCP?这要先从BoneCP说起: 什么?不是有C3P0/DBCP这些成熟的数据库连接池吗?一直用的好好的,为什么又搞出一个BoneCP来?因为,传说中BoneCP在快速这个特点上做到了极致,官方数据是C3P0等的25倍左右。不相信?其实我也不怎么信。可是,有图有真相啊(图片来自BoneCP官网:http://jolbox.com/benchmarks.html): 从上述结果可以看出HikariCP的性能远高于c3p0、tomcat等连接池,以致后来BoneCP作者都放弃了维护,在Github项目主页推荐大家使用HikariCP。另外,Spring Boot将在2.0版本中把HikariCP作为其默认的JDBC连接池。 PS:需要指出的是,上图中的数据是HikariCP作者对各个连接池调用DataSource.getConnection()、Connection.close()、Connection.prepareStatement()、Statement.execute()、Statement.close()方法的性能测试结果。 而且,网上对于BoneCP是好评如潮啊,推荐的文章一搜一大堆。 然而,上Maven Repository网站(http://mvnrepository.com/artifact/com.jolbox/bonecp)查找有没有最新版本的时候,你会发现最新的是2013年10月份的(这么久没新版本出来了?)。于是,再去BoneCP的Githut(https://github.com/wwadge/bonecp)上看看最近有没有提交代码。却发现,BoneCP的作者对于这个项目貌似已经心灰意冷,说是要让步给HikariCP了(有图有真相)

Java 对象占用内存大小与 java 对象格式

Java 对象占用内存大小与 java 对象格式

java 基本类型 byte:1个字节,8位,-128~127 最大存储数据量 255 short:2个字节,16位,-32768~32767 最大存储数据量 65535 char:2个字节,16位,存储Unicode编码,用‘’ int:4个字节,32位,负的2的31次方~2的31次方-1 最大存储数据量 2的31次方-1 float:4个字节,32位 double:8个字节,64位 long:8个字节,64位,负的2的64次方~2的64次方-1 最大存储数据量 2的64次方-1 ref:4(32bit) OR 8(64bit) OR 4(64bit && -XX:UseCompressedOops) 内存占用计算方法 如果读者关心对象在JVM中的存储原理,可阅读本文后边几个小节中关于对象存储原理的介绍。 如果不关心对象存储原理,而只想直接计算内存占用的话,其实并不难,笔者这里总结了三种方法以供参考: 1. Instrumentation 使用 java.lang.instrument.Instrumentation.getObjectSize() 方法,可以很方便的计算任何一个运行时对象的大小,返回该对象本身及其间接引用的对象在内存中的大小。 不过,这个类的唯一实现类InstrumentationImpl的构造方法是私有的,在创建时,需要依赖一个nativeAgent,和运行环境所支持的一些预定义类信息,我们在代码中无法直接实例化它,需要在JVM启动时,通过指定代理的方式,让JVM来实例化它。 具体来讲,就是需要声明一个premain方法,它和main方法的方法签名有点相似,只不过方法名叫“premain”,同时方法参数也不一样,它接收一个String类型和instrumentation参数,而String参数实际上和String[]是一样的,只不过用String统一来表达的。 在premain函数中,将instrumentation参数赋给一个静态变量,其它地方就可以使用了。 如: [java] public class SizeTool { private static Instrumentation instrumentation; public static void premain(String args, Instrumentation inst) { instrumentation = inst; } public static long getObjectSize(Object o) { return instrumentation.getObjectSize(o); } } 从方法名可以猜到,这里的premain是要先于main执行的,而先于main执行,这个动作只能由JVM来完成了。 即在JVM启动时,先启动一个agent,操作如下: 假设main方法所在的jar包为:A.jar,premain方法所在的jar包为B.jar。 注意为main所在的代码打包时,和其它工具类打包一样,需要声明一个MANIFEST.MF清单文件,如下所求: [plaintext] Manifest-Version: 1.0 Main-Class: yp.tools.Main Premain-Class: yp.too

利用开源 Sandboxie-Plus 为 Windows 桌面程序创建隔离沙箱环境 守护隐私 保持系统干净整洁

利用开源 Sandboxie-Plus 为 Windows 桌面程序创建隔离沙箱环境 守护隐私 保持系统干净整洁

Sandboxie-Plus 是什么 官网:https://sandboxie-plus.com/ GitHub:https://github.com/sandboxie-plus Sandboxie 是一款最早发布于 2004 年的老牌 Windows 沙盒软件,它可以创建一个隔离环境,在其中安装、运行程序而不影响沙盒外的文件。2020 年起,Sandboxie 转交开源社区维护。 Sandboxie-Plus 是开源社区基于 Sandboxie 开发的增强版本,拥有基于 Qt 的现代 UI 和开源后添加的所有新功能。Sandboxie-Plus 可以创建多个沙盒,可以为每个沙盒提供快照管理器、精细的文件系统控制、权限控制和网络访问控制。可以对沙盒内程序限制网络访问、限制资源访问(文件、注册表等)、限制提权、阻止访问剪贴板等。 Sandboxie-Plus 的第一个 1.0 稳定版发布于 2021 年 12 月 25 日,目前还在积极开发中。经笔者测试,目前的最新版 1.0.7 在 Windows 10 和 Windows 11 下都能正常使用,在 GitHub 上反馈的问题基本都能得到响应和修复。得益于热心的贡献者,UI 上的大部分元素都有中文翻译。 快速入门 Sandboxie-Plus (非便携模式) 默认将沙盘配置文件存放在 C:\Windows\Sandboxie.ini,备份此文件即可备份所有沙盘的配置。沙盘文件目录在 C:\Sandbox\[当前用户名]\[沙盘名] 中,在此路径下双击打开任何软件都将强制在沙盘中打开。沙盘中程序创建、修改的注册表位于 HKEY_USERS\Sandbox_[当前用户名]_[沙盘名] 中。当然,这些路径都可以在「设置-高级选项」中修改。 安装完成后还可以可选的在文件资源管理器右键菜单中添加「在沙盘中运行」项,方便使用。注意,这个文件必须要在你选择的沙盘中可读取,否则沙盘会报错。 在沙盘中运行程序与直接运行几乎没有区别,默认情况下在标题会有 [#] 标记,以及在鼠标移到标题时显示黄色边框,这些外观样式都可以在对应沙盘选项中修改。 ⚠️警告:不要认为隔离是100%的,即使虚拟机都存在被逃逸的可能,追求完美请使用物理方法隔离,不要尝试在沙盘中测试病毒! 沙盒模板简单介绍 部分功能需要捐赠,详见下方「捐赠获得支持者凭证(Supporter Certificate)」 Sandboxie-Plus 默认的 DefaultBox 即为标准隔离沙盒。这个沙盒模板默认不限制对所有文件的读取,但沙盒内程序无法写入、修改、删除沙盒外的文件、注册表。在沙盒内创建的文件会被重定向到该沙盒目录中,修改文件会在沙盒目录中创建一个副本进行修改,删除文件会在沙盒目录中建立一个对应的0字节文件。 安全防护加固型沙盒是在标准隔离沙盒的基础上,加上勾选「常

联系我们

联系电话

4000-640-466

联系邮箱

service@f-li.cn

办公地址

上海黄浦区外滩源1号

谢谢,您的信息已成功发送。
请填写信息。