网站建设费用属于业务宣传费吗网络系统集成
web/
2025/10/5 3:26:08/
文章来源:
网站建设费用属于业务宣传费吗,网络系统集成,中国建筑一局,网站上人家做的简历1 引入对JDBC的理解-1 一般来说#xff0c;Java应用程序访问数据库的过程是#xff1a;
装载数据库驱动程序#xff1b;通过jdbc建立数据库连接#xff1b;访问数据库#xff0c;执行sql语句#xff1b;断开数据库连接。
Public void FindAllUsers(){//1、装载sqlserve…1 引入对JDBC的理解-1 一般来说Java应用程序访问数据库的过程是
装载数据库驱动程序通过jdbc建立数据库连接访问数据库执行sql语句断开数据库连接。
Public void FindAllUsers(){//1、装载sqlserver驱动对象DriverManager.registerDriver(new SQLServerDriver()); //2、通过JDBC建立数据库连接Connection con DriverManager.getConnection(jdbc:sqlserver://192.168.2.6:1433;DatabaseNamecustomer, sa, 123); //3、创建状态会话Statement state con.createStatement(); //4、查询数据库并返回结果ResultSet result state.executeQuery(select * from users); //5、输出查询结果while(result.next()){System.out.println(result.getString(email));} //6、断开数据库连接result.close();state.close();con.close();
}程序开发过程中存在很多问题 首先每一次web请求都要建立一次数据库连接。建立连接是一个费时的活动每次都得花费0.05s1s的时间而且系统还要分配内存资源。 这个时间对于一次或几次web请求数据库操作或许感觉不出系统有多大的开销。可是对于现在的web应用尤其是大型电子商务网站同时有几百人甚至几千人在线是很正常的事。
在这种情况下频繁的进行数据库连接操作势必占用很多的系统资源网站的响应速度必定下降严重的甚至会造成服务器的崩溃。 不是危言耸听这就是制约某些电子商务网站发展的技术瓶颈问题。其次对于每一次数据库连接使用完后都得断开。 但是如果程序出现异常而未能关闭将会导致数据库系统中的内存泄漏最终将不得不重启数据库。 还有这种开发不能控制被创建的连接对象数系统资源会被毫无顾及的分配出去如连接过多也可能导致内存泄漏服务器崩溃。
上述的用户查询案例如果同时有1000人访问就会不断的有数据库连接、断开操作 通过上面的分析我们可以看出来“数据库连接”是一种稀缺的资源为了保障网站的正常使用应该对其进行妥善管理。其实我们查询完数据库后如果不关闭连接而是暂时存放起来当别人使用时把这个连接给他们使用就避免了一次建立数据库连接和断开的操作时间消耗。原理如下 由上面的分析可以看出问题的根源就在于对数据库连接资源的低效管理。我们知道对于共享资源有一个很著名的设计模式资源池resource pool。该模式正是为了解决资源的频繁分配、释放所造成的问题。 为解决上述问题可以采用数据库连接池技术。
数据库连接池的基本思想就是为数据库连接建立一个“缓冲池”。预先在缓冲池中放入一定数量的连接当需要建立数据库连接时只需从“缓冲池”中取出一个使用完毕之后再放回去。
我们可以通过设定连接池最大连接数来防止系统无尽的与数据库连接。更为重要的是我们可以通过连接池的管理机制——监视数据库的连接的数量、使用情况为系统开发、测试及性能调整提供依据。
我们自己尝试开发一个连接池来为上面的查询业务提供数据库连接服务
编写class 实现DataSource 接口在class构造器一次性创建10个连接将连接保存LinkedList中实现getConnection 从 LinkedList中返回一个连接提供将连接放回连接池中方法
public class MyDataSource implements DataSource {//链表 --- 实现栈结构privateLinkedListConnection dataSources new LinkedListConnection();//初始化连接数量publicMyDataSource() {//一次性创建10个连接for(int i 0; i 10; i) {try {//1、装载sqlserver驱动对象DriverManager.registerDriver(new SQLServerDriver());//2、通过JDBC建立数据库连接Connection con DriverManager.getConnection(jdbc:sqlserver://192.168.2.6:1433;DatabaseNamecustomer, sa, 123);//3、将连接加入连接池中dataSources.add(con);} catch (Exception e) {e.printStackTrace();}}}OverridepublicConnection getConnection() throws SQLException {//取出连接池中一个连接finalConnection conn dataSources.removeFirst(); // 删除第一个连接返回return conn;}//将连接放回连接池publicvoid releaseConnection(Connection conn) {dataSources.add(conn);}}//查询所有用户Public void FindAllUsers(){//1、使用连接池建立数据库连接MyDataSource dataSource new MyDataSource();Connection conn dataSource.getConnection(); //2、创建状态Statement state con.createStatement(); //3、查询数据库并返回结果ResultSet result state.executeQuery(select * from users); //4、输出查询结果while(result.next()){System.out.println(result.getString(email));} //5、断开数据库连接result.close();state.close();//6、归还数据库连接给连接池dataSource.releaseConnection(conn);}这就是数据库连接池的原理它大大提供了数据库连接的利用率减小了内存吞吐的开销。我们在开发过程中就不需要再关心数据库连接的问题自然有数据库连接池帮助我们处理这回放心了吧。但连接池需要考虑的问题不仅仅如此下面我们就看看还有哪些问题需要考虑。
1、并发问题 为了使连接管理服务具有最大的通用性必须考虑多线程环境即并发问题。这个问题相对比较好解决因为java语言自身提供了对并发管理的支持使用synchronized关键字即可确保线程是同步的。使用方法为直接在类方法前面加上synchronized关键字如
public synchronized connection getconnection2、多数据库服务器和多用户 对于大型的企业级应用常常需要同时连接不同的数据库如连接oracle和sybase。如何连接不同的数据库呢我们采用的策略是
设计一个符合单例模式的连接池管理类在连接池管理类的唯一实例被创建时读取一个资源文件其中资源文件中存放着多个数据库的url地址等信息。根据资源文件提供的信息创建多个连接池类的实例每一个实例都是一个特定数据库的连接池。连接池管理类实例为每个连接池实例取一个名字通过不同的名字来管理不同的连接池。
对于同一个数据库有多个用户使用不同的名称和密码访问的情况也可以通过资源文件处理即在资源文件中设置多个具有相同url地址但具有不同用户名和密码的数据库连接信息。
3、事务处理 我们知道事务具有原子性此时要求对数据库的操作符合“all-all-nothing”原则即对于一组sql语句要么全做要么全不做。在java语言中connection类本身提供了对事务的支持可以通过设置connection的autocommit属性为false 然后显式的调用commit或rollback方法来实现。
但要高效的进行connection复用就必须提供相应的事务支持机制。可采用每一个事务独占一个连接来实现这种方法可以大大降低事务管理的复杂性。
4、连接池的分配与释放 连接池的分配与释放对系统的性能有很大的影响。合理的分配与释放可以提高连接的复用度从而降低建立新连接的开销同时还可以加快用户的访问速度。
对于连接的管理可使用空闲池。即把已经创建但尚未分配出去的连接按创建时间存放到一个空闲池中。
每当用户请求一个连接时系统首先检查空闲池内有没有空闲连接。如果有就把建立时间最长通过容器的顺序存放实现的那个连接分配给他实际是先做连接是否有效的判断如果可用就分配给用户如不可用就把这个连接从空闲池删掉重新检测空闲池是否还有连接
如果没有则检查当前所开连接池是否达到连接池所允许的最大连接数maxconn如果没有达到就新建一个连接如果已经达到就等待一定的时间timeout。
如果在等待的时间内有连接被释放出来就可以把这个连接分配给等待的用户如果等待时间超过预定时间timeout 则返回空值null。
系统对已经分配出去正在使用的连接只做计数当使用完后再返还给空闲池。对于空闲连接的状态可开辟专门的线程定时检测这样会花费一定的系统开销但可以保证较快的响应速度。也可采取不开辟专门线程只是在分配前检测的方法。
5、连接池的配置与维护 连接池中到底应该放置多少连接才能使系统的性能最佳系统可采取设置最小连接数minconn和最大连接数maxconn来控制连接池中的连接。
最小连接数是系统启动时连接池所创建的连接数。如果创建过多则系统启动就慢但创建后系统的响应速度会很快如果创建过少则系统启动的很快响应起来却慢。
最大连接数是连接池中允许连接的最大数目具体设置多少要看系统的访问量可通过反复测试找到最佳点。如何确保连接池中的最小连接数呢有动态和静态两种策略。
动态即每隔一定时间就对连接池进行检测如果发现连接数量小于最小连接数则补充相应数量的新连接以保证连接池的正常运转。静态是发现空闲连接不够时再去检查。
实际开发中有成熟的开源连接池供我们使用: 理解了连接池的原理就可以了没有必要什么都从头写一遍那样会花费很多时间并且性能及稳定性也不一定满足要求。事实上已经存在很多流行的性能优良的第三方数据库连接池jar包供我们使用。如
Apache commons-dbcp
c3p0
Druid
HikariCP其中c3p0已经很久没有更新了DBCP更新速度很慢基本处于不活跃状态。而Druid和HikariCP处于活跃状态的更新中。
2 引入对JDBC的理解-2
数据库应用在许多软件系统中经常用到是开发中大型系统不可缺少的辅助。 但如果对数据库资源没有很好地管理(如没有及时回收数据库的游标(ResultSet)、Statement、连接 (Connection)等资源)往往会直接导致系统的稳定。 这类不稳定因素不单单由数据库或者系统本身一方引起只有系统正式使用后随着流量、用户的增加才会逐步显露。
对于一个简单的数据库应用由于对于数据库的访问不是很频繁。这时可以简单地在需要访问数据库时就新创建一个连接用完后就关闭它这样做也不会带来什么明显的性能上的开销。 但是对于一个复杂的数据库应用情况就完全不同了。频繁的建立、关闭连接会极大的减低系统的性能因为对于连接的使用成了系统性能的瓶颈。
连接复用 通过建立一个数据库连接池以及一套连接使用管理策略使得一个数据库连接可以得到高效、安全的复用避免了数据库连接频繁建立、关闭的开销。 对于共享资源有一个很著名的设计模式资源池。该模式正是为了解决资源频繁分配、释放所造成的问题的。 把该模式应用到数据库连接管理领域就是建立一个数据库连接池提供一套高效的连接分配、使用策略最终目标是实现连接的高效、安全的复用。
数据库连接池的基本原理 在内部对象池中维护一定数量的数据库连接并对外暴露数据库连接获取和返回方法。 如外部使用者可通过 getConnection 方法获取连接使用完毕后再通过 releaseConnection 方法将连接返回注意此时连接并没有关闭而是由连接池管理器回收并为下一次使用做好准备。
数据库连接池技术带来的优势
1 资源重用 由于数据库连接得到重用避免了频繁创建、释放连接引起的大量性能开销。在减少系统消耗的基础上另一方面也增进了系统运行环境的平稳性减少内存碎片以及数据库临时进程/线程的数量。
2 更快的系统响应速度 数据库连接池在初始化过程中往往已经创建了若干数据库连接置于池中备用。此时连接的初始化工作均已完成。 对于业务请求处理而言直接利用现有可用连接避免了数据库连接初始化和释放过程的时间开销从而缩减了系统整体响应时间。
3 新的资源分配手段 对于多应用共享同一数据库的系统而言可在应用层通过数据库连接的配置实现数据库连接池技术如果设计中还没有考虑到连接池的应用 那么…….快在设计文档中加上这部分的内容吧。某一应用最大可用数据库连接数的限制避免某一应用独占所有数据库资源。
4 统一的连接管理避免数据库连接泄漏 在较为完备的数据库连接池实现中可根据预先的连接占用超时设定强制收回被占用连接。从而避免了常规数据库连接操作中可能出现的资源泄漏。
一个最小化的数据库连接池实现 在基于Java开发的系统中JDBC是程序员和数据库打交道的主要途径提供了完备的数据库操作方法接口。 但考虑到规范的适用性JDBC只提供了最直接的数据库操作规范对数据库资源管理如对物理连接的管理及缓冲期望第三方应用服务器(Application Server)的提供。
应用在获取数据库连接connection时需要指定使用哪种类型的Driver在获得特定的连接后可按照固定的接口操作不同类型的数据库 如: 分别获取Statement、执行SQL获得ResultSet等如下面的例子 : Class.forName(com.mysql.jdbc.Driver);Connection conn DriverManager.getConnection(url, username, password);Statement stmt conn.createStatement();String sql1 update user set age 100 where id 1;int rows1 stmt.executeUpdate(sql1);stmt.close();conn.close();在完成数据操作后一定要关闭所有涉及到的数据库资源。这虽然对应用程序的逻辑没有任何影响但是关键的操作。 上面是个简单的例子如果搀和众多的if-else、exception资源的管理也难免百密一疏Java系统也同样会面临崩溃的恶运。 所以数据库资源的管理依赖于应用系统本身是不安全、不稳定的一种隐患。
JDBC连接池 在标准JDBC对应用的接口中并没有提供资源的管理方法。所以缺省的资源管理由应用自己负责。虽然在JDBC规范中多次提及资源的关闭/回收及其他的合理运用。 但最稳妥的方式还是为应用提供有效的管理手段。 所以JDBC为第三方应用服务器Application Server提供了一个由数据库厂家实现的管理标准接口连接缓冲(connection pooling)。 引入了连接池( Connection Pool )的概念 也就是以缓冲池的机制管理数据库的资源。
JDBC最常用的资源有三类: Connection数据库连接。 Statement会话。 ResultSet结果集游标。 数据库连接池的实现及原理: 这是一种“爷—父—子”的关系对Connection的管理就是对数据库资源的管理。举个例子: 如果想确定某个数据库连接(Connection)是否超时则需要确定其所有的子Statement是否超时同样需要确定所有相关的 ResultSet是否超时在关闭Connection前需要关闭所有相关的Statement和ResultSet。因此连接池(Connection Pool)所起到的作用不仅仅简单地管理Connection还涉及到 Statement和ResultSet。
连接池(ConnectionPool)与资源管理: ConnectionPool以缓冲池的机制在一定数量上限范围内控制管理ConnectionStatement和ResultSet。任何数据库的资源是有限的如果被耗尽则无法获得更多的数据服务。
在大多数情况下资源的耗尽不是由于应用的正常负载过高而是程序的原因。在实际工作中数据资源往往是瓶颈资源不同的应用都会访问同一数据源。其中某个应用耗尽了数据库资源后意味其他的应用也无法正常运行。
因此ConnectionPool的第一个任务是限制每个应用或系统可以拥有的最大资源也就是确定连接池的大小(PoolSize)。
ConnectionPool的第二个任务在连接池的大小(PoolSize)范围内最大限度地使用资源缩短数据库访问的使用周期。
许多数据库中连接Connection并不是资源的最小单元控制Statement资源比Connection更重要。以Oracle为例 每申请一个数据库连接Connection会在物理网络如 TCP/IP网络上建立一个用于通讯的连接在此连接上还可以申请一定数量的Statement。同一连接可提供的活跃Statement数量可以达到几百。 在节约网络资源的同时缩短了每次会话周期物理连接的建立是个费时的操作。 但在一般的应用中多数按照上例代码操作这样有10个程序调用则会产生10次物理连接每个Statement单独占用一个物理连接这是极大的资源浪费。
ConnectionPool可以解决这个问题让几十、几百个Statement只占用同一个物理连接 发挥数据库原有的优点。通过ConnectionPool对资源的有效管理应用可以获得的Statement总数到达 并发物理连接数×每个连接可提供的Statement数量
例如某种数据库可同时建立的物理连接数为 200个每个连接可同时提供250个Statement那么ConnectionPool最终为应用提供的并发Statement总数为: 200 × 250 50,000个。这是个并发数字很少有系统会突破这个量级。所以指出资源的耗尽与应用程序直接管理有关。
简单JDBC连接池的实现 在JDBC规范中应用通过驱动接口Driver Interface直接获取数据库的资源。为了有效、合理地管理资源在应用与JDBC Driver之间增加了连接池: Snap-ConnectionPool。 并且通过面向对象的机制使连接池的大部分操作是透明的。
参见下图Snap-ConnectionPool的体系 图中所示通过实现JDBC的部分资源对象接口( Connection, Statement, ResultSet ) 在 Snap-ConnectionPool内部分别产生三种逻辑资源对象: PooledConnection, PooledStatement和 PooledResultSet。它们也是连接池主要的管理操作对象并且继承了JDBC中相应的从属关系。这样的体系有以下几个特点
透明性 在不改变应用原有的使用JDBC驱动接口的前提下提供资源管理的服务。 资源封装 复杂的资源管理被封装在 Snap-ConnectionPool内部不需要应用系统过多的干涉。管理操作的可靠性、安全性由连接池保证。应用的干涉如主动关闭资源只起到优化系统性能的作用遗漏操作不会带来负面影响。 资源合理应用 按照JDBC中资源的从属关系Snap-ConnectionPool不仅对Connection进行缓冲处理对Statement也有相应的机制处理。合理运用Connection和Statement之间的关系可以更大限度地使用资源。所以Snap-ConnectionPool封装了Connection资源 通过内部管理PooledConnection为应用系统提供更多的Statement 资源。 资源连锁管理 Snap-ConnectionPool包含的三种逻辑对象继承了JDBC中相应对象之间的从属关系。在内部管理中也依照从属关系进行连锁管理。例如判断一个Connection是否超时需要根据所包含的Statement是否活跃判断Statement也要根据 ResultSet的活跃程度。
连接池集中管理ConnectionManager ConnectionPool是Snap-ConnectionPool的连接池对象。在Snap-ConnectionPool内部可以指定多个不同的连接池(ConnectionPool)为应用服务。ConnectionManager管理所有的连接池每个连接池以不同的名称区别。通过配置文件适应不同的数据库种类。如下图所示 通过ConnectionManager可以同时管理多个不同的连接池提供通一的管理界面。在应用系统中通过 ConnectionManager和相关的配置文件可以将凌乱散落在各自应用程序中的数据库配置信息包括数据库名、用户、密码等信息集中在一个文件中。便于系统的维护工作。
连接池使用范例 对上栗代码的标准JDBC的使用范例改为使用连接池结果如下 import java.sql.*;import net.snapbug.util.dbtool.*;…ConnectionPool dbConn ConnectionManager .getConnectionPool(testOracle );Statement st dbConn.createStatement();ResultSet rs st.executeQuery(“select * from demo_table” );…some data source operation in herers.close();st.close();在例子中Snap-ConnectionPool封装了应用对Connection的管理。只要改变JDBC获取Connection的方法——获取连接池(ConnectionPool)(粗体部分)其他的数据操作都可以不做修改。
按照这样的方式Snap-ConnectionPool可帮助应用有效地管理数据库资源。 如果应用忽视了最后资源的释放: rs.close() 和 st.close()连接池会通过超时(time-out)机制自动回收。
小结 无论是Snap-ConnectionPool还是其他的数据库连接池都应当具备一下基本功能
对源数据库资源的保护充分利用发挥数据库的有效资源简化应用的数据库接口封闭资源管理。对应用遗留资源的自动回收和整理提高资源的再次利用率。在这个前提下应用程序才能投入更多的精力于各自的业务逻辑中数据库资源也不再成为系统的瓶颈。
3 技术经理求求你别再乱改数据库连接池的大小了
基本上来说大部分项目都需要跟数据库做交互那么数据库连接池的大小设置成多大合适呢 一些开发老鸟可能还会告诉你没关系尽量设置的大些比如设置成 200这样数据库性能会高些吞吐量也会大些 你也许会点头称是真的是这样吗看完这篇文章也许会颠覆你的认知哦
可以很直接的说关于数据库连接池大小的设置每个开发者都可能在一环节掉进坑里事实上呢大部分程序员可能都会依靠自己的直觉去设置它的大小设置成 100 思量许久后自顾自想应该差不多吧
不妨意淫一下你手里有个网站并发压力虽然还没到 Facebook 那个级别但是呢也有个1万上下的并发量 也就是说差不多2万左右的 TPS[TPSTransactions Per Second每秒传输的事物处理个数TPS包括一条消息入和一条消息出加上一次用户数据库访问那么问题来了这个网站的数据库连接池应该设置成多大合适呢 其实这个问法本身就是有问题的我们需要反过来问正确问法应该是 “这个网站的数据库连接池应该设置成多小合适呢”
对 Oracle 数据库进行了压力测试模拟 9600 个并发线程来操作数据库每两次数据库操作之间 sleep 550ms注意开始设置的线程池大小为 2048。让我们来看看数据库连接池的大小为 2048 性能测试结果的鬼样子 每个请求要在连接池队列里等待 33ms获得连接之后执行SQL需要耗时77ms, CPU 消耗维持在 95% 左右接下来我们将连接池的大小改小点设置成 1024其他测试参数不变结果咋样 这里获取连接等待时长基本不变但是 SQL 的执行耗时降低了哎呦有长进哦接下来我们再设置小些连接池的大小降低到 96并发数等其他参数不变看看结果如何 每个请求在连接池队列中的平均等待时间为 1ms, SQL 执行耗时为 2ms。我去什么鬼我们没调整任何东西仅仅只是将数据库连接池的大小降低了这样就能把之前平均 100ms 响应时间缩短到了 3ms。吞吐量指数级上升啊 你这也太溜了为啥有这种效果? 我们不妨想一下为啥 Nginx 内部仅仅使用了 4 个线程其性能就大大超越了 100 个进程的 Apache HTTPD 呢 追究其原因的话回想一下计算机科学的基础知识答案其实非常明显。 要知道即使是单核 CPU 的计算机也能“同时”运行着数百个线程。但我们其实都知道这只不过是操作系统快速切换时间片跟我们玩的一个小把戏罢了。 一核 CPU同一时刻只能执行一个线程然后操作系统切换上下文CPU 核心快速调度执行另一个线程的代码不停反复给我们造成了所有进程同时运行假象。 其实在一核 CPU 的机器上顺序执行A和B永远比通过时间分片切换“同时”执行A和B要快其中原因学过操作系统这门课程的童鞋应该很清楚。 一旦线程的数量超过了 CPU 核心的数量再增加线程数系统就只会更慢而不是更快因为这里涉及到上下文切换耗费的额外的性能。 说到这里你应该恍然大悟了 ……
当我们在寻找数据库的性能瓶颈时大致可归为三类 CPU、 磁盘 IO 、网络 IO 也许你会说还有内存这一因素内存的确是需要考虑的但是比起磁盘IO和网络IO稍显微不足道这里就不加了。
假设我们不考虑磁盘 IO 和网络 IO就很好定论了在一个 8 核的服务器上数据库连接数/线程数设置为 8 能够提供最优的性能如果再增加连接数反而会因为上下文切换导致性能下降。
大家都知道数据库通常把数据存储在磁盘上而磁盘呢通常是由一些旋转着的金属碟片和一个装在步进马达上的读写头组成的。 读/写头同一时刻只能出现在一个位置当它需要再次执行读写操作时它必须“寻址”到另外一个位置才能完成任务。 所以呢这里就有了寻址耗时此外还有旋转耗时读写头需要等待磁盘碟片上的目标数据“旋转到位”才能进行读写操作。使用缓存当然是能够提升性能的但上述原理仍然适用。
在这段“I/O等待”时间内线程是处于“阻塞”等待状态也就是说没干啥正事此时操作系统可以将这个空闲的CPU 核心用于服务其他线程。 这里我们可以总结一下当你的线程处理的是 I/O 密集型业务时便可以让线程/连接数设置的比 CPU核心大一些这样就能够在同样的时间内完成更多的工作提升吞吐量。
那么问题又来了 大小设置成多少合适呢
这要取决于磁盘如果你使用的是 SSD 固态硬盘它不需要寻址也不需要旋转碟片。打住打住你千万可别理所当然的认为“既然SSD速度更快我们把线程数的大小设置的大些吧” 结论正好相反无需寻址和没有旋回耗时的确意味着更少的阻塞所以更少的线程更接近于CPU核心数会发挥出更高的性能。只有当阻塞密集时更多的线程数才能发挥出更好的性能。
上面我们已经说过了磁盘 IO, 接下来我们谈谈网络 IO
网络 IO 其实也是非常相似的。通过以太网接口读写数据时也会造成阻塞10G带宽会比1G带宽的阻塞耗时少一些而 1G 带宽又会比 100M 带宽的阻塞少一些。 通常情况下我们把网络 IO 放在第三顺位来考虑然而有些人会在性能计算中忽略网络 IO 带来的影响。 上图是 PostgreSQL 的基准性能测试数据从图中我们可以看到TPS 在连接数达到 50 时开始变缓。 回过头来想下Oracle 的性能测试中测试人员们将连接数从 2048 降到了 96实际上 96 还是太高了除非你的服务器 CPU 核心数有 16 或 32。
下面公式由 PostgreSQL 提供不过底层原理是不变的它适用于市面上绝大部分数据库产品。 还有你应该模拟预期的访问量并通过下面的公式先设置一个偏合理的值然后在实际的测试中通过微调来寻找最合适的连接数大小。
连接数 ((核心数 * 2) 有效磁盘数)核心数不应包含超线程(hyper thread)即使打开了超线程也是如此如果热点数据全被缓存了那么有效磁盘数实际是0随着缓存命中率的下降有效磁盘数也逐渐趋近于实际的磁盘数。 另外需要注意这一公式作用于SSD 的效果如何尚未明了。
好了按照这个公式如果说你的服务器 CPU 是 4核 i7 的连接池大小应该为 ((4*2)1)9。 取个整, 我们就设置为 10 吧。你这个行不行啊10 也太小了吧
你要是觉得不太行的话可以跑个性能测试看看我们可以保证它能轻松支撑 3000 用户以 6000 TPS 的速率并发执行简单查询的场景。 你还可以将连接池大小超过 10那时你会看到响应时长开始增加TPS 开始下降。
**结论**你需要的是一个小连接池和一个等待连接的线程队列 假设说你有 10000 个并发访问而你设置了连接池大小为 10000你怕是石乐志哦。 改成 1000太高改成 100还是太多了。你仅仅需要一个大小为 10 数据库连接池然后让剩下的业务线程都在队列里等待就可以了。
**连接池中的连接数量大小应该设置成**数据库能够有效同时进行的查询任务数通常情况下来说不会高于 2*CPU核心数。 你应该经常会看到一些用户量不是很大的 web 应用中为应付大约十来个的并发却将数据库连接池设置成 100 200 的情况。请不要过度配置您的数据库连接池的大小。
实际上连接池的大小的设置还是要结合实际的业务场景来说事。 比如说你的系统同时混合了长事务和短事务这时根据上面的公式来计算就很难办了。正确的做法应该是创建两个连接池一个服务于长事务一个服务于实时查询也就是短事务。 还有一种情况比方说一个系统执行一个任务队列业务上要求同一时间内只允许执行一定数量的任务这时我们就应该让并发任务数去适配连接池连接数而不是连接数大小去适配并发任务数。
4 数据库连接池druid参数详解
spring:datasource:druid:# 指定数据源类型为DruidDataSourcetype: com.alibaba.druid.pool.DruidDataSource# 数据库连接URLurl: jdbc:mysql://localhost:3306/test?useUnicodetruecharacterEncodingutf-8serverTimezoneAsia/ShanghaiuseSSLfalse# 数据库用户名username: root# 数据库密码password: xx123!## 连接池初始化时创建的连接数initialSize: 5# 连接池中最大连接数maxActive: 50# 连接池中最小空闲连接数minIdle: 5# 连接池中最大空闲连接数maxIdle: 10# 获取连接时的最大等待时间毫秒maxWait: 60000# 间隔多久检测一次空闲连接毫秒timeBetweenEvictionRunsMillis: 60000# 连接池中连接最小空闲时间毫秒minEvictableIdleTimeMillis: 300000# 用于检测连接是否有效的SQL语句validationQuery: SELECT 1# 是否开启空闲连接的检测testWhileIdle: true# 是否开启连接的检测功能在获取连接时检测连接是否有效testOnBorrow: false# 是否开启连接的检测功能在归还连接时检测连接是否有效testOnReturn: false# 是否缓存PreparedStatement对象poolPreparedStatements: true# 缓存PreparedStatement对象的最大数量maxPoolPreparedStatementPerConnectionSize: 20# 配置监控统计用的filter允许监控统计filters: stat# 配置扩展属性用于监控统计分析SQL性能等connectionProperties: druid.stat.mergeSqltrue;druid.stat.slowSqlMillis50001、type: 数据源类型这里使用了Druid连接池的类型。 注意事项使用Druid连接池的时候需要添加Druid连接池的依赖
dependencygroupIdcom.alibaba/groupIdartifactIddruid-spring-boot-starter/artifactIdversion${druid.version}/version
/dependency 2、url: 数据库连接的URL。 注意事项需要根据实际情况修改URL。
3、username: 数据库用户名。
4、password: 数据库密码 ;包含一些特殊字符的时候需要加引号。
5、initialSize: 连接池初始化时创建的连接数。 需要根据实际情况设置连接数。连接池创建连接时会创建initialSize个连接以确保应用程序在启动时可以立即获取到数据库连接。
6、maxActive: 连接池中最大连接数。 需要根据实际情况设置最大连接数。如果连接池中连接数达到maxActive则应用程序获取连接的请求将被阻塞直到有连接被释放。
7、minIdle: 连接池中最小空闲连接数。 需要根据实际情况设置最小空闲连接数。如果连接池中空闲连接数少于minIdle连接池会创建新的连接以达到minIdle。
8、maxIdle: 连接池中最大空闲连接数。 需要根据实际情况设置最大空闲连接数。如果连接池中空闲连接数超过maxIdle连接池会关闭多余的连接以避免占用过多的资源。
9、maxWait: 获取连接时的最大等待时间。 需要根据实际情况设置最大等待时间。如果连接池中没有可用连接且已经达到最大连接数则应用程序获取连接的请求将被阻塞最多等待maxWait毫秒。
10、timeBetweenEvictionRunsMillis: 间隔多久检测一次空闲连接毫秒。 需要根据实际情况设置检测间隔时间。连接池会定期检查空闲连接的状态如果空闲时间超过minEvictableIdleTimeMillis则将连接关闭。
11、minEvictableIdleTimeMillis: 连接池中连接最小空闲时间毫秒。 需要根据实际情况设置最小空闲时间。连接池会定期检查空闲连接的状态如果空闲时间超过minEvictableIdleTimeMillis则将连接关闭。
12、validationQuery: 用于检测连接是否有效的SQL语句。 需要根据实际情况设置SQL语句。连接池会使用这个SQL语句来检测连接是否有效。
13、testWhileIdle: 是否开启空闲连接的检测。 需要根据实际情况设置是否开启空闲连接的检测。如果开启连接池会定期检查空闲连接的状态。
14、testOnBorrow: 是否开启连接的检测功能 在获取连接时检测连接是否有效。 需要根据实际情况设置是否开启连接的检测功能。如果开启连接池在获取连接时会检查连接是否有效。
15、testOnReturn: 是否开启连接的检测功能在归还连接时检测连接是否有效。 需要根据实际情况设置是否开启连接的检测功能。如果开启连接池在归还连接时会检查连接是否有效。
16、poolPreparedStatements: 是否缓存PreparedStatement对象。 需要根据实际情况设置是否缓存PreparedStatement对象。如果开启连接池会缓存PreparedStatement对象以提高性能。
17、maxPoolPreparedStatementPerConnectionSize: 缓存PreparedStatement对象的最大数量。 需要根据实际情况设置缓存的最大数量。如果开启了缓存PreparedStatement对象连接池会限制每个连接缓存的最大数量。
maxPoolPreparedStatementPerConnectionSize是Druid连接池的一个配置项用于配置连接池中缓存的PreparedStatement的最大数量。 PreparedStatement是预编译的SQL语句可以提高SQL执行的效率和安全性避免SQL注入等安全问题。 在使用Druid连接池时当开启了缓存PreparedStatement功能时每个连接都会缓存一定数量的PreparedStatement对象以便在需要执行SQL语句时能够快速获取。
而maxPoolPreparedStatementPerConnectionSize就是用于配置每个连接中缓存的PreparedStatement的最大数量。 需要注意的是缓存PreparedStatement虽然可以提高SQL执行的效率但同时也会占用一定的内存资源。因此需要根据实际情况进行合理配置。 默认情况下该属性的值为10。
在上面的配置中maxPoolPreparedStatementPerConnectionSize: 20 表示将每个连接中缓存的PreparedStatement的最大数量设置为20个。
18、filters: 配置监控统计用的filter允许监控统计。 如果要使用Druid的监控功能需要配置此项。stat表示使用Druid的监控功能。
19、connectionProperties: 配置扩展属性用于监控统计分析SQL性能等。 druid.stat.mergeSql和druid.stat.slowSqlMillis是两个与SQL监控有关的属性。
druid.stat.mergeSql用于配置是否合并SQL。当该属性设置为true时Druid会将相同的SQL语句合并为一条以节省SQL统计的开销和提高统计精度。 默认情况下该属性的值为false。
druid.stat.slowSqlMillis用于配置SQL执行的时间阈值单位为毫秒。当一条SQL执行的时间超过该阈值时Druid会将该SQL记录到慢SQL列表中以便进行分析和优化。默认情况下该属性的值为3000毫秒。 在上面的配置中druid.stat.mergeSqltrue表示启用SQL合并功能 druid.stat.slowSqlMillis5000表示将SQL执行的时间阈值设置为5000毫秒。 这些属性的具体含义和配置方法可以参考Druid的官方文档。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/87134.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!