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

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

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

一、高性能浏览器访问

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.什么时候考虑使用池化

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

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

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

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

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

vue-baidu-map实现在地图上选择范围并解决相关问题

vue-baidu-map实现在地图上选择范围并解决相关问题 实现地图上选择不规则范围实现功能遇到的问题1、覆盖物多边形怎么才能盖住覆盖物点2、遇到其他问题 实现地图上选择不规则范围 这个功能比较简单&#xff0c;只需要使用vue-baidu-map插件的覆盖物多边形功能就行了。直接看文…

重生奇迹mu卓越哪里掉的最多

项链篇 [火之项链] 1.地下城:(地狱猎犬怪,骷髅战士,地狱蜘蛛,死灵巫师,毒牛怪,暗黑骑士) 2.失落之塔:(鬼魂,剧毒鬼魂) 3.亚特兰蒂斯:(小巴哈姆特,死亡美人鱼,蓝翼海怪) [雷之项链] 1.地下城:(毒牛怪,暗黑骑士,魔鬼戈登) 2.失落之塔:(鬼魂,剧毒鬼魂,诅咒巫师,牛魔王,恶魔…

二叉树oj题总结

1.检查两颗树是否相同 https://leetcode.cn/problems/same-tree/ 分成子问题和结束条件 &#xff0c;这里用前序的思想解题&#xff08;先判断根&#xff0c;再左右子树&#xff09;&#xff0c;不然会很浪费时间。假如左右相等&#xff0c;最后根不同&#xff0c;白白比较了 …

员工持股平台模式有哪几种?

员工持股平台模式 目前在现有的市场环境下持股平台的模式主要有公司型的持股平台以及有限合伙企业的持股平台。 &#xff08;一&#xff09;公司型员工持股平台 设立公司型的员工持股平台的唯一目的是为了让平台公司受让母公司的股权&#xff0c;从而实现员工间接持有母公司股权…

自动定量包装机市场研究: 2023年行业发展潜力分析

中国包装机械业取得了快速发展&#xff0c;但也出现了一些低水平重复建设现象。据有关资料显示&#xff0c;与工业发达国家相比&#xff0c;中国食品和包装机械产品品种缺乏25%-30%&#xff0c;技术水平落后15-25年。我国包装专用设备制造行业规模以上企业有319家&#xff0c;主…

宁盾统一身份中台助力某集团公司实现统一身份认证和管理(如泛微OA、微软AD)

某集团公司是一家以钢铁为主业&#xff0c;涉足互联网金融、文化健康、智慧城市、现代物流等多领域的大型现代化企业集团。创业发展已有三十余年&#xff0c;拥有员工人数超万人&#xff0c;为了提升管理效率&#xff0c;同时实现国产化创新和数字化转型&#xff0c;公司采用了…

[MySQL] MySQL复合查询(多表查询、子查询)

前面我们学习了MySQL简单的单表查询。但是我们发现&#xff0c;在很多情况下单表查询并不能很好的满足我们的查询需求。本篇文章会重点讲解MySQL中的多表查询、子查询和一些复杂查询。希望本篇文章会对你有所帮助。 文章目录 一、基本查询回顾 二、多表查询 2、1 笛卡尔积 2、2…

JVM 命令行监控及诊断工具

面试题 你使用过Java虚拟机性能监控和故障处理工具吗&#xff1f;&#xff08;美图&#xff09; 怎么打出线程栈信息。&#xff08;字节跳动&#xff09; JVM诊断调优工具用过哪些&#xff1f; (京东) 怎么获取 Java 程序使用的内存&#xff1f;堆使用…

Linux学习教程(第十四章 Linux系统服务管理)一

第十四章 Linux系统服务管理&#xff08;一&#xff09; 什么是系统服务&#xff1f;服务是在后台运行的应用程序&#xff0c;并且可以提供一些本地系统或网络的功能。 那么&#xff0c;Linux 中常见的服务有那些&#xff0c;这些服务怎么分类&#xff0c;服务如何启动&#x…

diffusers pipeline拆解:理解pipelines、models和schedulers

diffusers pipeline拆解&#xff1a;理解pipelines、models和schedulers 翻译自&#xff1a;https://huggingface.co/docs/diffusers/using-diffusers/write_own_pipeline v0.24.0 diffusers 设计初衷就是作为一个简单且易用的工具包&#xff0c;来帮助你在自己的使用场景中构建…

四十、Saga模式

目录 一、定义 二、流程 三、优点 四、缺点 五、四种模式的对比 一、定义 Saga模式是一种用于处理复杂异步操作流的模式&#xff0c;通常用于React/Redux的应用程序中。在这种模式中&#xff0c;业务逻辑被分成多个离散步骤&#xff0c;每个步骤都是一个Generator函数&…

AUTOSAR CP Port Driver简介

Port Driver 1 背景2 基于 EB 及 TC39X 配置3 Port API 使用1 背景 Port driver 在 AUTOSAR 中是一个比较冷门的模块,基本上在 MCAL 层级,关注的人也少,他由不像其他模块那样通用型比较强,Port 在每种内核的 MCU 的配置都有区别,甚至有些芯片直接没有 Port 模块,使用其他方…

企业级高级美颜美妆SDK解决方案

人们对于美的追求已经不仅仅局限于现实世界&#xff0c;更延伸到了虚拟世界。为了满足这一需求&#xff0c;美摄科技全新开发了一款高级美颜美妆SDK&#xff0c;为企业提供了一站式的美颜美妆解决方案。 这款全新的美颜美妆SDK&#xff0c;是我们对美颜技术的一次全面升级。它…

Java实现布隆过滤器

一、概述 布隆过滤器本质上是一个很长的二进制数组&#xff0c;主要用来判断一个数据存不存在数组里&#xff0c;如果存在就用1表示&#xff0c;不存在用0表示&#xff0c;它的优点是空间效率和查询时间都比一般的算法要好的多&#xff0c;缺点是有一定的误识别率和删除困难。 …

教你pycharm运行Django第一个项目

文章目录 前言搭建Django:1.新建Django项目&#xff1a;2.为Django项目指定远程中创建的虚拟环境下的python解释器&#xff1a;3.配置ubuntu的端口转发&#xff08;添加端口号为1234的端口&#xff09;&#xff1a;关于Python技术储备一、Python所有方向的学习路线二、Python基…

Nacos源码解读07——集群数据同步

Distro协议背景 Distro 协议是 Nacos 社区自研的⼀种 AP 分布式协议&#xff0c;是面向临时实例设计的⼀种分布式协议&#xff0c; 其保证了在某些 Nacos 节点宕机后&#xff0c;整个临时实例处理系统依旧可以正常工作。作为⼀种有状态 的中间件应用的内嵌协议&#xff0c;Dis…

【软件推荐】文本转语音,语音转wav,导入ue5

文字转语音 在线免费文字转语音 - TTSMaker官网 | 马克配音https://ttsmaker.cn/ 文件转换器 语音转wav Convertio — 文件转换器https://convertio.co/zh/

[英语学习][10][Word Power Made Easy]的精读与翻译优化

[序言] 下面这段话, 译者翻译没有太大问题, 就是某些单词上, 跟他理解得不一样. 另外还有一个关键的定语从句, 我认为译者理解不到位, 导致翻译不够通顺. [英文学习的目标] 提升自身的英语水平, 对日后编程技能的提升有很大帮助. 希望大家这次能学到东西, 同时加入我的社区讨…

静态HTTP和动态HTTP的混合使用:最佳实践

在当今的互联网环境中&#xff0c;静态HTTP和动态HTTP各有其优势和局限。静态HTTP具有速度快、安全性高和易于维护的特点&#xff0c;而动态HTTP则能够实现动态交互和处理大量动态数据。为了充分利用两者的优势&#xff0c;越来越多的网站开始采用静态HTTP和动态HTTP混合使用的…

两个分数相加。

输入两个分数&#xff0c;例如3/41/2&#xff0c;输出3/41/25/4。 运行程序时&#xff0c;如下图所示&#xff1a; 输入样例1: 1/61/2输出样例2: 1/61/22/3 #include<stdio.h> int gcd(int a,int b) //求最大公约数&#xff08;Greatest Common Divisor&…