范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

Java池化技术你了解多少?

  在我们平常的编码中,通常会将一些对象保存起来,这主要考虑的是对象的创建成本。比如像线程资源、数据库连接资源或者 TCP 连接等,这类对象的初始化通常要花费比较长的时间,如果频繁地申请和销毁,就会耗费大量的系统资源,造成不必要的性能损失。
  并且这些对象都有一个显著的特征,就是通过轻量级的重置工作,可以循环、重复地使用。这个时候,我们就可以使用一个虚拟的池子,将这些资源保存起来,当使用的时候,我们就从池子里快速获取一个即可。
  在 Java 中,池化技术应用非常广泛,常见的就有数据库连接池、线程池等,本文主讲连接池,线程池我们将在后续的博客中进行介绍。  公用池化包 Commons Pool 2简介
  我们首先来看一下 Java 中公用的池化包  Commons Pool 2 ,来了解一下对象池的一般结构。根据我们的业务需求,使用这套 API 能够很容易实现对象的池化管理。     org.apache.commons    commons-pool2    2.11.1
  GenericObjectPool  是对象池的核心类,通过传入一个对象池的配置和一个对象的工厂,即可快速创建对象池。 public GenericObjectPool(             final PooledObjectFactory factory,             final GenericObjectPoolConfig config)案例
  Redis 的常用客户端 Jedis,就是使用  Commons Pool  管理连接池的,可以说是一个最佳实践。下图是 Jedis 使用工厂创建对象的主要代码块。对象工厂类最主要的方法就是makeObject,它的返回值是 PooledObject  类型,可以将对象使用 new DefaultPooledObject<>(obj)  进行简单包装返回。
  redis.clients.jedis.JedisFactory ,使用工厂创建对象。 @Overridepublic PooledObject makeObject() throws Exception {  Jedis jedis = null;  try {    jedis = new Jedis(jedisSocketFactory, clientConfig);    //主要的耗时操作    jedis.connect();    //返回包装对象    return new DefaultPooledObject<>(jedis);  } catch (JedisException je) {    if (jedis != null) {      try {        jedis.quit();      } catch (RuntimeException e) {        logger.warn("Error while QUIT", e);      }      try {        jedis.close();      } catch (RuntimeException e) {        logger.warn("Error while close", e);      }    }    throw je;  }}
  我们再来介绍一下对象的生成过程,如下图,对象在进行获取时,将首先尝试从对象池里拿出一个,如果对象池中没有空闲的对象,就使用工厂类提供的方法,生成一个新的。  public T borrowObject(final Duration borrowMaxWaitDuration) throws Exception {    //此处省略若干行    while (p == null) {        create = false;        //首先尝试从池子中获取。        p = idleObjects.pollFirst();        // 池子里获取不到,才调用工厂内生成新实例        if (p == null) {            p = create();            if (p != null) {                create = true;            }        }        //此处省略若干行    }    //此处省略若干行}
  那对象是存在什么地方的呢?这个存储的职责,就是由一个叫作  LinkedBlockingDeque 的结构来承担的,它是一个双向的队列。
  接下来看一下  GenericObjectPoolConfig  的主要属性: // GenericObjectPoolConfig本身的属性private int maxTotal = DEFAULT_MAX_TOTAL;private int maxIdle = DEFAULT_MAX_IDLE;private int minIdle = DEFAULT_MIN_IDLE;// 其父类BaseObjectPoolConfig的属性private boolean lifo = DEFAULT_LIFO;private boolean fairness = DEFAULT_FAIRNESS;private long maxWaitMillis = DEFAULT_MAX_WAIT_MILLIS;private long minEvictableIdleTimeMillis = DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS;private long evictorShutdownTimeoutMillis = DEFAULT_EVICTOR_SHUTDOWN_TIMEOUT_MILLIS;private long softMinEvictableIdleTimeMillis = DEFAULT_SOFT_MIN_EVICTABLE_IDLE_TIME_MILLIS;private int numTestsPerEvictionRun = DEFAULT_NUM_TESTS_PER_EVICTION_RUN;private EvictionPolicy evictionPolicy = null; // Only 2.6.0 applications set this private String evictionPolicyClassName = DEFAULT_EVICTION_POLICY_CLASS_NAME;private boolean testOnCreate = DEFAULT_TEST_ON_CREATE;private boolean testOnBorrow = DEFAULT_TEST_ON_BORROW;private boolean testOnReturn = DEFAULT_TEST_ON_RETURN;private boolean testWhileIdle = DEFAULT_TEST_WHILE_IDLE;private long timeBetweenEvictionRunsMillis = DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS;private boolean blockWhenExhausted = DEFAULT_BLOCK_WHEN_EXHAUSTED;
  参数很多,要想了解参数的意义,我们首先来看一下一个池化对象在整个池子中的生命周期。如下图所示,池子的操作主要有两个:一个是业务线程,一个是检测线程。
  对象池在进行初始化时,要指定三个主要的参数:  maxTotal  对象池中管理的对象上限 maxIdle  最大空闲数 minIdle  最小空闲数
  其中 maxTotal 和业务线程有关,当业务线程想要获取对象时,会首先检测是否有空闲的对象。如果有,则返回一个;否则进入创建逻辑。此时,如果池中个数已经达到了最大值,就会创建失败,返回空对象。
  对象在获取的时候,有一个非常重要的参数,那就是最大等待时间( maxWaitMillis ),这个参数对应用方的性能影响是比较大的。该参数默认为 -1,表示永不超时,直到有对象空闲。
  如下图,如果对象创建非常缓慢或者使用非常繁忙,业务线程会持续阻塞 ( blockWhenExhausted  默认为 true),进而导致正常服务也不能运行。
  面试题
  一般面试官会问:你会把超时参数设置成多大呢?
  我一般都会把最大等待时间,设置成接口可以忍受的最大延迟。比如,一个正常服务响应时间 10ms 左右,达到 1 秒钟就会感觉到卡顿,那么这个参数设置成  500~1000ms  都是可以的。超时之后,会抛出 NoSuchElementException  异常,请求会快速失败,不会影响其他业务线程,这种 Fail Fast 的思想,在互联网应用非常广泛。
  带有evcit 字样的参数,主要是处理对象逐出的。池化对象除了初始化和销毁的时候比较昂贵,在运行时也会占用系统资源。比如,连接池会占用多条连接,线程池会增加调度开销等。业务在突发流量下,会申请到超出正常情况的对象资源,放在池子中。等这些对象不再被使用,我们就需要把它清理掉。
  超出  minEvictableIdleTimeMillis  参数指定值的对象,就会被强制回收掉,这个值默认是 30 分钟;softMinEvictableIdleTimeMillis  参数类似,但它只有在当前对象数量大于 minIdle 的时候才会执行移除,所以前者的动作要更暴力一些。
  还有 4 个 test 参数: testOnCreate 、testOnBorrow 、testOnReturn 、testWhileIdle ,分别指定了在创建、获取、归还、空闲检测的时候,是否对池化对象进行有效性检测。
  开启这些检测,能保证资源的有效性,但它会耗费性能,所以默认为 false。生产环境上,建议只将  testWhileIdle  设置为 true,并通过调整空闲检测时间间隔(timeBetweenEvictionRunsMillis ),比如 1 分钟,来保证资源的可用性,同时也保证效率。 JMH 测试
  使用连接池和不使用连接池,它们之间的性能差距到底有多大呢?下面是一个简单的 JMH 测试例子(见仓库),进行一个简单的 set 操作,为 redis 的 key 设置一个随机值。  @Fork(2) @State(Scope.Benchmark) @Warmup(iterations = 5, time = 1) @Measurement(iterations = 5, time = 1) @BenchmarkMode(Mode.Throughput) public class JedisPoolVSJedisBenchmark {    JedisPool pool = new JedisPool("localhost", 6379);    @Benchmark    public void testPool() {        Jedis jedis = pool.getResource();        jedis.set("a", UUID.randomUUID().toString());        jedis.close();    }    @Benchmark    public void testJedis() {        Jedis jedis = new Jedis("localhost", 6379);        jedis.set("a", UUID.randomUUID().toString());        jedis.close();    }    //此处省略若干行}
  将测试结果使用  meta-chart  作图,展示结果如下图所示,可以看到使用了连接池的方式,它的吞吐量是未使用连接池方式的 5 倍!
  数据库连接池 HikariCP
  HikariCP 源于日语"光る",光的意思,寓意软件工作速度和光速一样快,它是 SpringBoot 中默认的数据库连接池。数据库是我们工作中经常使用到的组件,针对数据库设计的客户端连接池是非常多的,它的设计原理与我们在本文开头提到的基本一致,可以有效地减少数据库连接创建、销毁的资源消耗。
  同是连接池,它们的性能也是有差别的,下图是 HikariCP 官方的一张测试图,可以看到它优异的性能,官方的 JMH 测试代码见 Github。
  一般面试题是这么问的:HikariCP 为什么快呢?主要有三个方面:  它使用  FastList  替代 ArrayList ,通过初始化的默认值,减少了越界检查的操作; 优化并精简了字节码,通过使用  Javassist ,减少了动态代理的性能损耗,比如使用invokestatic  指令代替 invokevirtual  指令; 实现了无锁的  ConcurrentBag ,减少了并发场景下的锁竞争。
  HikariCP 对性能的一些优化操作,是非常值得我们借鉴的,在之后的博客中,我们将详细分析几个优化场景。
  数据库连接池同样面临一个最大值( maximumPoolSize )和最小值(minimumIdle )的问题。这里同样有一个非常高频的面试题:你平常会把连接池设置成多大呢?
  很多同学认为,连接池的大小设置得越大越好,有的同学甚至把这个值设置成 1000 以上,这是一种误解。根据经验,数据库连接,只需要 20~50 个就够用了。具体的大小,要根据业务属性进行调整,但大得离谱肯定是不合适的。
  HikariCP  官方是不推荐设置 minimumIdle  这个值的,它将被默认设置成和 maximumPoolSize  一样的大小。如果你的数据库Server端连接资源空闲较大,不妨也可以去掉连接池的动态调整功能。
  另外,根据数据库查询和事务类型,一个应用中是可以配置多个数据库连接池的,这个优化技巧很少有人知道,在此简要描述一下。
  业务类型通常有两种:一种需要快速的响应时间,把数据尽快返回给用户;另外一种是可以在后台慢慢执行,耗时比较长,对时效性要求不高。如果这两种业务类型,共用一个数据库连接池,就容易发生资源争抢,进而影响接口响应速度。虽然微服务能够解决这种情况,但大多数服务是没有这种条件的,这时就可以对连接池进行拆分。
  如图,在同一个业务中,根据业务的属性,我们分了两个连接池,就是来处理这种情况的。
  HikariCP 还提到了另外一个知识点,在 JDBC4 的协议中,通过  Connection.isValid()  就可以检测连接的有效性。这样,我们就不用设置一大堆的 test 参数了,HikariCP 也没有提供这样的参数。 结果缓存池
  到了这里你可能会发现池(Pool)与缓存(Cache)有许多相似之处。
  它们之间的一个共同点,就是将对象加工后,存储在相对高速的区域。我习惯性将缓存看作是数据对象,而把池中的对象看作是执行对象。缓存中的数据有一个命中率问题,而池中的对象一般都是对等的。
  考虑下面一个场景,jsp 提供了网页的动态功能,它可以在执行后,编译成 class 文件,加快执行速度;再或者,一些媒体平台,会将热门文章,定时转化成静态的 html 页面,仅靠 nginx 的负载均衡即可应对高并发请求(动静分离)。
  这些时候,你很难说清楚,这是针对缓存的优化,还是针对对象进行了池化,它们在本质上只是保存了某个执行步骤的结果,使得下次访问时不需要从头再来。我通常把这种技术叫作结果缓存池( Result Cache Pool ),属于多种优化手段的综合。 小结
  下面我来简单总结一下本文的内容重点:
  我们从 Java 中最通用的公用池化包  Commons Pool 2  说起,介绍了它的一些实现细节,并对一些重要参数的应用做了讲解;Jedis 就是在 Commons Pool 2  的基础上封装的,通过 JMH 测试,我们发现对象池化之后,有了接近 5 倍的性能提升;接下来介绍了数据库连接池中速度速快的 HikariCP ,它在池化技术之上,又通过编码技巧进行了进一步的性能提升,HikariCP 是我重点研究的类库之一,我也建议你加入自己的任务清单中。
  总体来说,当你遇到下面的场景,就可以考虑使用池化来增加系统性能:  对象的创建或者销毁,需要耗费较多的系统资源;  对象的创建或者销毁,耗时长,需要繁杂的操作和较长时间的等待;  对象创建后,通过一些状态重置,可被反复使用。
  将对象池化之后,只是开启了第一步优化。要想达到最优性能,就不得不调整池的一些关键参数,合理的池大小加上合理的超时时间,就可以让池发挥更大的价值。和缓存的命中率类似,对池的监控也是非常重要的。
  如下图,可以看到数据库连接池连接数长时间保持在高位不释放,同时等待的线程数急剧增加,这就能帮我们快速定位到数据库的事务问题。
  平常的编码中,有很多类似的场景。比如 Http 连接池, Okhttp  和 Httpclient  就都提供了连接池的概念,你可以类比着去分析一下,关注点也是在连接大小和超时时间上;在底层的中间件,比如 RPC,也通常使用连接池技术加速资源获取,比如 Dubbo  连接池、 Feign  切换成 httppclient  的实现等技术。
  你会发现,在不同资源层面的池化设计也是类似的。比如线程池,通过队列对任务进行了二层缓冲,提供了多样的拒绝策略等,线程池我们将在后续的文章中进行介绍。
  线程池的这些特性,你同样可以借鉴到连接池技术中,用来缓解请求溢出,创建一些溢出策略。现实情况中,我们也会这么做。那么具体怎么做?有哪些做法?这部分内容就留给大家思考了。
  来源:tomcat.blog.csdn.net/article/details/123867269

冷类星体形成新恒星,尽管活动星系核天文学家感到困惑利用美国宇航局的爱非亚些远信,亲自想下人中的研究人员发现了CO4179星系,尽管在量指中心自时亮的活动车关吃,这个年前之的从走源仔维所究议,但它下在严生新的但星米白海萨大学的动人员韩旭荣誉来之不易这块奖牌非常沉重李梦因发烧错过比赛很遗憾北京时间10月1日,2022年国际篮联(FIBA)女篮世界杯决赛,中国女篮6183不敌卫冕冠军美国女篮获得亚军,追平队史最佳成绩。赛后,中国女篮球员李梦杨力维韩旭王思雨均接受了媒体这几年谁在闷声发大财这几年,谁在闷声发大财?各位要记住一个准则,这样的话你看待世界会完全不一样。这个世界的能量是守恒的。这个地方没有了,那个地方凸起来了,这个地方出现一个海沟,那个地方隆起一座火山,这平鲁人看平鲁李生财美不美,家乡水亲不亲,故乡人。这是人们流淌在血液里,镌刻在骨髓里对家乡的一种深深的热爱。我对家乡有一种特殊的情愫,家乡在我心中的分量是世界上任何繁华闹市都无可替代的。这里留下了对我人到中年,四事越少,生活越好作家梁文道曾说每个年轻人,都相信自己能飞,而中年人在扇动翅膀的时候,两边羽翼上还挂着甩不掉的重重的秤砣。少时酷爱做加法,只愿收获不愿舍,事事皆想拔头筹,满心满眼名和利。人到中年,走天安门广场好美,祝福祖国繁荣昌盛一年一度,一年一岁,祖国母亲,生日快乐,祝福伟大的祖国生日快乐,每每看到这样的场景,真的是心潮澎湃,天安门广场真的太美了,祖国首都北京真的太美了,生活在北京的人真的太幸福,北京的繁真正的高手,在别人眼里都是笨蛋无论什么时候任何场合,当大家都夸一个人聪明的时候,说明这个人根本就不够聪明。因为真正的聪明人,在别人眼里都是傻子水木然聪明是一种生存的能力而智慧则是生存的一种境界。世界上聪明人不多中超1逆转送武汉长江四连败奥乌苏奥斯卡双响坎特助攻戴帽北京时间9月29日,2022赛季中超联赛第18轮补赛,武汉长江主场对阵沧州雄狮。第4分钟,许东禁区前沿远射弹地破门。第19分钟,奥斯卡头球助攻奥乌苏抢射破门。第41分钟,坎特助攻奥新疆银行总行调增20亿元专项信贷资金支持伊犁州复工复产天山网讯(记者苏璐萍报道)9月29日晚,伊犁哈萨克自治州人民政府新闻办公室召开疫情防控新闻发布会。会上,新疆银行伊犁分行党委委员副行长曹强通报新疆银行伊犁分行助企纾困情况。新疆银行新疆不值得去的5个景点,曾为我国偿还47债务,是2弹1星原料产地新疆是很多人非常向往的地方,这里有东方小瑞士喀纳斯,中国的普罗旺斯伊犁,一年穿越四季的独库公路,以及有着最后一滴眼泪之称的赛里木湖,这些新疆独有的美景让不少游客流连忘返而今天要跟大廿万公里10章新疆餐厅吃饭,有人给片哈密瓜,千万不要接,是笼子哈萨克骑手在北疆勒马驰骋第一节准备一个人到新疆,书记不干了。自从俺在紫鹊界小东江漓江徒步归来之后,觉得一个人独游那是太过瘾了。这不国庆节又要到了放假七天,俺又在发愁到哪里去混过这几九九又重阳金风飘菊蕊,玉露泣萸枝。转眼又到了一年一度的重阳节。刚下楼,看到一对银发爷爷奶奶,他们相互搀扶着,开心地在交流着什么,时不时还停下脚步温情地看着对方。这无疑是重阳节最动人的风景,同乒乓奶奶再发威!59岁倪夏莲独赢两场,率队提前晋级世乒赛16强北京时间10月3日晚,2022世界乒乓球团体锦标赛继续在我国成都进行。19点开球的一场较量中,传奇老将倪夏莲带领卢森堡女乒击败泰国队,以3胜1负的战绩结束第一阶段小组征程尽管同组对太阳大爆冷!绿军41分大胜,爵士新王当立!两将42分火箭收获惊喜休赛期市场虽然告一段落,但季前赛却充满看点,仅仅一夜,便又迎来了4组对决。而在这其中,太阳大爆冷,绿军41分大胜,爵士新王当立,两将42分火箭收获惊喜!绿军41分大胜经历了休赛期的看着哈兰德在英超天神下凡,我满眼都是巅峰罗纳尔多哈兰德,让世界惊叹。3个进球,2次助攻,无所不能的哈兰德,以一己之力将曼联生吞活剥。2日晚,曼城主场63大胜曼联,哈兰德在8场14球的恐怖输出的同时,兴之所至的挪威人,甚至还用德布终于不装了!再见郭艾伦!人家会是辽宁队的新老大用一张图表达心情!全新的赛季,全新的合同,全新的号码,全新的张镇麟。从这家伙最近的采访,第一次感受到他的野心,或许是夺冠后就要放飞自我了。首先按张镇麟的说法,他在新赛季希望换一种打成都世乒赛团体赛小组赛首局连下7分打出气势,樊振东30取胜10月3日,成都世乒赛团体赛男团第一小组的比赛继续进行,中国队迎战斯洛文尼亚队。樊振东王楚钦和马龙三名选手出战本场比赛。首先登场的是樊振东,而他的对手是丹尼科组尔。首局比赛尽管一度王治郅新工作内容曝光!大校军衔,球迷难怪拒绝姚明的邀请10月3日,八一男篮解散之后淡出公众视野的王治郅,再次成为国内媒体球迷关注的焦点!值得一提的是,王治郅受到国内媒体球迷的关注,与他的90后妻子无关,而是因为他的新工作。2020年1愤怒!韩旭前两年状态低迷也曾被网暴喷子祝我坐飞机回去时坠机10月3日消息,2022年女篮世界杯已经落下帷幕,中国女篮获得亚军,追平队史最好成绩。女篮当家球星李梦因高烧错过决赛遭到极端网友的攻击,对此,韩旭表示自己也曾遭遇过网暴。本届赛事,大意外!国乒女队7个30之后有人丢了一局,首秀就犯错真的太不稳北京时间10月3日,世乒赛小组赛中国女乒大战美国队的比赛已经到来了,女篮两天之前输给美国,那么现在国乒女队能不能给他们报仇?给无畏金兰的姐妹们出一口气呢?答案是肯定的。本场国乒使用西边的太阳快要落山了太阳队季前赛爆冷惨败NBL弱旅10月3日,季前赛,太阳队主场对决NBL球队阿德莱德36人,太阳队惨败。历史第18次NBA球队输给非NBA球队。上半场,阿德莱德投进12个三分球,太阳队半场输了12分,下半场太阳队开门红!火箭捡到宝了,两大首轮秀力压格林,这次斯通该妥协了北京时间10月3日,NBA季前赛迎来一场万众瞩目的对决,由休斯顿火箭主场迎战马刺,作为一场德比内战,这场比赛引发诸多媒体们的关注,其最主要的原因还是两支球队都属于重建期,且队内都拥
开启下饺子模式OPPO下月将发布三款新机2月份目前看来要等新机发布的话就都是月底的MWC上了,所以让我们把目光转向3月。今日,博主数码闲聊站带来了OPPO三款新机的消息,其表示OPPO已经有三款新机备案完成只待发布了,三超高速2T固态硬盘地板价了,入手国产金百达M。2SSD硬盘实测超高速2T固态硬盘地板价了,入手国产金百达M。2SSD硬盘实测自从M。2SSD硬盘面世之后,凭借超高的速度,超薄的身材,安装简单获得了大家的喜爱。的确,数倍于SATA机械硬盘和SA微软在谷歌Chrome浏览器官网注入全尺寸广告,希望用户留在EdgeIT之家2月22日消息,作为Windows10和11系统中的预装浏览器,微软Edge也是很多用户下载Chrome或其他浏览器的首选。不过这让微软很不高兴,以至于其无所不用其极地想尽星际传说地球的人文故事分享历史五千年我是外星人海角七号坐着飞船我来到了古埃及时期的金字塔前,惊叹于人类早期文明所创造的巨大工程,同时也对埃及文化的神秘和神话充满了好奇。接着,到达了中国的长城,看到了古代莱莎的炼金工房3全平台预购开启Steam标准版售价349元莱莎的炼金工房3全平台预购今日(2月22日)正式开启,该作将于3月23日登陆PS5PS4Switch和Steam(Steam版将于3月24日发售),支持中文。Steam莱莎的炼金工三国谈夷陵之战解析真实的理由游戏中的关羽形象文宋延坤公元219年,孙权突然向荆州发动进攻,并擒杀了刘备麾下最重要的将领关羽。公元221年,刘备匆忙地在益州称帝,并在同一年亲率大军讨伐东吴,这场大战也就是三国时开学了要跟室友5排开黑?看看这四款高性价比性能机手机中国导购开学季来临,全国各地的高校陆续开学,大学生们也纷纷返校。在校期间,最有意思的事情莫过于跟室友一起开黑打游戏。但当下国内手游市场推出的新游往往对手机配置要求非常高,而此前三职业传奇自由之刃2怎么打宝三职业传奇自由之刃2怎么打宝小伙伴们大家好今天继续讲自由之刃2王城争霸这款在1的基础上更是,满满福利满级会员免费送做任务得魂环可打金猪爆充值每日灵符兑换,好了,言归正传以上图片来自森林之子steam下载方法森林续作森林之子下载超详细教学森林之子是恐怖游戏森林的续作,于2月24日正式上线,热度一再飙升。这作的设定是玩家们来到一座孤岛完成任务,会碰到古怪的生物。有很多玩家都在查找森林之子steam下载方法,想知道如何中文在线科幻主题元宇宙RESTART将于近期上线e公司讯,中文在线(300364)在互动平台表示,RESTART将于近期上线。RESTART是以流浪地球为世界观基底打造的元宇宙空间,公司拥有刘慈欣流浪地球数字版权及AVG全球全语抓住长高黄金期让孩子春天蹿个头春季不仅是万物生长的季节,更是孩子们长高的黄金期。近日,长沙市第三医院骨科二十一病室副主任副主任医师刘峰提醒家长和孩子,选择一些向上的跳跃类运动,如跳绳打篮球羽毛球引体向上等,可以