파충류의 성능 최적화
##1. 차단 및 비차단 응용 프로그램 상태
request.get()
1. 차단
2.준비 완료
준비와 차단이 사용자에게 주는 느낌은 바로 카드이다. 차단은 프로그램이io작업에 부딪혀 계속 실행할 수 없다는 것을 말한다
3. 실행
IO 조작에 있어서 다중 루트를 사용할 수도 있고 다중 프로세스를 사용할 수도 있다
io 밀집형: 다중 루틴 계산 밀집형 사용 가능: 다중 프로세스를 사용해야 합니다
둘.동기화 및 비동기는 작업을 커밋하는 방법을 나타냅니다.
동기화: 작업을 제출한 후 제자리에서 기다리고 실행이 끝난 후에야 계속할 수 있는 비효율적인 것을 말한다
비동기식: 작업을 제출한 후에는 상관하지 않고 계속 실행할 수 있어 효율이 높다
1. 동시 호출
import requests
def parse_page(res):
print(' %s' %(len(res)))
def get_page(url):
print(' %s' %url)
response=requests.get(url)
if response.status_code == 200:
return response.text
urls=['https://www.baidu.com/','http://www.sina.com.cn/','https://www.python.org']
for url in urls:
res=get_page(url) # ,
parse_page(res)
1.1 솔루션(다중 스레드 또는 다중 프로세스)
서버에서 다중 루틴이나 다중 프로세스를 사용할 때 모든 링크가 독립된 루틴(프로세스)을 가지도록 한다. 이렇게 하면 어떤 차단된 막힘도 다른 링크에 영향을 주지 않는다. (그러나 현장이 너무 많으면 서버에 대한 압력이 너무 크다)
#IO
import requests
from threading import Thread,current_thread
def parse_page(res):
print('%s %s' %(current_thread().getName(),len(res)))
def get_page(url,callback=parse_page):
print('%s %s' %(current_thread().getName(),url))
response=requests.get(url)
if response.status_code == 200:
callback(response.text)
if __name__ == '__main__':
urls=['https://www.baidu.com/','http://www.sina.com.cn/','https://www.python.org']
list = []
for url in urls:
t=Thread(target=get_page,args=(url,))
t.start()
list.append(t)
#
for i in list:
i.join()
1.2 개선 방안(스레드 탱크와 프로세스 탱크 + 비동기 호출)
해결 방법: 프로세스 탱크 또는 스레드 탱크 + 리셋 메커니즘
스레드 탱크: 스레드를 생성하고 소각하는 빈도를 줄이고 일정한 합리적인 수량의 스레드를 유지하며 빈 스레드로 하여금 새로운 실행 임무를 다시 맡게 한다
링크 탱크: 링크의 캐시 탱크를 유지하고 기존의 연결을 최대한 다시 사용하며 링크를 만들고 닫는 빈도를 줄인다
상기 두 가지 계수는 시스템의 비용을 잘 낮출 수 있어 모두 광범위하게 응용되었다
import requests
from threading import current_thread
from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor
def parse_page(res):
res = res.result()
print('%s %s' % (current_thread().getName(), len(res)))
def get_page(url):
print('%s %s' % (current_thread().getName(), url))
response = requests.get(url)
if response.status_code == 200:
return response.text
if __name__ == '__main__':
urls = [
'https://www.baidu.com/', 'http://www.sina.com.cn/', 'https://www.python.org'
]
pool = ThreadPoolExecutor(50)
for url in urls:
pool.submit(get_page, url).add_done_callback(parse_page)
#
pool.shutdown(wait=True)
향상된 문제점:
스레드 탱크와 연결 탱크 기술도 Io의 빈번한 호출이 가져오는 호출 자원 문제를 어느 정도 완화시켰다. 요청한 수량이 스레드의 수량을 크게 초과할 때 스레드 탱크가 없는 것에 비해 큰 차이가 없기 때문에 응답 규모에 따라 스레드 탱크의 크기를 조정해야 한다.
다중 스레드 모델은 소규모 서비스 요청을 편리하고 효율적으로 해결할 수 있지만 대규모 서비스 요청에 직면하면 다중 스레드 모델도 병목에 부딪힐 수 있다. 해결 방식은 비막힘io인터페이스를 사용하는 것이다.
둘.비차단 IO(비동기 호출)
**문제분석: **문제를 해결하는 관건은 우리가 응용 프로그램 단계에서 검사하는 것이다. 프로그램이 IO 조작을 만났을 때 우리는 프로그램의 다른 조작으로 전환한다. 그러면 cpu의 효율을 최대한 활용하고 프로그램의 Io를 최소화한다. 그러면 운영체제는 이 프로그램 전체의 Io가 비교적 적은 운영 프로그램으로 인정하고 cpu는 우리에게 최대한 분배한다.
1.asyncio 모듈
python 3.3 이후에 asyncio 모듈을 추가하여 IO를 자동으로 검출하고 응용 프로그램의 전환을 실현할 수 있습니다. 원리는gevent와 마찬가지로 IO를 만났을 때 하나의 작업(즉 협정)을 전환할 수 있습니다.
자세히 보기:https://blog.csdn.net/qq_42737056/article/details/86645971
import asyncio
# Io
@asyncio.coroutine
def task(task_id, senconds):
print('%s is start' % task_id)
yield from asyncio.sleep(senconds) # yield from Io , io
print('%s is end' % task_id)
tasks = [task(task_id=" 1", senconds=3), task(" 2", 2), task(task_id=" 3", senconds=1)]
loop = asyncio.get_event_loop()
#
loop.run_until_complete(asyncio.wait(tasks))
print(' ')
loop.close()
2.asyncio+requests
asycio는 tcp 프로토콜의 요청만 발송할 수 있기 때문에 http 프로토콜의 요청 헤더는 스스로 헤더를 정의해야 하기 때문에 Requests와 분업하여 작업합니다
import asyncio
import requests
def get_page(func, *args):
print('GET: %s' % args[0])
loop = asyncio.get_event_loop()
future = loop.run_in_executor(None, func, *args)
response = yield from future
print(response.url, len(response.text))
return ('complete')
tasks = [
get_page(requests.get, 'https://www.python.org/doc'),
get_page(requests.get, 'https://www.cnblogs.com/linhaifeng'),
get_page(requests.get, 'https://www.openstack.org')
]
def run():
loop = asyncio.get_event_loop()
results = loop.run_until_complete(asyncio.gather(*tasks))
loop.close()
print('>>>', results)
if __name__ == '__main__':
run()
3.gevent 모듈(이동 제출 작업)
from gevent import monkey;monkey.patch_all()
import gevent
import requests
def get_page(url):
print('GET:%s' %url)
response=requests.get(url)
print(url,len(response.text))
return 1
#
from gevent.pool import Pool
pool=Pool(2)
g1=pool.spawn(get_page,'https://www.python.org/doc')
g2=pool.spawn(get_page,'https://www.cnblogs.com/linhaifeng')
g3=pool.spawn(get_page,'https://www.openstack.org')
gevent.joinall([g1,g2,g3,])
print(g1.value,g2.value,g3.value) #
4.grequests 모듈
Request+gevent 모듈 봉인
#pip3 install grequests
import grequests
request_list=[
grequests.get('https://wwww.xxxx.org/doc1'),
grequests.get('https://www.cnblogs.com/linhaifeng'),
grequests.get('https://www.openstack.org')
]
# ( )
def exception_handler(request, exception):
# print(request,exception)
print("%s Request failed" %request.url)
#
response_list = grequests.map(request_list, exception_handler=exception_handler)
print(response_list)
5.twisted
Twisted는 Python으로 이루어진 이벤트 구동 기반의 네트워크 엔진 프레임워크로 Twisted는 TCP, UDP, HTTP 등 많은 흔한 전송 및 응용층 프로토콜을 지원한다.
python3에서 문자열은utf8 형식으로 변환해야 합니다. 그렇지 않으면 발송할 수 없습니다.예컨대
str("test").encode("utf8")
면 된다from twisted.web.client import getPage, defer
from twisted.internet import reactor
def all_done(args):
# print(args)
reactor.stop()
def callback(res):
print(res)
return 1
defer_list = []
urls = [
'http://www.baidu.com',
'http://www.bing.com',
'https://www.python.org',
]
for url in urls:
obj = getPage(url.encode('utf-8'), )
obj.addCallback(callback)
defer_list.append(obj)
defer.DeferredList(defer_list).addBoth(all_done)
reactor.run()
6.tornado 모듈
Tornado는 Python을 사용하여 작성된 강력하고 확장 가능한 웹 서버입니다.그것은 심각한 네트워크 데이터를 처리할 때 충분히 강건하지만, 창설과 작성할 때 충분한 경량급을 가지고 있어 대량의 응용 프로그램과 도구에 사용될 수 있다.
from tornado.httpclient import AsyncHTTPClient
from tornado.httpclient import HTTPRequest
from tornado import ioloop
count=0
def handle_response(response):
"""
( , IO ), ioloop.IOLoop.current().stop()
:param response:
:return:
"""
if response.error:
print("Error:", response.error)
else:
print(len(response.body))
global count
count-=1 # , 1
if count == 0:
ioloop.IOLoop.current().stop()
def func():
url_list = [
'http://www.baidu.com',
'http://www.bing.com',
]
global count
for url in url_list:
print(url)
http_client = AsyncHTTPClient()
http_client.fetch(HTTPRequest(url), handle_response)
count+=1 # 1
ioloop.IOLoop.current().add_callback(func)
ioloop.IOLoop.current().start()
twisted와 tornado의 차이
모두 파충류 기반의 서버 프레임워크(스킬 쓰기 서버, 쓰기 클라이언트가 있음)
twisted: 성능은 강하지만 cpu에 대한 점용도 강합니다. tornado: 성능은 먼저 약하고 cpu에 대한 점용도 약합니다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.