首页 > 微软云自主医疗保健手册正文

微软云自主医疗保健手册

2020-03-17

原标题:微软云自主医疗保健手册

今天我们给大家说说Azure上的MySQL的健康保健相关的话题,不带推销保健品,大家可以放心食用。

数据库是所有应用中最不可或缺的一个组件,所有有状态的数据都需要依托数据库提供的格式,规范进行存储、读取、改写等。那么既然是一个炙手可热的角色,如何让系统能够快速有效的和数据库进行沟通,就是一个比较有意思的话题了。如果把这个内容全部展开,可能会涉及到数据库的冗余性,扩展性设计等一系列的问题, 这次我们就先把目标锁定在如何快速管理连接这个点上。

如果把各个应用比作是需要看病就医的病患,那么医院可以说是一个大的数据库。那如何看病就医,井然有序,就需要一个规章法度,比如病人是否有此地就医的资格,是否已经挂号,有否既往病史,还需要什么化验等。那么同样,应用如果要得到数据库的增删改查的权限也一定要有一个流程。简要来说,流程就是通过一些网络协议,握手连接到数据库,提供一个有效的连接字符串,随后数据库会对比此应用是否有资格来访问这个数据库,最后就能愉快的增删改查了。

接下来我们将以Azure上面的MySQL PaaS为例,给大家讲解一些简单的数据库连接的使用场景,以及最佳实践。

0 1

第一种场景:

单个进程连接,非频繁访问

我们假设一个病人只是有点小的头疼脑热,那么第一次就诊结束,配了点药,然后可能需要第二天去复诊。这个时候也许他还得要走一次挂号,查医保信息,配药看医生等一系列流程。所以并不能直接敲开医生诊室的门,说我想直接看病配药。那么同样的道理,我们到数据库的连接中,会有一个超时(timeout)的概念,也就是说我第一次增删改查完,也许我等待了60秒,再一次查询,发现数据库说对不起,请重新连接“挂号”因为时间太长了,我不认识你了,或者说你的状态我不知道了,请重新握手协议,连接字符串,身份验证走一遍。那么我们看图示,里面哪些是我们需要一个数据库连接要提供的信息呢。

1.数据库的连接字符串,这个可以在Azure上得到你的程序需要的连接字符串。需要注意的是Azure上的数据库用户名比较特殊,在@后面会带上服务器名,这个和本地自建的不太一样。

2.随后我们用Python的程序新建一个表格,并且插入一些数据,模拟一个单进程的非频繁访问。

3.那么现在我们加入一个延时60秒,看看会发生什么?

4.为什么之前连接执行语句都好好的,怎们就加了60秒的等待就歇菜了呢?别着急,我们在Azure MySQL的参数调整里看一下wait_timeout的值,你会发现,咦,怎么有一个值是30秒呢?原来超过了30秒这个时间,原来的连接就超时了,我们程序里写得是休眠60秒。就需要重新连接,重新挂号了。

那么你会发现一旦程序有了空闲时间段,数据库就会不继续等待了,直接用timeout这个参数把你的连接给掐断了,需要你从头再来。这个很好理解,比如你在昨天看了医生,医生也不可能一直记得你,也不可能一直等你,只有到了你再去的时候,重新挂号然后再和白衣天使一起讨论病情。那么你有可能会问,那么如果是比较复杂的病情,一会要拍个片,一会要验血,其中都需要等待时间,那么拿了报告,医生又让我挂号,验证身份,岂不是很烦?那有没有一个比较人性化的制度可以让这些频繁的检查能够管理起来,那么我们就来看第二个场景。

0 2

第二个场景:

单个进程,需要频繁交互的数据库

之前我们讨论那种需要等化验结果,多次询问医生的场景。那么映射到数据库,就是说单个进程,需要频繁的访问数据库。这个其实有两个思路可以解决,第一种是把timeout的参数调的大一点其实就好了。这个没错,但是也存在一定安全和资源浪费,比如这个长连接会不会被非法占用,宝贵的数据库连接数是不是会被长时间占用,这些都是问题。那么第二个思路是,由一个中间人来协调所有的连接,同时让这些连接不会超时,同时也可以免去某一个进程需要频繁交互,频繁验证握手等,给程序带了很多等待时间。那么这种中间人的技术就叫做连接池,它的作用就相当于一共有10个医生坐班,连接池就是一个医导(可以是人,也可以是医院的信息化系统),事先都和这些医生很熟,建立了信任的连接,那么病患只要和这个医导建立连接,挂号验证身份,就能做完各种化验,继续找医生看病,省却了很多流程上的时间。那么再数据库的技术上有很多这些连接池的技术,比如DBUtils,PySQLpool等再python上使用比较频繁的模块。这次我们就以DBUtils来给大家讲解一下。

