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