二、网站高性能架构设计——web前端与池化

news2024/7/4 5:24:48

 从公众号转载,关注微信公众号掌握更多技术动态

---------------------------------------------------------------

一、高性能浏览器访问

1.减少HTTP请求

    HTTP协议是无状态的应用层协议,也就是说每次HTTP请求都需要建立通信链路、进行数据传输,而在服务器端,每个HTTP都需要启动独立的线程进行处理。这些通信和服务的开销很昂贵,因此减少HTTP请求的数量可以有效提高访问性能。

(1)合并CSS、合并JS

    将浏览器一次访问需要的JS、CSS合并成一个文件、这样浏览器只需要一次请求。然而这种方式不利于模块化代码的编写,会让代码的组织变得杂乱无章,同时可能导致一个页面加载时加载了多于自己所需要的样式或者脚本,因此该种方式需要进行权衡利弊后再进行使用。

(2)合并图片

    可以将多张图片合并成一张,如果每张图片都有不同的超链接,可通过CSS偏移坐标响应鼠标点击操作。

<div>    <span id="image1" class="nav"></span>    <span id="image2" class="nav"></span>    <span id="image3" class="nav"></span>    <span id="image4" class="nav"></span>    <span id="image5" class="nav"></span></div>.nav {    width: 50px;    height: 50px;    display: inline-block;    border: 1px solid #000;    background-image: url('E:/1.png');}#image1 {        background-position: 0 0;}#image2 {        background-position: -95px 0;}#image3 {        background-position: -185px 0;}#image4 {        background-position: -275px 0;}#image5 {        background-position: -366px -3px;}

2.使用浏览器缓存

    对于一个网站来说,CSS、JS、图标这些静态资源文件更新的频率比较低,而这些文件又几乎是每次HTTP请求都需要的,如果将这些文件缓存在浏览器中,可以极好地改善性能。通过服务端设置HTTP头中Cache-Control和Expires的属性,可设定浏览器缓存,缓存时间可以是数天甚至是几个月。

    在某些时候,静态资源文件变化需要及时引用到客户端浏览器,这种情况,可通过改变文件名实现,使用浏览器缓存策略的时候网站在更新静态资源时,应采用逐量更新的方法,比如要更新100个图片文件,不应该同时更新,而是应该根据情况选择五个五个更新以此来避免大量缓存失效,集中更新缓存,造成服务器负载骤、网络堵塞的情况。

3.启用压缩

    在服务端对文件进行压缩,在浏览器端对文件进行解压缩,可有效减少通信传输的数据量。文本文件的压缩效率可达80%以上,一次HTML、CSS、JS文件启用GZIP压缩可达到良好的效果。但是压缩对服务器和浏览器会产生一定的压力,在通信带宽良好,而服务器资源不足的情况下不推荐使用。

4.CSS放在页面头部,JS放在页面底部

    浏览器会在下载全部CSS后对页面进行渲染,因此最好是将CSS放在页面的最上面,让浏览器尽快下载CSS.和JS则相反,浏览器在加载JS后立即执行,有可能阻塞整个页面,造成页面显示缓慢,因此JS最好放在页面最下面。

5.减少cookie传输

    一方面cookie包含在每次请求和响应中,太大的cookie会严重影响数据传输,因此哪些数据需要写入Cookie需要慎重考虑,尽量减少Cookie的数据量。另一方面对于大多数静态资源来说,发送cookie没有意义,可以考虑静态资源使用独立的域名进行访问,避免请求静态资源的时候也包含Cookie。

二、CDN加速

    CDN的本质仍然是一个缓存,而且是将数据缓存在离用户最近的地方,使用户以最快速度获取数据。由于CDN部署在网络运营商的机房,这些运营商又是终端运营商的网络服务提供商,因此用户请求路由第一跳就到达了CDN服务器,当CDN中存在浏览器请求的资源时,从CDN直接返回给浏览器,最短路径返回响应(即北京用户访问北京的数据,杭州用户访问杭州 的数据),加快用户访问速度,减少数据中心复杂压力。CDN 就是将静态的资源分发到位于多个地理位置机房中的服务器上,因此它 能很好地解决数据就近访问的问题,也就加快了静态资源的访问速度。

    CDN缓存的一般是一些静态资源,图片、CSS、JS、静态网页等,这些文件访问率高,放在CDN可以极大改善网页的打开速度。

1.如何让用户的请求到达 CDN 节点

    可能会觉得这很简单,只需要告诉用户 CDN 节点的 IP 地址,然后请求这个 IP 地址上面部署的 CDN 服务就可以了 啊。但是这样会有一个问题:就是使用的是第三方厂商的 CDN 服务,CDN 厂商会给一个 CDN 的节点 IP,比如说这个 IP 地址是“111.202.34.130”,那么电商系统中的图片的地址很可能是这样的:“http://111.202.34.130/1.jpg”, 这个地址是 要存储在数据库中的。

    那么如果这个节点 IP 发生了变更怎么办?或者如果更改了 CDN 厂商怎么办?是不是要修改所有的商品的 url 域名呢?这就是一个比较大的工作量了。所以要做的事情是 将第三方厂商提供的 IP 隐藏起来,给到用户的最好是一个本公司域名的子域名。

    那么如何做到这一点呢?这就需要依靠 DNS 来解决域名映射的问题了。DNS(Domain Name System,域名系统)实际上就是一个存储域名和 IP 地址对应关系 的分布式数据库。而域名解析的结果一般有两种,一种叫做“A 记录”,返回的是域名对应 的 IP 地址;另一种是“CNAME 记录”,返回的是另一个域名,也就是说当前域名的解析 要跳转到另一个域名的解析上,实际上 www.baidu.com 域名的解析结果就是一个 CNAME 记录,域名的解析被跳转到 www.a.shifen.com 上了,正是利用 CNAME 记 录来解决域名映射问题的,具体是怎么解决的呢?

    比如一级域名叫做 example.com,那么可以图片服务的域名定义 为“img.example.com”,然后将这个域名的解析结果的 CNAME 配置到 CDN 提供的域名上,比如 uclound 可能会提供一个域名是“80f21f91.cdn.ucloud.com.cn”这个域名。这样你的电商系统使用的图片地址可以是“http://img.example.com/1.jpg”。用户在请求这个地址时,DNS 服务器会将域名解析到 80f21f91.cdn.ucloud.com.cn 域名 上,然后再将这个域名解析为 CDN 的节点 IP,这样就可以得到 CDN 上面的资源数据了。

2.如何找到离用户最近的 CDN 节点

    GSLB(Global Server Load Balance,全局负载均衡), 它的含义是对于部署在不同地域 的服务器之间做负载均衡,下面可能管理了很多的本地负载均衡组件。它有两方面的作用:GSLB 可以通过多种策略,来保证返回的 CDN 节点和用户尽量保证在同一地缘区域,比如 说可以将用户的 IP 地址按照地理位置划分为若干的区域,然后将 CDN 节点对应到一个区 域上,然后根据用户所在区域来返回合适的节点;也可以通过发送数据包测量 RTT 的方式 来决定返回哪一个节点。有了 GSLB 之后,节点的解析过程变成了下图中的样子:一方面,它是一种负载均衡服务器,负载均衡,顾名思义嘛,指的是让流量平均分配使 得下面管理的服务器的负载更平均;另一方面,它还需要保证流量流经的服务器与流量源头在地缘上是比较接近的。

图片

    当然,是否能够从 CDN 节点上获取到资源还取决于 CDN 的同步延时。一般会通过 CDN 厂商的接口将静态的资源写入到某一个 CDN 节点上,再由 CDN 内部的同步机制将 资源分散同步到每个 CDN 节点,即使 CDN 内部网络经过了优化,这个同步的过程是有延 时的,一旦无法从选定的 CDN 节点上获取到数据,就不得不从源站获取数据,而 用户网络到源站的网络可能会跨越多个主干网,这样不仅性能上有损耗,也会消耗源站的带 宽,带来更高的研发成本。所以在使用 CDN 的时候需要关注 CDN 的命中率和源站 的带宽情况。

三、动静分离

    动静分离是指,静态页面与动态页面解耦分离,用不同系统承载对应流量的架构设计方法。

1.动静分离简介

“动静分离”就是把用户请求的数据(如 HTML 页面)划分为“动态数据”和“静态数据”。简单来说,“动态数据”和“静态数据”的主要区别就是看页面中输出的数据是否和 URL、浏览者、时间、地域相关,以及是否含有 Cookie 等私密数据。比如说:

  • 很多媒体类的网站,某一篇文章的内容不管是你访问还是我访问,它都是一样的。所以 它就是一个典型的静态数据,但是它是个动态页面。

  • 如果现在访问淘宝的首页,每个人看到的页面可能都是不一样的,淘宝首页中包含 了很多根据访问者特征推荐的信息,而这些个性化的数据就可以理解为动态数据了。

静态数据,不能仅仅理解为传统意义上完全存在磁盘上的 HTML 页面,它也可能是经过 Java 系统产生的页面,但是它输出的页面本身不包含上面所 说的那些因素。也就是所谓“动态”还是“静态”,并不是说数据本身是否动静,而是数据 中是否含有和访问者相关的个性化数据。还有一点要注意,就是页面中“不包含”,指的是“页面的 HTML 源码中不含有”,这一 点务必要清楚。分离了动静数据,就可以对分离出来的静态数据做缓存,有了缓存之后,静态数据 的“访问效率”自然就提高了。

2.动静分离的实现

静态页面与动态页面解耦分离,用不同系统承载对应流量的架构

图片

  • 静态页面访问路径短,访问速度快,几毫秒

  • 动态页面访问路径长,访问速度相对较慢(数据库的访问,网络传输,业务逻辑计算),几十毫秒甚至几百毫秒,对架构扩展性的要求更高

  • 静态页面与动态页面以不同域名区分

3.静态页面缓存

(1)静态数据缓存

把静态数据缓存到离用户最近的地方。静态数据就是那些相对不会变化的数 据,因此我们可以把它们缓存起来。缓存到哪里呢?常见的就三种,用户浏览器里、CDN 上或者在服务端的 Cache 中。

(2)页面静态化技术

将原本需要动态生成的站点提前生成好,使用静态页面加速技术来访

图片

  • 用户端访问/detail/12348888x.shtml 详情页;

  • web-server层从RESTful接口中,解析出帖子id是12348888;

  • service通过DAO层拼装SQL,访问数据库;

  • 最终获取数据,拼装html返回浏览器;

而“页面静态化”是指,将帖子ID为12348888的帖子12348888x.shtml提前生成好,由静态页面相关加速技术来加速,这样的话,将极大提升访问速度,减少访问时间,提高用户体验。

图片

并不是所有的业务场景都适合页面静态化,滥用该技术,反而会降低系统性能。页面静态化,适用于:总数据量不大,生成静态页面数量不多的业务。

  • 快狗打车的城市页只有几百个,就可以用这个优化,只需提前生成几百个城市的“静态化页面”即可;

  • 一些二手车业务,只有几万量二手车库存,也可以提前生成这几万量二手车的静态页面;

  • 像58同城这样的信息模式业务,有几十亿的帖子量,就不太适合于静态化(碎片文件多,反而访问慢);

(3)谁来缓存静态数据

    不同语言写的 Cache 软件处理缓存数据的效率也各 不相同。以 Java 为例,因为 Java 系统本身也有其弱点(比如不擅长处理大量连接请求, 每个连接消耗的内存较多,Servlet 容器解析 HTTP 协议较慢),所以你可以不在 Java 层 做缓存,而是直接在 Web 服务器层上做,这样你就可以屏蔽 Java 语言层面的一些弱点;而相比起来,Web 服务器(如 Nginx、Apache、Varnish)也更擅长处理大并发的静态文 件请求。

4.动静分离的改造实践

(1)分离动态内容和静态内容

    以典型的商品详情系统为例来详细介绍。这里,你可以先打开京东或者淘宝的商品 详情页,看看这个页面里都有哪些动静数据。从以下 5 个方面来分离出动态内容。

  • URL 唯一化。商品详情系统天然地就可以做到 URL 唯一化,比如每个商品都由 ID 来标 识,那么 http://item.xxx.com/item.htm?id=xxxx 就可以作为唯一的 URL 标识。为啥 要 URL 唯一呢?前面说了我们是要缓存整个 HTTP 连接,那么以什么作为 Key 呢?就 以 URL 作为缓存的 Key,例如以 id=xxx 这个格式进行区分。

  • 分离浏览者相关的因素。浏览者相关的因素包括是否已登录,以及登录身份等,这些相 关因素我们可以单独拆分出来,通过动态请求来获取。

  • 分离时间因素。服务端输出的时间也通过动态请求获取。

  • 异步化地域因素。详情页面上与地域相关的因素做成异步方式获取,当然你也可以通过 动态请求方式获取,只是这里通过异步获取更合适。

  • 去掉 Cookie。服务端输出的页面包含的 Cookie 可以通过代码软件来删除,如 Web 服 务器 Varnish 可以通过 unset req.http.cookie 命令去掉 Cookie。注意,这里说的去掉 Cookie 并不是用户端收到的页面就不含 Cookie 了,而是说,在缓存的静态数据中不含 有 Cookie。

(2)数据组织

分离出动态内容之后,如何组织这些内容页就变得非常关键了。因为这其中很多动态内容都会被页面中的其他模块用到,如判断该用户是否已登录、用户 ID 是 否匹配等,所以这个时候应该将这些信息 JSON 化(用 JSON 格式组织这些数据), 以方便前端获取。动态内容的处理通常有两种方案:ESI(Edge Side Includes)方案和 CSI(Client Side Include)方案。

  • ESI 方案(或者 SSI):即在 Web 代理服务器上做动态内容请求,并将请求插入到静态 页面中,当用户拿到页面时已经是一个完整的页面了。这种方式对服务端性能有些影 响,但是用户体验较好。

  • CSI 方案。即单独发起一个异步 JavaScript 请求,以向服务端获取动态内容。这种方式 服务端性能更佳,但是用户端页面可能会延时,体验稍差。

(3)动静分离的几种架构方案

  • 实体机单机部署;

  • 统一 Cache 层;

  • 上 CDN。

方案 1:实体机单机部署

    这种方案是将虚拟机改为实体机,以增大 Cache 的容量,并且采用了一致性 Hash 分组的 方式来提升命中率。这里将 Cache 分成若干组,是希望能达到命中率和访问热点的平衡。Hash 分组越少,缓存的命中率肯定就会越高,但短板是也会使单个商品集中在一个分组 中,容易导致 Cache 被击穿,所以应该适当增加多个相同的分组,来平衡访问热点和命中率的问题。这里我给出了实体机单机部署方案的结构图,如下:

图片

实体机单机部署有以下几个优点:

  • 没有网络瓶颈,而且能使用大内存;

  • 既能提升命中率,又能减少 Gzip 压缩;

  • 减少 Cache 失效压力,因为采用定时失效方式,例如只缓存 3 秒钟,过期即自动失效。

这个方案中,虽然把通常只需要虚拟机或者容器运行的 Java 应用换成实体机,优势很明显,它会增加单机的内存容量,但一定程度上也造成了 CPU 的浪费,因为单个的 Java 进程很难用完整个实体机的 CPU。另外就是,一个实体机上部署了 Java 应用又作为 Cache 来使用,这造成了运维上的高复 杂度,所以这是一个折中的方案。如果没有更多的系统有类似需求,那么这样 做也比较合适,如果有多个业务系统都有静态化改造的需求,那还是建议把 Cache 层 单独抽出来公用比较合理。

方案 2:统一 Cache 层

将单机的 Cache 统一分离出来,形成一个单独的 Cache 集群。统一 Cache 层是个更理想的可推广方案,该方案的结构图如下:

图片

将 Cache 层单独拿出来统一管理可以减少运维成本,同时也方便接入其他静态化系统。此 ,它还有一些优点。

  • 单独一个 Cache 层,可以减少多个应用接入时使用 Cache 的成本。这样接入的应用只 要维护自己的 Java 系统就好,不需要单独维护 Cache,而只关心如何使用即可。

  • 统一 Cache 的方案更易于维护,如后面加强监控、配置的自动化,只需要一套解决方案 就行,统一起来维护升级也比较方便。

  • 可以共享内存,最大化利用内存,不同系统之间的内存可以动态切换,从而能够有效应 对各种攻击。

这种方案虽然维护上更方便了,但是也带来了其他一些问题,比如缓存更加集中,导致:

  • Cache 层内部交换网络成为瓶颈;

  • 缓存服务器的网卡也会是瓶颈;

  • 机器少风险较大,挂掉一台就会影响很大一部分缓存数据。要解决上面这些问题,可以再对 Cache 做 Hash 分组,即一组 Cache 缓存的内容相同,这 样能够避免热点数据过度集中导致新的瓶颈产生。

方案 3:上 CDN

在将整个系统做动静分离后,自然会想到更进一步的方案,就是将 Cache 进一步前移到 CDN 上,因为 CDN 离用户最近,效果会更好。但是要想这么做,有以下几个问题需要解决。

  • 失效问题。前面我们也有提到过缓存时效的问题,不知道你有没有理解,我再来解释一 下。谈到静态数据时,我说过一个关键词叫“相对不变”,它的言外之意是“可能会变 化”。比如一篇文章,现在不变,但如果你发现个错别字,是不是就会变化了?如果你 的缓存时效很长,那用户端在很长一段时间内看到的都是错的。所以,这个方案中也 是,我们需要保证 CDN 可以在秒级时间内,让分布在全国各地的 Cache 同时失效,这 对 CDN 的失效系统要求很高。

  • 命中率问题。Cache 最重要的一个衡量指标就是“高命中率”,不然 Cache 的存在就失 去了意义。同样,如果将数据全部放到全国的 CDN 上,必然导致 Cache 分散,而 Cache 分散又会导致访问请求命中同一个 Cache 的可能性降低,那么命中率就成为一个 问题。

  • 发布更新问题。如果一个业务系统每周都有日常业务需要发布,那么发布系统必须足够 简洁高效,而且你还要考虑有问题时快速回滚和排查问题的简便性。

从前面的分析来看,将商品详情系统放到全国的所有 CDN 节点上是不太现实的,因为存在失效问题、命中率问题以及系统的发布更新问题。那么是否可以选择若干个节点来尝试实施 呢?答案是“可以”,但是这样的节点需要满足几个条件:

  • 靠近访问量比较集中的地区;

  • 离主站相对较远;

  • 节点到主站间的网络比较好,而且稳定;

  • 节点容量比较大,不会占用其他 CDN 太多的资源。

  • 节点不要太多。

基于上面几个因素,选择 CDN 的二级 Cache 比较合适,因为二级 Cache 数量偏少,容量 也更大,让用户的请求先回源的 CDN 的二级 Cache 中,如果没命中再回源站获取数据, 部署方式如下图所示:

图片

使用 CDN 的二级 Cache 作为缓存,可以达到和当前服务端静态化 Cache 类似的命中率, 因为节点数不多,Cache 不是很分散,访问量也比较集中,这样也就解决了命中率问题, 同时能够给用户最好的访问体验,是当前比较理想的一种 CDN 化方案。除此之外,CDN 化部署方案还有以下几个特点:

  • 把整个页面缓存在用户浏览器中;

  • 如果强制刷新整个页面,也会请求 CDN;

  • 实际有效请求,只是用户对“刷新抢宝”按钮的点击。

这样就把 90% 的静态数据缓存在了用户端或者 CDN 上,当真正秒杀时,用户只需要点击 特殊的“刷新抢宝”按钮,而不需要刷新整个页面。这样一来,系统只是向服务端请求很少 的有效数据,而不需要重复请求大量的静态数据。秒杀的动态数据和普通详情页面的动态数据相比更少,性能也提升了 3 倍以上。

存储在浏览器或 CDN 上区别很大,因为在 CDN 上,可以做主动失效,而在用户的浏览器里就更不可控,如果用户不主动刷新的 话,你很难主动地把消息推送给用户的浏览器。另外,在什么地方把静态数据和动态数据合并并渲染出一个完整的页面也很关键,假如在用 户的浏览器里合并,那么服务端可以减少渲染整个页面的 CPU 消耗。如果在服务端合并的 话,就要考虑缓存的数据是否进行 Gzip 压缩了:如果缓存 Gzip 压缩后的静态数据可以减 少缓存的数据量,但是进行页面合并渲染时就要先解压,然后再压缩完整的页面数据输出给 用户;如果缓存未压缩的静态数据,这样不用解压静态数据,但是会增加缓存容量。

四、池化技术

开发过程中会用到很多的连接池,像是数据库连接池、HTTP 连接池、Redis 连接池等等。而连接池的管理是连接池设计的核心

1.连接池

(1)连接池管理的关键点

数据库连接池有两个最重要的配置:最小连接数和最大连接数,它们控制着从连接池中获取连接的流程:

  • 如果当前连接数小于最小连接数,则创建新的连接处理数据库请求;

  • 如果连接池中有空闲连接则复用空闲连接;

  • 如果空闲池中没有连接并且当前连接数小于最大连接数,则创建新的连接处理请求;

  • 如果当前连接数已经大于等于最大连接数,则按照配置中设定的时间(C3P0 的连接池配 置是 checkoutTimeout)等待旧的连接可用;

  • 如果等待超过了这个设定时间则向用户抛出错误。

在这里,需要注意池子中连接的维护问题,有的连接虽然还存在,但有的时候会有故障:

  • 数据库的域名对应的 IP 发生了变更,池子的连接还是使用旧的 IP,当旧的 IP 下的数据 库服务关闭后,再使用这个连接查询就会发生错误;

  • MySQL 有个参数是“wait_timeout”,控制着当数据库连接闲置多长时间后,数据库会 主动的关闭这条连接。这个机制对于数据库使用方是无感知的,所以当使用这个被关闭 的连接时就会发生错误。 有以下解决方案

    • 启动一个线程来定期检测连接池中的连接是否可用,比如使用连接发送“select 1”的命 令给数据库看是否会抛出异常,如果抛出异常则将这个连接从连接池中移除,并且尝试关闭。目前 C3P0 连接池可以采用这种方式来检测连接是否可用。

    • 在获取到连接之后,先校验连接是否可用,如果可用才会执行 SQL 语句。比如 DBCP 连 接池的 testOnBorrow 配置项,就是控制是否开启这个验证。这种方式在获取连接时会引 入多余的开销,在线上系统中还是尽量不要开启,在测试服务上可以使用。

(2)httpclient连接池设置

HttpConnectionManager httpConnectionManager = new MultiThreadedHttpConnectionManager();HttpConnectionManagerParams params = httpConnectionManager.getParams(); params.setConnectionTimeout(5000); params.setSoTimeout(20000);        params.setDefaultMaxConnectionsPerHost(32);//每个host路由的默认最大连接        params.setMaxTotalConnections(256);//qps*建立连接时间*预留时间(一般是1.7)       

(3)为什么不用IO多路复用

    DB 访问一般采用连接池这种现象是生态造成的。历史上的 BIO + 连接池的做法经过多年的发展,已经解决了主要的问题。在 Java 的大环境下,这个方案是非常靠谱的,成熟的。而基于 IO 多路复用的方式尽管在性能上可能有优势,但是其对整个程序的代码结构要求过多,过于复杂。当然,如果有特定的需要,希望使用 IO 多路复用管理 DB 连接,是完全可行的。

(4)数据库连接为什么费资源

     MySQL 的通信协议是基于 TCP 传输协议的,所以需要经过三次握手和四次挥手

2.用线程池预先创建线程

(1)线程池简介

    JDK 1.5 中引入的 ThreadPoolExecutor 就是一种线程池的实现,它有两个重要 的参数:coreThreadCount 和 maxThreadCount

  • 如果线程池中的线程数少于 coreThreadCount 时,处理新的任务时会创建新的线程;如果线程数大于 coreThreadCount 则把任务丢到一个队列里面,由当前空闲的线程执 行;

  • 当队列中的任务堆积满了的时候,则继续创建线程,直到达到 maxThreadCount;当线程数达到 maxTheadCount 时还有新的任务提交,那么我们就不得不将它们丢弃 了。

图片

(2)线程池设置

最佳线程数目 = ((线程等待时间+线程CPU时间)/线程CPU时间 )* CPU数目

比如平均每个线程CPU运行时间为0.5s,而线程等待时间(非CPU运行时间,比如IO)为1.5s,CPU核心数为8,那么根据上面这个公式估算得到:((0.5+1.5)/0.5)*8=32。这个公式进一步转化为:

最佳线程数目 = (线程等待时间与线程CPU时间之比 + 1)* CPU数目

线程等待时间所占比例越高,需要越多线程。线程CPU时间所占比例越高,需要越少线程。

3.什么时候考虑使用池化

当遇到下面的场景,就可以考虑使用池化来增加系统性能:

  • 对象的创建或者销毁,需要耗费较多的系统资源;

  • 对象的创建或者销毁,耗时长,需要繁杂的操作和较长时间的等待;

  • 对象创建后,通过一些状态重置,可被反复使用。

将对象池化之后,只是开启了第一步优化。要想达到最优性能,就不得不调整池的一些关键参数,合理的池大小加上合理的超时时间,就可以让池发挥更大的价值。和缓存的命中率类似,对池的监控也是非常重要的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1207006.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

锂价疲软,市场需求持续低迷,赣锋锂业在短期内将继续面临痛苦

来源&#xff1a;猛兽财经 作者&#xff1a;猛兽财经 公司介绍 在赣锋锂业(01772)(002460)网站上&#xff0c;赣锋锂业称自己是一家拥有“中国第一”和“世界最大锂金属生产商”的“锂化合物产能”公司。 根据其2022财年年度报告&#xff0c;该公司最近一个财年的收入有84%和1…

基于LDPC编译码和FP-MAP球形检测算法的协作MIMO系统误码率matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 4.1 LDPC码 4.1 Fincke-Pohst-MAP球形检测算法 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 matlab2017b 3.部分核心程序 .........................................…

SpringBoot文件在线预览实现

kkFileView - 在线文件预览&#xff0c;一款成熟且开源的文件文档在线预览项目解决方案。 详细wiki文档&#xff1a;https://gitee.com/kekingcn/file-online-preview/wikis/pages 中文文档&#xff1a;https://gitee.com/kekingcn/file-online-preview/blob/master/README.md…

关于start-burp抓包夜神-系统证书导入

1、开启开发中模式 2、开启USB调试 3、开启端口监听并下载start-burp证书 4、证书在线格式转换 根据该网站【在线DER格式转pem CER格式转pem CRT格式转PEM证书格式--查错网】也可以搜索其它在线转换网站进行操作 新建一个文本文件重名为【9a5ba575.0】&#xff0c;将转换的内…

【万字长文】前端性能优化实践 | 京东云技术团队

一、引言 从一个假死页面引发的思考&#xff1a; 作为前端开发&#xff0c;除了要攻克页面难点&#xff0c;也要有更深的自我目标&#xff0c;性能优化是自我提升中很重要的一环&#xff1b; 在前端开发中&#xff0c;会偶遇到页面假死的现象&#xff0c; 是因为当js有大量计算…

【工程部署】在RK3588上部署OCR(文字检测识别)(DBNet+CRNN)

硬件平台&#xff1a; 1、firefly安装Ubuntu系统的RK3588&#xff1b; 2、安装Windows系统的电脑一台&#xff0c;其上安装Ubuntu18.04系统虚拟机。 参考手册&#xff1a;《00-Rockchip_RKNPU_User_Guide_RKNN_API_V1.3.0_CN》 《RKNN Toolkit Lite2 用户使用指南》 1、文…

SAP Debug时如何跳过(不执行)某些代码

Debug时如何跳过(不执行)某些代码 在DEBUG界面, 首先将光标定位到想跳至的代码行, 然后从右键菜单中选择Goto Statement, 或者从Debugger菜单中选择Goto Statement:&#xff08;效果相同&#xff09; 然后光标就会定位到想跳至的代码行 执行结果如下: 结果是000的原因是&#…

日历应用程序 BusyCal mac中文版软件特点

BusyCal mac是一款日历应用程序&#xff0c;它可以帮助用户轻松地管理日程安排、事件提醒、会议安排等。BusyCal 支持 macOS 和 iOS 平台&#xff0c;并且可以与 iCloud、Google 日历、Exchange 等多种日历服务进行同步。 BusyCal mac软件特点 强大的日历功能&#xff1a;Busy…

SQL练习01

1.游戏玩法分析 SQL Create table If Not Exists Activity (player_id int, device_id int, event_date date, games_played int); Truncate table Activity; insert into Activity (player_id, device_id, event_date, games_played) values (1, 2, 2016-03-01, 5); insert …

【Python3】【力扣题】268. 丢失的数字

【力扣题】题目描述&#xff1a; 【Python3】代码&#xff1a; 1、解题思路&#xff1a;哈希。元素去重&#xff0c;依次判断是否在0-n内&#xff0c;没有则返回。 知识点&#xff1a;set(...)&#xff1a;转为集合&#xff0c;集合中的元素不重复。 class Solution:def mis…

6.6二叉树的最大深度(LC104-E)、N叉树的最大深度(LC559-E)

二叉树的最大深度&#xff1a; 二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。 二叉树的最大深度二叉树的高度 算法&#xff1a; 这道题既可以求深度&#xff0c;也可以直接求高度。不过高度和深度用的遍历方式不同。 二叉树写代码之前要确定遍历顺序…

基于Java实现的轻量级私有云平台,让企业拥有自己的云平台

一、开源项目简介 KVM Cloud 是一款基于Java实现的轻量级私有云平台&#xff0c;旨在帮助中小企业快速实现计算、存储、网络等资源的管理&#xff0c;让企业拥有自己的云平台。 二、开源协议 使用Apache-2.0开源协议 三、界面展示 四、功能概述 KVM Cloud 是一款基于Java实…

JAVA基础语法编程详解---三目运算符

6.判断体重指数 题目描述 - 描述 体重指数 体重 (kg) / ( 身高 (m) 身高 (m) )&#xff0c;小于18.5属于偏瘦&#xff0c;介于18.5和20.9之间&#xff08;左闭右开&#xff09;属于苗条&#xff0c;介于20.9和24.9之间&#xff08;左闭右闭&#xff09;属于适中&#xff0c;…

python入口文件方便在其它目录也能执行

dir_path os.path.dirname(os.path.realpath(__file__)) parent_dir_path os.path.abspath(os.path.join(dir_path, os.pardir)) sys.path.insert(0, parent_dir_path)

优秀智慧园区案例 - 新华三未来工厂制造园,园区业务创新及零碳升级

目录 一、新华三未来工厂制造园建设背景 二、未来工厂制造园总体设计思路 三、未来工厂制造园建设内容 四、关键技术及创新点 五、应用效益与推广 关键词&#xff1a;智慧园区解决方案&#xff0c;智慧园区建设总体方案&#xff0c;智慧园区建设规划方案&#xff0c;智慧园…

J. Chem. Theory Comput. | AI驱动的柔性蛋白-小分子复合物建模

今天为大家介绍的是来自陈语谦教授团队发表在Journal of Chemical Theory and Computation的论文&#xff0c;“Equivariant Flexible Modeling of the Protein−Ligand Binding Pose with Geometric Deep Learning”&#xff0c;博士生董铁君为第一作者。该文提出了一种新的AI…

【nlp】2.2 传统RNN模型

传统RNN模型 1 传统RNN模型1.1 RNN结构分析1.2 使用Pytorch构建RNN模型1.3 传统RNN优缺点1 传统RNN模型 1.1 RNN结构分析 结构解释图: 内部结构分析: 我们把目光集中在中间的方块部分, 它的输入有两部分, 分别是h(t-1)以及x(t), 代表上一时间步的隐层输出, 以及此时间步的…

tcpdump wireshark简单使用

tcpdump工作原理 tcpdump 是 Linux 系统中非常有用的网络工具&#xff0c;运行在用户态&#xff0c;本质上是通过调用 libpcap 库的各种 api 来实现数据包的抓取功能&#xff0c;利用内核中的 AF_PACKET 套接字&#xff0c;抓取网络接口中传输的网络包。查 看 tcpdump 的 手册…

「Verilog学习笔记」用优先编码器①实现键盘编码电路

专栏前言 本专栏的内容主要是记录本人学习Verilog过程中的一些知识点&#xff0c;刷题网站用的是牛客网 分析 用此编码器实现键盘的编码电路。 注意&#xff1a;编码器的输出是低电平有效&#xff0c;而键盘编码电路输出的是正常的8421BCD码&#xff0c;是高电平有效。因此将编…