1.先看一下大概的概念,对比一下医导和连接池的类似概念。如图上显示的连接池在第一次验证之后,把所有的连接都放在它的大池子里,应用端不用每次都走一遍繁琐的流程,如果要在一个交易或者业务逻辑里频繁增删改查几十次,那么完全可以省下来之前这么多步骤,应用速度大大提升。

2.那么接下来, 用DBUtils来建立一个9个连接的连接池,数据库timeout参数还是30s不变,然后我们同样休眠60s,发现继续使用conn1还是可以连接,说明数据库连接池并没有释放掉原来的连接,而是缓存在了连接池之中。连接池一直保持这和数据库的硬连接,这个“硬”连接是真正走过所有的握手协议身份验证的,而应用和连接池的连接则是软连接是放在一个缓存池中里的。当然你还能定义有多少硬连接是在连接池建立完之后一直保留着的,这样会对突发的软连接有一定的帮助。

3.一旦设置了连接池,就比较完美解决了单进程的频繁访问问题了。那么你可能会问,如果是多进程怎么处理呢?连接池可以完美解决这个问题吗?接下来我们来看看下一个场景。

0 3

第三种场景:

多进程访问数据库

一般在显示问题里,资源都是比较紧俏的。资源不紧俏说的好听是冗余度高,防范黑天鹅,说的不好听就是浪费,但是这个平衡点确实很难掌握。那么我们现在讨论的场景就是资源相当紧俏的数据库连接,要被很多进程频繁同时访问。比如现在是流行病高发时期,医院看呼吸道疾病的医生可能只有10个人,但是同时要看病的患者可能成百上千,那么怎么样才能让这些心急火燎的病患能够看病治疗呢?那么医导这个系统可以记住所有来访的病人,知道哪些可以先去做血液检查,哪些在这个空隙,可以找医生看片子,那么10个医生的效率得到了最有话。只需要医导系统与这10个医生连接,所有的病人信息都缓存在医导这里;而不需要病人直接和医生建立连接,那么效率就是等10个病人全部检查完毕,才能看接下来的病人,效率会十分的缓慢。

1.现在我们先看一下, 如果不做任何共享连接的方式。也就是说到了连接上限就掐断,所有应用被劝离。

2.先看一下目前Azure MySQL的设置的连接数上限是10(当然这个不是最大值,最大连接数随着你选择的实例大小而变化)

3.初始化连接池的时候,不选共享连接, 参数上Blocking放成False。启动20个并发的线程

4.没有共享等待连接机制的情况下,超出连接数的线程就报错了。

5.那么现在我们把等待缓存机制换上,那么并发来的线程就能够等待之前的线程释放资源后,继续使用有限的连接数。这样就达到了一个缓存池的作用。同样的道理,如果我们医生医院不够大的时候,就可以建立很多简易或者野外的医院,隔离病房等,让看病的病患先得到妥善安置,然后在按需就医。

6.现在我们把缓存机制打开,把Blocking参数置成True。发现即使有20个进程同时并发,也会通过连接池缓存技术,妥善把所有进程完成,达到共享10个连接数的可能性。

场景总结

最后我们来总结一下前面三个场景。第一个场景是单进程非频繁访问,所以每一次访问都需要做一次数据库连接,会消耗一定资源和数据库连接数量。那么第二个场景是单进程,但是频繁访问,引入了数据库连接池的概念,可以事先维护好一定数量的连接池,不用每次访问都去建立一次连接,那么频繁访问的速度得到了保证。第三种场景的问题是如果是多进程的访问情况,连接数量会不够,这个时候引入了连接池缓存等待机制,就很好的解决了高并发多进程的问题。 所以在什么场景下选择什么样的技术方案是至关重要的。

要解决数据库连接或者看病难这种紧缺资源的问题,需要用到一些中间调剂人或者系统,那么这个系统是用公平的轮询机制,随机数机制,还是带有权重的机制,就涉及到资源分配的大问题了。设计系统的时候一定要把这些因素考虑进去,那么愿天下系统安稳,一切苦厄消散。

最后,提供本文技术参考指南及MySQL 连接池代码供各位查阅:

DBUtils 用户指南:

https://cito.github.io/DBUtils/UsersGuide.html#id2

代码传送门:

https://github.com/jurejoy/MySQLconnectionpool

2