程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式師世界 >> 編程語言 >  >> 更多編程語言 >> Python

Python-Level2-day17:http請求與響應,web 服務項目實現,高並發技術探討

編輯:Python

4. web服務

4.1 HTTP協議

4.1.1 協議概述

  • 用途 : 網頁獲取,數據的傳輸

  • 特點

    • 應用層協議,使用tcp進行數據傳輸

    • 簡單,靈活,很多語言都有HTTP專門接口

    • 有豐富的請求類型

    • 可以傳輸的數據類型眾多

4.1.2 網頁訪問流程

  1. 客戶端(浏覽器)通過tcp傳輸,發送http請求給服務端

  2. 服務端接收到http請求後進行解析

  3. 服務端處理請求內容,組織響應內容

  4. 服務端將響應內容以http響應格式發送給浏覽器

  5. 浏覽器接收到響應內容,解析展示

 

 

4.1.2 HTTP請求

  • 請求行 : 具體的請求類別和請求內容

 GET         /       HTTP/1.1
請求類別   請求內容     協議版本

請求類別:每個請求類別表示要做不同的事情

   GET : 獲取網絡資源
  POST :提交一定的信息,得到反饋
  HEAD : 只獲取網絡資源的響應頭
  PUT : 更新服務器資源
  DELETE : 刪除服務器資源
  • 請求頭:對請求的進一步解釋和描述(例如什麼時間用什麼浏覽器發給服務器的)

 eg.Accept-Encoding: gzip   一行行鍵值對構成
  • 空行

  • 請求體: 請求參數或者提交內容

 

 

4.1.3 HTTP響應

  • 響應行 : 反饋基本的響應情況

   HTTP/1.1     200       OK
  版本信息     響應碼     附加信息

響應碼 :

   1xx 提示信息,表示請求被接收
  2xx 響應成功
  3xx 響應需要進一步操作,即二次處理重定向
  4xx 客戶端錯誤
  5xx 服務器錯誤
  • 響應頭:對響應內容的描述 ----詳細解釋給你的響應是什麼格式,大小等信息

   eg.Content-Type: text/html ---以網頁格式解析
  • 空行

  • 響應體:響應的主體內容信息

 

 

"""
http 請求和響應
"""
from socket import *
​
# 創建tcp套接字
sock = socket()
sock.bind(("0.0.0.0", 8888))
sock.listen(5)
​
# 等待浏覽器連接
connfd, addr = sock.accept()
print("Connect from", addr)
​
# 接收HTTP請求
request = connfd.recv(1024)
print(request.decode())
​
# 組織響應格式
response = """HTTP/1.1 200 OK
Content-Type:text/html
​
Hello World
"""
connfd.send(response.encode()) # 發送響應
​
connfd.close()
sock.close()
​
"""
練習: 根據所學http協議完成
通過浏覽器訪問服務端,請求根 則會
顯示一張圖片在浏覽器上 ,圖片自選
​
Content-Type:image/jpeg
"""
from socket import *
​
​
def get_response(filename):
  response = "HTTP/1.1 200 OK\r\n"
  response += "Content-Type:image/jpeg\r\n"
  response += "\r\n"
  with open(filename, 'rb') as file:
      response = response.encode() + file.read()
  return response # 字節串
​
​
def main():
  sock = socket()
  sock.bind(("0.0.0.0", 8000))
  sock.listen(5)
​
  while True:#浏覽器可以多個頁面循環訪問
      connfd, addr = sock.accept()
      print("Connect from", addr)
      # 接收請求
      request = connfd.recv(1024)
      print(request.decode())
      response = get_response("yaya.jpeg")#前端工程師提供圖像信息
      connfd.send(response) # 字節串
​
​
if __name__ == '__main__':
  main()
​

4.2 web 服務項目實現

  1. 主要功能 : 【1】 接收客戶端(浏覽器)請求

    【2】 解析客戶端發送的請求

    【3】 根據請求組織數據內容

    【4】 將數據內容形成http響應格式返回給浏覽器

  2. 主要特點 :

    【1】 采用IO並發,可以滿足多個客戶端同時發起請求情況

    【2】 通過類接口形式進行功能封裝

    【3】 做基本的請求解析,根據具體請求返回具體內容,同時可以滿足客戶端的網頁效果加載

"""
web sever 服務
"""
from socket import *
from select import select
import os
​
​
# 具體處理http請求
class Handle:
  def __init__(self, html):
      self.html = html
​
  def _response(self, status, filename):
      response = "HTTP/1.1 %s\r\n" % status
      response += "Content-Type:text/html\r\n"
      response += "\r\n"
      with open(filename, 'rb') as file:
          response = response.encode() + file.read()
      return response
​
  def _send_response(self, connfd, info):
      # 請求的是 首頁 還是 其他網頁
      if info == '/':
          filename = self.html + "/index.html"
      else:
          filename = self.html + info
​
      # 判斷是否存在 True / False
      if os.path.exists(filename):
          data = self._response("200 OK", filename)
      else:
          data = self._response("404 Not Found", self.html + "/404.html")
      connfd.send(data) # 發送響應
​
  def handle(self, connfd):
      # 接收HTTP請求
      request = connfd.recv(1024).decode()
      if not request:
          return
      # 獲取請求內容
      info = request.split(" ")[1]
      print('請求內容:', info)
      # 組織響應並發送
      self._send_response(connfd, info)
​
​
class WebServer:
  # 實例化對象過程中做好准備工作
  def __init__(self, host='', port=0, html=None):
      self.host = host
      self.port = port
      self.address = (host, port)
      self.html = html # 用戶提供的網頁
      self.rlist = []
      self.handle = Handle(html)
      self.sock = self._create_socket()
