DBUtils连接池,websocket
1.mysql數(shù)據(jù)庫連接池
概念:數(shù)據(jù)庫連接池(Connection pooling)是程序啟動(dòng)時(shí)建立足夠的數(shù)據(jù)庫連接,并將這些連接組成一個(gè)連接池,由程序動(dòng)態(tài)地對(duì)池中的連接進(jìn)行申請(qǐng),使用,釋放。
這樣集中管理,供程序使用可以保證較快的數(shù)據(jù)讀寫速度,而且不用來回創(chuàng)建數(shù)據(jù)庫連接,節(jié)省了時(shí)間,也更加的安全可靠。
1.1 背景
所有線程都只用一個(gè)mysql連接,如果這個(gè)連接斷掉,程序也會(huì)出現(xiàn)問題
如果我們?cè)诿看螆?zhí)行一個(gè)sql語句的時(shí)候都建立一個(gè)mysql連接,執(zhí)行完就關(guān)掉,那么可以想象頻繁開關(guān)這樣很容易消耗我們的資源,而且增加了連接失敗的幾率
1.2 優(yōu)勢(shì)
數(shù)據(jù)庫連接池優(yōu)勢(shì):減少鏈接次數(shù),此外支持并發(fā)
原理:
參考鏈接:猛戳此處
1.在程序創(chuàng)建連接的時(shí)候,可以從一個(gè)空閑的連接中獲取,不需要重新初始化連接,提升獲取連接的速度
2.關(guān)閉連接的時(shí)候,把連接放回連接池,而不是真正的關(guān)閉,所以可以減少頻繁地打開和關(guān)閉連接
2. DBUtils連接池
在python中,我們可以通過安裝DButils,來實(shí)現(xiàn)數(shù)據(jù)庫連接池的功能,它是一個(gè)第三方包
DButils主要作用在于提升mysql的執(zhí)行效率,當(dāng)然這種情況下需要結(jié)合pymsql來使用
2.1常規(guī)操作pymsql
import pymysqlconn = pymysql.connect(host='localhost',port=3306,user='root',password='',database='bbb',charset='utf8')cursor = conn.cursor() sql = "insert into bbb(id,name) value ('%s','%s')" % ("5","打算") cursor.execute(sql) conn.commit()cursor.close() conn.close()我在我的bbb數(shù)據(jù)庫中的bbb表添加了一條數(shù)據(jù),以上是我們的常規(guī)操作。針對(duì)數(shù)據(jù)量的大情況下,這種操作方式就不在合適了
2.2 操作數(shù)據(jù)庫連接池
創(chuàng)建數(shù)據(jù)庫連接池
import pymysql from DBUtils.PooledDB import PooledDBPOOL = PooledDB(creator=pymysql, # 使用連接數(shù)據(jù)庫的模塊maxconnections=6, # 連接池允許的最大連接數(shù),0和None表示不限制連接數(shù)mincached=2, # 初始化時(shí),連接池中至少創(chuàng)建的空閑的鏈接,0表示不創(chuàng)建maxcached=5, # 鏈接池中最多閑置的鏈接,0和None表示不限制maxshared=3, # 鏈接池中最多共享的鏈接數(shù)量,0和None表示全部共享。# PS: 無用,因?yàn)閜ymysql和MySQLdb等模塊的 threadsafety都為1,所有值無論設(shè)置為多少,_maxcached永遠(yuǎn)為0,所以永遠(yuǎn)是所有鏈接都共享。blocking=True, # 連接池中如果沒有可用連接后,是否阻塞等待。True,等待;False,不等待然后報(bào)錯(cuò)maxusage=None, # 一個(gè)鏈接最多被重復(fù)使用的次數(shù),None表示無限制setsession=[], # 開始會(huì)話前執(zhí)行的命令列表。如:["set datestyle to ...", "set time zone ..."]ping=0, # ping MySQL服務(wù)端,檢查是否服務(wù)可用。# 如:0 = None = never,# 1 = default = whenever it is requested,# 2 = when a cursor is created,# 4 = when a query is executed,# 7 = alwayshost='127.0.0.1',port=3306,user='root',password='',database='bbb',charset='utf8' )?使用數(shù)據(jù)路連接池
def func():# 檢測(cè)當(dāng)前正在運(yùn)行連接數(shù)的是否小于最大鏈接數(shù),如果不小于則:等待或報(bào)raise TooManyConnections異常# 否則# 則優(yōu)先去初始化時(shí)創(chuàng)建的鏈接中獲取鏈接 SteadyDBConnection。# 然后將SteadyDBConnection對(duì)象封裝到PooledDedicatedDBConnection中并返回。# 如果最開始創(chuàng)建的鏈接沒有鏈接,則去創(chuàng)建一個(gè)SteadyDBConnection對(duì)象,再封裝到PooledDedicatedDBConnection中并返回。# 一旦關(guān)閉鏈接后,連接就返回到連接池讓后續(xù)線程繼續(xù)使用。conn = POOL.connection()cursor = conn.cursor()cursor.execute('select * from bbb')result = cursor.fetchall()print(result)cursor.close()conn.close()func()效果:
?數(shù)據(jù)路連接池詳細(xì)介紹:猛戳此處
?3.websocket
3.1介紹:
WebSocket是一種在單個(gè)TCP連接上進(jìn)行全雙工通信的協(xié)議。WebSocket通信協(xié)議于2011年被IETF定為標(biāo)準(zhǔn)RFC 6455,并由RFC7936補(bǔ)充規(guī)范。WebSocket?API也被W3C定為標(biāo)準(zhǔn)。 ---->維基百科
socke與websocket區(qū)別:
socket:位于網(wǎng)絡(luò)層級(jí)的傳輸層,它是對(duì)TCP,UDP的封裝
websocket:它常與http協(xié)議作比較
WebSocket常見于客戶端-服務(wù)端全雙工的場(chǎng)景,客戶端可以發(fā)送消息給服務(wù)端,同時(shí)服務(wù)端也可以主動(dòng)發(fā)送消息給客戶端。
而Http是單向的關(guān)系,只能客戶端發(fā)送請(qǐng)求,服務(wù)端被動(dòng)接收,服務(wù)端沒有主動(dòng)發(fā)起對(duì)話的能力。
websocket作用:
WebSocket 使得客戶端和服務(wù)器之間的數(shù)據(jù)交換變得更加簡單,允許服務(wù)端主動(dòng)向客戶端推送數(shù)據(jù)
在 WebSocket API 中,瀏覽器和服務(wù)器只需要完成一次握手,兩者之間就直接可以建立持久性的連接,并進(jìn)行雙向數(shù)據(jù)傳輸。
?websocket優(yōu)勢(shì):
建立在 TCP 協(xié)議之上
與 HTTP 協(xié)議有著良好的兼容性。默認(rèn)端口也是80(http)和443(https),并且握手階段采用 HTTP 協(xié)議,因此握手時(shí)不容易屏蔽,能通過各種 HTTP 代理服務(wù)器
數(shù)據(jù)格式比較輕量,性能開銷小,通信高效
可以發(fā)送文本,也可以發(fā)送二進(jìn)制數(shù)據(jù)
沒有同源限制,客戶端可以與任意服務(wù)器通信
協(xié)議標(biāo)識(shí)符是ws(如果加密,則為wss),服務(wù)器網(wǎng)址就是 URL
3.2 websocket客戶端
創(chuàng)建websocket對(duì)象:
var Socket = new WebSocket(url, [protocol] ); # 第一個(gè)參數(shù) url 指定連接的URL。第二個(gè)參數(shù) protocol可選,指定可接受的子協(xié)議。websocket對(duì)象屬性:
Socket.readyState # 只讀屬性readyState表示連接狀態(tài),可以是以下值:0 - 表示連接尚未建立。1 - 表示連接已建立,可以進(jìn)行通信。2 - 表示連接正在進(jìn)行關(guān)閉。3 - 表示連接已經(jīng)關(guān)閉或者連接不能打開 Socket.bufferedAmount # 只讀屬性bufferedAmount已被 send() 放入正在隊(duì)列中等待傳輸,但是還沒有發(fā)出的 UTF-8 文本字節(jié)數(shù)websocket對(duì)象事件:
Socket.onopen # 連接建立時(shí)觸發(fā) Socket.onmessage # 客戶端接收服務(wù)端數(shù)據(jù)時(shí)觸發(fā) Socket.onerror # 通信發(fā)生錯(cuò)誤時(shí)觸發(fā) Socket.onclose # 連接關(guān)閉時(shí)觸發(fā)websocket對(duì)象相關(guān)方法:
Socket.send() # 使用連接發(fā)送數(shù)據(jù) Socket.close() # 關(guān)閉連接實(shí)例:
// 初始化一個(gè) WebSocket 對(duì)象 var ws = new WebSocket("ws://localhost:9998/echo");// 建立 web socket 連接成功觸發(fā)事件 ws.onopen = function () {// 使用 send() 方法發(fā)送數(shù)據(jù)ws.send("發(fā)送數(shù)據(jù)");alert("數(shù)據(jù)發(fā)送中..."); };// 接收服務(wù)端數(shù)據(jù)時(shí)觸發(fā)事件 ws.onmessage = function (evt) {var received_msg = evt.data;alert("數(shù)據(jù)已接收..."); };// 斷開 web socket 連接成功觸發(fā)事件 ws.onclose = function () {alert("連接已關(guān)閉..."); };?3.2 websocket服務(wù)端
? 服務(wù)端我們可以利用Node.js、Java、C++、Python等多種語言實(shí)現(xiàn)
3.3 基于websocket實(shí)現(xiàn)的群聊
先安裝相關(guān)模塊:
pip install gevent-websocket# 注意,單詞之間有個(gè)杠,不然檢索不到
代碼演示
?chat.py(服務(wù)端)
from flask import Flask,request,render_template from geventwebsocket.handler import WebSocketHandler from gevent.pywsgi import WSGIServer from geventwebsocket.websocket import WebSocket import jsonapp = Flask(__name__) user_dict = {} # 存放用戶名和信息 @app.route("/<username>") def index(username):user_obj = request.environ.get("wsgi.websocket") #type:WebSocketif user_obj:user_dict[username] =user_objprint(user_dict)# {'小a': <geventwebsocket.websocket.WebSocket object at 0x0000016B332183F0>}# 循環(huán)接收消息while True:msg = user_obj.receive()print(msg) # {"username":"小a","msg":"a發(fā)的消息"}# 前端發(fā)送的是json數(shù)據(jù),需要我們反序列化recv_msg = json.loads(msg)# 構(gòu)造數(shù)據(jù)結(jié)構(gòu)send_msg = {"username":recv_msg.get("username"),"msg":recv_msg.get("msg")}for i in user_dict.values():if i == user_obj:continuei.send(json.dumps(send_msg))@app.route("/ws") def ws():return render_template("people.html")if __name__ == "__main__":# 創(chuàng)建一個(gè)服務(wù)器http_serv = WSGIServer(("0.0.0.0",5000),app,handler_class=WebSocketHandler)# 監(jiān)聽http請(qǐng)求http_serv.serve_forever()people.html(客戶端)
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>Title</title></head> <body> 昵稱:<input type="text" id="nickname"> <button onclick="connws()">連接服務(wù)器</button> <br><br> 發(fā)送消息:<input type="text" id="talk"> <button onclick="send_msg()">發(fā)送信息</button> <br><br> <div style="width: 500px;height: 100%;border: 1px red solid;" id="text"></div> </body> <script type="application/javascript">var user_name = null; //用戶名var ws = null; //WebSocket 對(duì)象//連接wsfunction connws() {//獲取輸入框中的用戶名 user_name = document.getElementById("nickname").value;//創(chuàng)建 WebSocket 對(duì)象 ws = new WebSocket("ws://127.0.0.1:5000/" + user_name);//客戶端接收服務(wù)端數(shù)據(jù)時(shí)觸發(fā) ws.onmessage = function (data) {// 反序列化接收數(shù)據(jù)var recv_msg = JSON.parse(data.data);console.log(recv_msg);// 執(zhí)行自定義函數(shù)createDiv,傳入2個(gè)參數(shù) createDiv(recv_msg.username, recv_msg.msg);};}//發(fā)送消息function send_msg() {// 獲取輸入框的發(fā)送消息var talk = document.getElementById("talk").value;// 執(zhí)行自定義函數(shù)createDiv createDiv("w", talk);// 組件發(fā)送數(shù)據(jù)對(duì)象 send_str = {username: user_name, //用戶名 msg: talk //消息 };//使用連接發(fā)送數(shù)據(jù),序列化對(duì)象 ws.send(JSON.stringify(send_str));}//顯示聊天信息function createDiv(self, content) {// 創(chuàng)建div標(biāo)簽var divtag = document.createElement("div");//定義格式var who = self + " : ";// 判斷參數(shù)為w時(shí)if (self == "w") {// 替換字符串 who = "我 : "}// 修改顯示框的text屬性 divtag.innerText = who + content;// 獲取顯示框var text = document.getElementById("text");// appendChild() 方法向節(jié)點(diǎn)添加最后一個(gè)子節(jié)點(diǎn)// 添加一個(gè)div標(biāo)簽 text.appendChild(divtag);}</script> </html># 當(dāng)我們運(yùn)行flask時(shí),它會(huì)hang住,此時(shí)我們?cè)陧撁嬖L問http://127.0.0.1:5000/ws,多訪問幾個(gè)該url,就能實(shí)現(xiàn)多人聊天
開啟三個(gè)該url訪問后效果:
3.3 基于websocket實(shí)現(xiàn)的單聊
?和上面群聊類似
chat.py
from flask import Flask,request,render_template from geventwebsocket.handler import WebSocketHandler from gevent.pywsgi import WSGIServer from geventwebsocket.websocket import WebSocket import jsonapp = Flask(__name__)user_dict = {} # 空字典,用來存放用戶名和發(fā)送消息 @app.route("/<username>") # 參數(shù)為用戶名 def index(username):# 獲取請(qǐng)求的WebSocket對(duì)象user_socket = request.environ.get("wsgi.websocket") # type:WebSocketif user_socket:user_dict[username] = user_socket# 循環(huán),接收消息while True:# 接收消息msg = user_socket.receive()# 反序列化數(shù)據(jù),因?yàn)榍岸税l(fā)送的是jsonrecv_msg = json.loads(msg)print(recv_msg)# 構(gòu)造數(shù)據(jù)結(jié)構(gòu)send_msg = {"msg": recv_msg.get("msg"),"from_user": username,}# 獲取聊天對(duì)象的名字to_user = user_dict.get(recv_msg.get("to_user"))# 發(fā)送數(shù)據(jù) to_user.send(json.dumps(send_msg))@app.route("/ws") def ws():return render_template("people.html")if __name__ == '__main__':# 創(chuàng)建一個(gè)WebSocket服務(wù)器http_serv = WSGIServer(("0.0.0.0",5000),app,handler_class=WebSocketHandler)# 開始監(jiān)聽HTTP請(qǐng)求http_serv.serve_forever()people.html
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>Title</title></head> <body> 昵稱:<input type="text" id="nickname"> <button οnclick="connws()">連接服務(wù)器</button> <br> 與誰說話:<input type="text" id="sender"> <br> 發(fā)送消息:<input type="text" id="talk"> <button οnclick="send_msg()">發(fā)送信息</button> <br><br> <div style="width: 500px;height: 100%;border: 1px red solid;" id="text"> </div> </body> <script type="application/javascript">var user_name = null;var ws = null; //WebSocket 對(duì)象//連接wsfunction connws() {//獲取輸入框中的用戶名user_name = document.getElementById("nickname").value;//創(chuàng)建 WebSocket 對(duì)象ws = new WebSocket("ws://127.0.0.1:5000/" + user_name);//客戶端接收服務(wù)端數(shù)據(jù)時(shí)觸發(fā)ws.onmessage = function (data) {// 反序列化接收數(shù)據(jù)var recv_msg = JSON.parse(data.data);console.log(recv_msg);// 執(zhí)行自定義函數(shù)createDiv,傳入2個(gè)參數(shù)createDiv(recv_msg.from_user, recv_msg.msg);};}function send_msg() {// 獲取輸入框的發(fā)送消息var talk = document.getElementById("talk").value;// 獲取輸入框的聊天對(duì)象var sender = document.getElementById("sender").value;// 執(zhí)行自定義函數(shù)createDivcreateDiv("w", talk);// 構(gòu)造發(fā)送數(shù)據(jù)對(duì)象send_str = {msg: talk, //消息to_user: sender, //對(duì)方};//使用連接發(fā)送數(shù)據(jù),序列化對(duì)象ws.send(JSON.stringify(send_str));};//顯示聊天信息function createDiv(self, content) {// 創(chuàng)建div標(biāo)簽var divtag = document.createElement("div");//定義格式var who = self + " : ";// 判斷參數(shù)為w時(shí)if (self == "w") {// 替換字符串who = "我 : "}// 修改顯示框的text屬性divtag.innerText = who + content;// 獲取顯示框var text = document.getElementById("text");// appendChild() 方法向節(jié)點(diǎn)添加最后一個(gè)子節(jié)點(diǎn)// 添加一個(gè)div標(biāo)簽text.appendChild(divtag);}</script> </html>訪問:http://127.0.0.1:5000/ws,同時(shí)開啟兩個(gè)url頁面
效果
?
?
?阮一峰博客websocket介紹:參考此處
?
轉(zhuǎn)載于:https://www.cnblogs.com/LearningOnline/p/9603642.html
總結(jié)
以上是生活随笔為你收集整理的DBUtils连接池,websocket的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: IJ-java-com-util-com
- 下一篇: Python代码打包成exe文件