04 | 连接池:别让连接池帮了倒忙
04 | 连接池:别让连接池帮了倒忙
讲述:王少泽
时长23:42大小21.70M
注意鉴别客户端 SDK 是否基于连接池
使用连接池务必确保复用
连接池的配置不是一成不变的
重点回顾
思考与讨论
赞 22
提建议
精选留言(53)
- Darren置顶2020-03-16实操性比较强,收获满满!!! 自从spring boot 2.x版本后,有较大的改动: 默认的redis的链接池从JedisPool变成了LettucePool,Lettuce主要利用netty实现与redis的同步和异步通信。所以更安全和性能更好; 默认的数据库连接池也变更为HikariCP,HiKariCP 号称是业界跑得最快的数据库连接池,HiKariCP 官方网站解释了其性能之所以如此之高的秘密。微观上 HiKariCP 程序编译出的字节码执行效率更高,站在字节码的角度去优化 Java 代码,HiKariCP 的作者对性能的执着可见一斑,不过遗憾的是他并没有详细解释都做了哪些优化。而宏观上主要是和两个数据结构有关,一个是 FastList,另一个是 ConcurrentBag。 FastList是对Java List的增强,HiKariCP作者认为Java SDK的List在其使用场景下比较慢,因此在SDK提供的List(ArrayList的remove)的基础上做了增强; ConcurrentBag是对Java并发集合的增强, 通过 ThreadLocal 做一次预分配,避免直接竞争共享资源,非常适合池化资源的分配。 试着回答下课后的问题: 第一个问题: JedisPool的设置: 获取链接超时:maxWait TCP超时:JedisPool中有一个soTimeout的属性,在链接的时候,使用socket.setSoTimeout(soTimeout)控制的。 HikariCP的设置: 获取链接超时:connectionTimeout。 This property controls the maximum number of milliseconds that a client (that's you) will wait for a connection from the pool. If this time is exceeded without a connection becoming available, a SQLException will be thrown. Lowest acceptable connection timeout is 250ms. Default: 30000 (30 seconds) TCP超时:数据的库的wait_timeout属性吧 Apache HttpClient设置: 获取链接超时:connectionRequestTimeout 建立链接超时:connectionTimeout 等待响应超时:socketTimeout 第二个问题就不回答了,因为到目前为止,还没有在生产使用过Mongo,😂😂😂😂 上面有些参数感觉说的不对,请老师指点展开
作者回复: 假设我们希望设置连接超时5s,获取连接超时10s: hikari两个参数设置方式: spring.datasource.hikari.connection-timeout=10000 spring.datasource.url=jdbc:mysql://localhost:6657/common_mistakes?connectTimeout=5000&characterEncoding=UTF-8&useSSL=false&rewriteBatchedStatements=true jedis两个参数设置: JedisPoolConfig config = new JedisPoolConfig(); config.setMaxWaitMillis(10000); try (JedisPool jedisPool = new JedisPool(config, "127.0.0.1", 6379, 5000); Jedis jedis = jedisPool.getResource()) { return jedis.set("test", "test"); } httpclient两个参数设置: RequestConfig requestConfig = RequestConfig.custom() .setConnectTimeout(5000) .setConnectionRequestTimeout(10000) .build(); HttpGet httpGet = new HttpGet("http://127.0.0.1:45678/twotimeoutconfig/test"); httpGet.setConfig(requestConfig); try (CloseableHttpResponse response = httpClient.execute(httpGet)) {...
共 5 条评论62 - Wiggle Wiggle置顶2020-03-14请问对于连接池的监控,是把监控系统直连JMX,监控、修改操作都走连接池已经实现好的JMX比较好?还是自己做一层封装,对外暴露接口,以编程方式获取、设置参数比较好?
作者回复: 自己封装必要不大,然后如果需要走http的话用jolokia,或者使用prometheus的jmx_exporter以agent方式暴露mbeans,https://github.com/prometheus/jmx_exporter
34 - 👽置顶2020-03-16个人总结: 1. 池化技术的核心在于,在鱼塘养好一群鱼,需要的时候就从里面拿一条,用完再放回去。而不是自己生产一条鱼,然后用完就销毁。从而减少了开销。 2. 大多已经实现的连接池,都是有线程安全处理的。通常比个人创建管理连接更加安全。 3. 使用了连接池技术,就要保证连接池能够被有效复用。频繁创建连接池比频繁创建链接更加耗费资源。 4. 连接池的参数配置要根据实际情况,并不存在多多益善 5. 连接池的主要好处:(1)减少资源消耗,(2)利用现有的线城安全实现,(3)提升并发量展开
作者回复: 总结的不错
共 2 条评论12 - 蚂蚁内推+v2020-03-14退出程序前为什么要关闭连接池啊,程序都结束了连接不就释放了么
作者回复: 优雅关闭总是更好的
共 3 条评论9 - 每天晒白牙2020-03-14干货满满,还需要慢慢消化一下
作者回复: 如有收货,欢迎转发
8 - 👽2020-03-16hikari具体配置项为application.yml 中 spring.datasource.hikari.connection-timeout 点进去可以发现是 HikariDataSource 类,继承了HikariConfig。 点进HikariConfig可看出 connectionTimeout不允许小于250毫秒,小于250ms会被强制重置为30秒。 参数connectionTimeout定义是并未赋初始值的原始类型long,初始值应该是0L; 所以,个人判断,默认的connectionTimeout数值就是30秒。 如有纰漏,欢迎指正展开
作者回复: 回答一下Hikari的配置,其ConnectionTimeout是从连接池获取数据库连接的超时,不是和MySQL建立连接的超时,后者需要设置JDBC连接字符串中的connectTimeout属性。对于Hikari的JavaConfig配置这2个参数的方式是: @Bean public DataSource dataSource(){ HikariConfig hikariConfig = new HikariConfig(); hikariConfig.setConnectionTimeout(2400); hikariConfig.setJdbcUrl("jdbc:mysql://localhost:6658/common_mistakes"); hikariConfig.addDataSourceProperty("connectTimeout", "1200"); HikariDataSource dataSource = new HikariDataSource(hikariConfig); return dataSource; }
共 3 条评论5 - 👽2020-03-16课后题2: 受限于本人英文水平,无奈与使用谷歌翻译阅读文档。从文档中得知,MongoClient 对象的正确使用姿势应该是:使用 MongoClients.create()(或者其他有参) 方法创建,并再整个应用程序中使用它。文档内容如下: MongoClient (从3.7版本开始) 一个MongoClient实例表示到数据库连接池; MongoClient即使有多个线程,您也只需要一个类的实例。 重要 通常,您只MongoClient为给定的MongoDB部署创建一个实例(例如独立实例,副本集或分片群集),并在整个应用程序中使用它。但是,如果您确实创建了多个实例: 所有资源使用限制(例如,最大连接数等)适用于每个MongoClient实例。 要处置实例,请致电MongoClient.close()以清理资源。展开
作者回复: 是的
共 3 条评论6 - justin2020-03-26老师你好,看了这篇文章感觉收获满满,然后关于上面的CloseableHttpClient有个几个疑问: 1、复用同一个tcp连接的时候比每次都创建一个新的tcp连接的QPS高很多,当有大量http请求服务端时,每个http连接都共用同一个tcp连接时,这种情况下不会造成其中一些http请求的响应速度变慢吗。 2、 httpClient = HttpClients.custom().setMaxConnPerRoute(1).setMaxConnTotal(1).evictIdleConnections(60, TimeUnit.SECONDS).build(); 当我尝试去扩大setMaxConnTotal这个最大连接数时,qps反而降低了。如果线上有上千qps的话,设置连接数为1就可以了吗。展开
作者回复: 1、其实本文说的点不是复用连接,而是复用连接池,也就是CloseableHttpClient,一个TCP连接同时自然无法实现多个HTTP请求的复用 2、文中设置为1只是举例,实际应用的时候显然应该设置一个合理的最大值,不能是1。扩大MaxConnPerRoute和MaxConnTotal之后qps降低,这个有没有实际的性能数据?你是怎么测试的呢?
共 2 条评论4 - Husiun2020-03-14每次更新都是第一时间打开,每一课都干货满满,必须给老师赞一个,http那个平时研究不多还需要好好消化一下。
作者回复: 有收货就好
5 - pedro2020-03-14干货很多,收获很大。问老师一个问题,使用hook来关闭连接池的时候,都会创建一个线程,那如果有多个连接池,每个连接池都有一个线程来调用hook,这样做是否有点奢侈,有没有更优的办法?
作者回复: 可以都放到一个Thread,放到多个的话会并行执行,只要不是太多问题不大。或者用Spring的话还可以使用@PreDestroy来实现资源释放。
共 2 条评论4 - boyxie2020-04-06数据库连接池Druid 在数据库连接被网络中断后,需要15分钟的重连时间,这个超时时间为什么要这么久?总结网上的资料大致是获取连接的时候会去 testConnectionInternal,由于底层socket被断开,会一直被阻塞直到抛异常,老师可以帮忙分析一下吗?
作者回复: 这个问题我们也遇到过,看下此文你就明白咋回事了:https://www.elietio.xyz/2019/12/keepAlive%E8%A7%A3%E5%86%B3druid%E7%A9%BA%E9%97%B2%E8%BF%9E%E6%8E%A5socket%20timeout%2015%E5%88%86%E9%92%9F.html
共 3 条评论3 - 👽2020-03-16课后题1: Hikari 可以再Spring的配置文件中配置各项参数。
作者回复: 具体配置参数是什么呢?
3 - Outside2020-06-09请教一下老师,执行完 wrong2之后, client.execute阻塞住了是什么原因 线程dump如下 client.execute "http-nio-8088-exec-1" #28 daemon prio=5 os_prio=31 tid=0x00007fecb09d2000 nid=0x9a03 runnable [0x000070000d121000] java.lang.Thread.State: RUNNABLE at java.net.SocketInputStream.socketRead0(Native Method) at java.net.SocketInputStream.socketRead(SocketInputStream.java:116) at java.net.SocketInputStream.read(SocketInputStream.java:171) at java.net.SocketInputStream.read(SocketInputStream.java:141) at org.apache.http.impl.conn.LoggingInputStream.read(LoggingInputStream.java:84) at org.apache.http.impl.io.SessionInputBufferImpl.streamRead(SessionInputBufferImpl.java:137) at org.apache.http.impl.io.SessionInputBufferImpl.fillBuffer(SessionInputBufferImpl.java:153) at org.apache.http.impl.io.SessionInputBufferImpl.readLine(SessionInputBufferImpl.java:280) at org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:138) at org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:56) at org.apache.http.impl.io.AbstractMessageParser.parse(AbstractMessageParser.java:259) at org.apache.http.impl.DefaultBHttpClientConnection.receiveResponseHeader(DefaultBHttpClientConnection.java:163) at org.apache.http.impl.conn.CPoolProxy.receiveResponseHeader(CPoolProxy.java:157) at org.apache.http.protocol.HttpRequestExecutor.doReceiveResponse(HttpRequestExecutor.java:273) at org.apache.http.protocol.HttpRequestExecutor.execute(HttpRequestExecutor.java:125) at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:272) at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:186) at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:89) at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110) at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:185) 尝试用新启一个webserver, 用client.execute执行这个新的get请求,可以得到返回 这是什么原因呢展开
作者回复: 是不是之前做实验的时候server.tomcat.max-threads=1没有改过来呢?
2 - DZZ2020-04-05如果一个应用里使用了多个mongo库,那么是否应该创建多个mongoclient去对应每一个库的使用? 举个例子:1个应用需要连接3个不同mongo库,那么该如何正确去使用mongoclient呢
作者回复: 如果是不同的db但还是一个mongo集群还是用一个,除非你的应用真的是连接了多个mongo的集群
共 2 条评论2 - z小俊、Arno2020-03-27老师,说一个与本节无关的问题哈,你的git代码里面这一行,我不明白它的含义。。 <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <mainClass>org.geekbang.time.commonmistakes.troubleshootingtools.jdktool.CommonMistakesApplication </mainClass> </configuration> </plugin> </plugins> 这儿的 : <mainClass>org.geekbang.time.commonmistakes.troubleshootingtools.jdktool.CommonMistakesApplication </mainClass> 有什么作用啊?展开
作者回复: 后面加餐中我们需要打成jar包运行程序,这个项目中这么多main类,需要指定一个我们需要的main入口
共 2 条评论2 - 刘善良~2020-03-21有文档 资料 ,还是语音 要是 能倍速 播放 最好了,睡觉听,坐地铁听
作者回复: 音频可以倍速的
2 - Daiver2020-03-20jconsole观察连接数的时候为啥我这里没有图形的方式呢?2
- hellojd2020-03-17进程都kill了,相关的资源应该自动释放吧,比如启动的线程和连接。jvm环境都没了,依赖的基础都没了
作者回复: 优雅关闭总是好的,特别是涉及到服务端的tcp连接
2 - 匿名2020-03-17辛苦!老师2
- 袁素芬2020-03-15辛苦老师
作者回复: :)
2