​
  # 創建套接字
  def _create_socket(self):
      sock = socket()
      sock.bind(self.address)
      sock.setblocking(False) # 非阻塞
      return sock
​
  # 連接浏覽器
  def _connect(self):
      connfd, addr = self.sock.accept()
      connfd.setblocking(False)
      self.rlist.append(connfd) # 增加關注
​
  # start啟動函數過程中 搭建服務 IO並發模型
  def start(self):
      self.sock.listen(5)
      print("Listen the port %d" % self.port)
      self.rlist.append(self.sock) # 初始關注監聽套接字
      # 循環接收監控IO發生
      while True:
          rs, ws, xs = select(self.rlist, [], [])
          for r in rs:
              if r is self.sock:
                  self._connect() # 處理連接
              else:
                  try:
                      self.handle.handle(r) # 處理http請求
                  except:
                      pass
                  self.rlist.remove(r) # 短連接場景,處理完即關閉
                  r.close()
​
​
if __name__ == '__main__':
  # 先想一下怎麼用
  # 什麼需要用戶決定: 服務器地址 內容
  httpd = WebServer(host="0.0.0.0", port=8888,
                    html="./static")
  httpd.start() # 啟動服務
​

5. 高並發技術探討

5.1 高並發問題

  • 衡量高並發的關鍵指標

    • 響應時間(Response Time) : 接收請求後處理的時間

    • 同時在線用戶數量:同時連接服務器的用戶的數量

    • 每秒查詢率QPS(Query Per Second): 每秒接收請求的次數

    • 每秒事務處理量TPS(Transaction Per Second):每秒處理請求的次數(包含接收,處理,響應)

    • 吞吐量(Throughput): 響應時間+QPS+同時在線用戶數量

  • 多大的並發量算是高並發

    • 沒有最高,只要更高

      比如在一個小公司可能QPS2000+就不錯了,在一個需要頻繁訪問的門戶網站可能要達到QPS5W+

    • C10K問題

      早先服務器都是單純基於進程/線程模型的,新到來一個TCP連接,就需要分配1個進程(或者線程)。而進程占用操作系統資源多,一台機器無法創建很多進程。如果是C10K就要創建1萬個進程,那麼單機而言操作系統是無法承受的,這就是著名的C10k問題。創建的進程線程多了,數據拷貝頻繁, 進程/線程切換消耗大, 導致操作系統崩潰,這就是C10K問題的本質!

5.2 更高並發的實現

為了解決C10K問題,現在高並發的實現已經是一個更加綜合的架構藝術。涉及到進程線程編程,IO處理,數據庫處理,緩存,隊列,負載均衡等等,這些我們在後面的階段還會學習。此外還有硬件的設計,服務器集群的部署,服務器負載,網絡流量的處理等。

 

 

實際工作中,應對更龐大的任務場景,網絡並發模型的使用有時也並不單一。比如多進程網絡並發中每個進程再開辟線程,或者在每個進程中也可以使用多路復用的IO處理方法。

 

前情回顧

1. IO多路復用

   利用系統內核的IO監控功能 ,哪個IO就緒就處理哪個IO
   對象,形成多個IO可以 "同時" 處理多個IO

   IO多路是單進程,資源占用少,但是只能處理簡單的IO操作

2. select   epoll

   select: 平台支持好,但是同時監控IO數量有限,效率沒有
           epoll高

   epoll : 效率高,支持同時監控IO數量多,但是只用於Linux

3. 使用IO多路復用實現網絡並發


4. HTTP 協議

   應用層   tcp傳輸    簡單方便   請求類型多

   HTTP協議使用: 傳輸數據  訪問網站
                網頁訪問流程


練習: 根據所學http協議完成
通過浏覽器訪問服務端,請求根 則會
顯示一張圖片在浏覽器上 ,圖片自選

Content-Type:image/jpeg

webserver 模塊

需求分析
    接收客戶端(浏覽器)請求
    解析客戶端發送的請求
    根據請求組織數據內容
    將數據內容形成http響應格式返回給浏覽器

技術 :  IO多路復用並發網絡 : select
       TCP

模塊封裝 :  類
協議 : HTTP協議

類接口設計 :

   socket : 生成對象,使用對象靈活的調用各種方法
            組合,就會產生不同的功能效果

   Process : 生成對象,調用方法啟動功能 (如果多
   調用方法也是為主體功能服務的),能為用戶決定就幫他決定
   不能替用戶決定需要用戶傳參

核心編程

1. 網絡編程

   網絡基礎知識:
      1. TCP/IP模型和OSI七層模型
      2. 三次握手和四次揮手過程
      3. tcp和udp的區別
      4. http協議的特點和請求響應格式

   socket 模塊
      tcp套接字編程 (重點)

      udp套接字編程 (重點)


2. 進程和線程

   基礎概念
     1. 進程與線程的特點和區別
     2. 理解什麼是進程和進程狀態

   多進程  (包括自定義進程類)  重點,難點
      multiprocessing

   多線程  (包括同步互斥方法)  重點
      threading
      GIL


3. IO模型

   阻塞IO

   非阻塞IO

   IO多路復用 (重點,難點)
      select
      epoll


4. 網絡並發模型

   多進程多線程並發 (重點)

   IO多路復用並發 (重點)

5. 綜合代碼
    學生管理系統 :
       文件  正則   函數編程

    群聊聊天室 :
       udp   多進程  函數編程
       通信協議請求  "總分結構"

    ftp文件服務器
       tcp   多線程並發模型   面向對象
       通信協議響應   請求應答的模式

    webserver
       tcp   IO多路復用並發模型  設計類接口
       類的設計思路

<核心編程 第三版>
<圖解TCP/IP>
<圖解HTTP>


作業: 1. webserver自己寫一下
     2.  github.com
         gitee.com


 


  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式師世界 All Rights Reserved