Aiohttp: μ‹œκ°„μ΄ 지남에 따라 μ„±λŠ₯ μ €ν•˜ ...

에 λ§Œλ“  2017λ…„ 04μ›” 17일  Β·  44μ½”λ©˜νŠΈ  Β·  좜처: aio-libs/aiohttp

μ•„λž˜μ— λΉ λ₯Έ AsyncScraper 클래슀λ₯Ό μž‘μ„±ν–ˆμŠ΅λ‹ˆλ‹€.

import logging, datetime, time
import aiohttp
import asyncio
import uvloop

# asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())

logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
logger.addHandler(logging.StreamHandler())

class AsyncScraper(object):
    headers = {"User-Agent" : 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.131 Safari/537.36'}
    def __init__(self, max_connections=1000, timeout=10):
        self.max_connections = max_connections
        self.timeout = timeout

    async def get_response(self, url, session):
        with aiohttp.Timeout(timeout=self.timeout):
            async with session.get(url, allow_redirects=True, headers=AsyncScraper.headers, timeout=self.timeout) as response:
                try:
                    content = await response.text()
                    return {'error': "", 'status': response.status, 'url':url, 'content': content, 'timestamp': str(datetime.datetime.utcnow())}
                except Exception as err:
                    return {'error': err, 'status': "", 'url':url, 'content': "", 'timestamp': str(datetime.datetime.utcnow())}
                finally:
                    response.close()

    def get_all(self, urls):
        loop = asyncio.get_event_loop()
        with aiohttp.ClientSession(loop=loop, connector=aiohttp.TCPConnector(keepalive_timeout=10, limit=self.max_connections, verify_ssl=False)) as session:
            tasks = asyncio.gather(*[self.get_response(url, session) for url in urls], return_exceptions=True)
            results = loop.run_until_complete(tasks)
            return results

def chunks(l, n):
    for i in range(0, len(l), n):
        yield l[i:i + n]

def process_urls(urls, chunk_size=1000):
    scraper = AsyncScraper()

    results = []
    t0 = time.time()
    for i, urls_chunk in enumerate(chunks(sorted(set(urls)), chunk_size)):
        t1 = time.time()
        result = scraper.get_all(urls_chunk)
        success_size = len( [_ for _ in result if ((isinstance(_, Exception) is False) and (_['status']==200)) ] )
        results.extend(result)
        logger.debug("batch {} => success: {} => iteration time: {}s =>  total time: {}s => total processed {}".format(i+1, success_size, time.time()-t1, time.time()-t0, len(results)))
    return results

두 가지 μ£Όμš” λ¬Έμ œκ°€ μžˆμŠ΅λ‹ˆλ‹€.

  1. λ‹¨μˆœ URL λͺ©λ‘ (예 : get_all λ©”μ„œλ“œλ₯Ό 톡해)을 100k둜 μ „λ‹¬ν•˜λ©΄ 였λ₯˜κ°€ λ²”λžŒν•©λ‹ˆλ‹€.

    2017-04-17 15 : 50 : 53,541-asyncio-ERROR-SSL μ „μ†‘μ‹œ 치λͺ…적인 였λ₯˜
    μ‹€ν—˜ κ³„νšμ•ˆ:
    전솑 : <_SelectorSocketTransport λ‹«κΈ° fd = 612 read = idle write =>
    μ—­ 좔적 (κ°€μž₯ 졜근 호좜 λ§ˆμ§€λ§‰) :
    _process_write_backlog의 파일 "/Users/vgoklani/anaconda3/lib/python3.6/asyncio/sslproto.py", 639 ν–‰
    ssldata = self._sslpipe.shutdown (self._finalize)
    파일 "/Users/vgoklani/anaconda3/lib/python3.6/asyncio/sslproto.py", 쀄 151, μ’…λ£Œ 쀑
    RuntimeError ( 'shutdown in progress') λ°œμƒ
    RuntimeError : μ’…λ£Œ 진행 쀑

  2. 그런 λ‹€μŒ URL을 1,000 개 λ‹¨μœ„λ‘œ 일괄 μ²˜λ¦¬ν•˜κ³  일괄 처리 κ°„μ˜ 응닡 μ‹œκ°„μ„ μΈ‘μ •ν–ˆμŠ΅λ‹ˆλ‹€. 그리고 μ‹œκ°„μ— λ”°λ₯Έ μ„±λŠ₯ μ €ν•˜λ₯Ό λͺ…ν™•ν•˜κ²Œ μΈ‘μ • ν•  μˆ˜μžˆμ—ˆμŠ΅λ‹ˆλ‹€ (μ•„λž˜ μ°Έμ‘°). κ²Œλ‹€κ°€ μ‹œκ°„μ΄ 지남에 따라 였λ₯˜ μˆ˜κ°€ μ¦κ°€ν–ˆμŠ΅λ‹ˆλ‹€ ... λ‚΄κ°€ 뭘 잘λͺ»ν•˜κ³  μžˆλŠ”κ°€?

    반볡 0은 16.991 μ΄ˆμ— μ™„λ£Œλ˜μ—ˆμŠ΅λ‹ˆλ‹€.
    39.376 μ΄ˆμ— 반볡 1 μ™„λ£Œ
    반볡 2λŠ” 35.656 μ΄ˆμ— μ™„λ£Œλ˜μ—ˆμŠ΅λ‹ˆλ‹€.
    19.716sμ—μ„œ 반볡 3 μˆ˜ν–‰
    29.331sμ—μ„œ 반볡 4 μˆ˜ν–‰
    19.708sμ—μ„œ 반볡 5 μˆ˜ν–‰
    19.572 μ΄ˆμ— 6 번 반볡
    29.907sμ—μ„œ 반볡 7 μˆ˜ν–‰
    23.379 μ΄ˆμ— 8 번 반볡
    21.762 μ΄ˆμ— 9 번 반볡
    22.091 μ΄ˆμ— 10 번 반볡
    22.940 μ΄ˆμ— 11 번 반볡
    31.285 μ΄ˆμ— 12 번 반볡
    반볡 13은 24.549 μ΄ˆμ— μ™„λ£Œλ˜μ—ˆμŠ΅λ‹ˆλ‹€.
    반볡 14λŠ” 26.297 μ΄ˆμ— μ™„λ£Œλ˜μ—ˆμŠ΅λ‹ˆλ‹€.
    23.816 μ΄ˆμ— 15 번 반볡
    29.094 μ΄ˆμ— 16 번 반볡
    24.885 μ΄ˆμ— 17 번 반볡
    26.456 μ΄ˆμ— 18 번 반볡
    27.412sμ—μ„œ 19 번 반볡
    29.969 μ΄ˆμ— 20 번 반볡
    28.503 μ΄ˆμ— 21 번 반볡
    28.699 μ΄ˆμ— 22 번 반볡
    31.570 μ΄ˆμ— 23 번 반볡
    31.898sμ—μ„œ 26 번 반볡
    33.553 μ΄ˆμ— 27 번 반볡
    34.022 μ΄ˆμ— 28 번 반볡
    33.866 μ΄ˆμ— 29 번 반볡
    36.351sμ—μ„œ 30 번 반볡
    40.060 μ΄ˆμ— 31 번 반볡
    35.523 μ΄ˆμ— 32 번 반볡
    36.607 μ΄ˆμ— 33 번 반볡
    36.325 μ΄ˆμ— 34 번 반볡
    38.425 μ΄ˆμ— 35 번 반볡
    39.106 μ΄ˆμ— 36 번 반볡
    38.972 μ΄ˆμ— 37 번 반볡
    39.845 μ΄ˆμ— 38 번 반볡
    40.393sμ—μ„œ 39 회 반볡
    40.734 μ΄ˆμ— 40 번 반볡
    47.799 μ΄ˆμ— 41 번 반볡
    43.070sμ—μ„œ μˆ˜ν–‰λ˜λŠ” 반볡 42
    43.365 μ΄ˆμ— 43 번 반볡
    42.081 μ΄ˆμ— 44 번 반볡
    44.118 μ΄ˆμ— 45 번 반볡
    44.955 μ΄ˆμ— 46 번 반볡
    45.400 μ΄ˆμ— 47 번 반볡
    45.987sμ—μ„œ 48 번 반볡
    46.041sμ—μ„œ μˆ˜ν–‰ 된 반볡 49
    45.899 μ΄ˆμ— 50 회 반볡
    49.008sμ—μ„œ μˆ˜ν–‰λ˜λŠ” 반볡 51
    49.544 μ΄ˆμ— 52 회 반볡
    55.432 μ΄ˆμ— 53 번 반볡
    52.590 μ΄ˆμ— 54 번 반볡
    50.185 μ΄ˆμ— 55 번 반볡
    52.858 μ΄ˆμ— 56 번 반볡
    52.698sμ—μ„œ 57 회 반볡
    53.048 μ΄ˆμ— 58 회 반볡
    54.120 μ΄ˆμ— 59 번 반볡
    54.151 μ΄ˆμ— 60 번 반볡
    55.465 μ΄ˆμ— 61 번 반볡
    56.889 μ΄ˆμ— 62 번 반볡
    56.967 μ΄ˆμ— 63 번 반볡
    57.690 μ΄ˆμ— 64 번 반볡
    57.052 μ΄ˆμ— 65 번 반볡
    67.214sμ—μ„œ μˆ˜ν–‰λ˜λŠ” 반볡 66
    58.457 μ΄ˆμ— 67 번 반볡
    60.882 μ΄ˆμ— 68 번 반볡
    58.440 μ΄ˆμ— 69 번 반볡
    60.755 μ΄ˆμ— 70 번 반볡
    58.043sμ—μ„œ μˆ˜ν–‰λ˜λŠ” 반볡 71
    65.076 μ΄ˆμ— 72 번 반볡
    63.371 μ΄ˆμ— 73 번 반볡
    62.800 μ΄ˆμ— 74 번 반볡
    62.419 μ΄ˆμ— 75 번 반볡
    61.376 μ΄ˆμ— 76 번 반볡
    63.164sμ—μ„œ 77 번 반볡
    65.443 μ΄ˆμ— 78 번 반볡
    64.616 μ΄ˆμ— 79 번 반볡
    69.544 μ΄ˆμ— 80 번 반볡
    68.226sμ—μ„œ μˆ˜ν–‰λ˜λŠ” 반볡 81
    78.050 μ΄ˆμ— 82 번 반볡
    67.871 μ΄ˆμ— 83 번 반볡
    69.780 μ΄ˆμ— 84 번 반볡
    67.812 μ΄ˆμ— 85 번 반볡
    68.895 μ΄ˆμ— 86 번 반볡
    71.086sμ—μ„œ μˆ˜ν–‰ 된 반볡 87
    68.809 μ΄ˆμ—μ„œ μˆ˜ν–‰ 된 반볡 88
    70.945 μ΄ˆμ— 89 번 반볡
    72.760 μ΄ˆμ— 90 번 반볡
    71.773sμ—μ„œ μˆ˜ν–‰λ˜λŠ” 반볡 91
    72.522 μ΄ˆμ— 92 번 반볡

μ—¬κΈ°μ„œ μ‹œκ°„μ€ 1,000 개의 URL을 μ²˜λ¦¬ν•˜λŠ” 반볡 μ‹œκ°„μ— ν•΄λ‹Ήν•©λ‹ˆλ‹€. μ‘°μ–Έν•˜μ‹­μ‹œμ˜€. 감사

outdated

κ°€μž₯ μœ μš©ν•œ λŒ“κΈ€

λ¬Έμ œκ°€ κΈ°λŒ€μ˜ λ¬Έμ œμΌκΉŒμš”? μ΄κ²ƒμ˜ 핡심은 "이것이 λ²„κ·Έμž…λ‹ˆκΉŒ, μ•„λ‹ˆλ©΄μ΄ μ‚¬μš© 사둀λ₯Ό μ§€μ›ν•˜λŠ” 데 μ‚¬μš©λ˜λŠ” λ‹€λ₯Έ λ°©λ²•μž…λ‹ˆκΉŒ?"인 것 κ°™μŠ΅λ‹ˆλ‹€. 그리고 아무도 ν™•μ‹€ν•˜μ§€ μ•Šμ€ 것 κ°™μŠ΅λ‹ˆλ‹€. μ§€κΈˆ λ‹Ήμž₯은 μ‚¬μš©μžμ—κ²Œ λ²„κ·Έμ²˜λŸΌ λ³΄μ΄λŠ” μ˜ˆμƒμΉ˜ λͺ»ν•œ ν–‰λ™μœΌλ‘œ 인해 μ•½κ°„μ˜ μ’Œμ ˆκ°μ—μ„œ λ‹¨μˆœνžˆ 라이브러리λ₯Ό μ‚¬μš©ν•˜μ§€ μ•ŠλŠ” 것에 이λ₯΄κΈ°κΉŒμ§€ λ‹€μ–‘ν•œ 응닡이 λ°œμƒν•œλ‹€κ³  μ£Όμž₯ν•©λ‹ˆλ‹€.

λͺ¨λ“  44 λŒ“κΈ€

μ–΄λ–€ λ²„μ „μ˜ aiohttpλ₯Ό μ‚¬μš©ν•˜μ‹­λ‹ˆκΉŒ? μ—΄λ¦° TCP 연결도 ν™•μΈν•˜μ‹­μ‹œμ˜€. μˆ«μžκ°€ μ¦κ°€ν•©λ‹ˆκΉŒ?

2017 λ…„ 4 μ›” 17 일 μ˜€ν›„ 12:46에 Vishal Goklani [email protected]이 λ‹€μŒκ³Ό 같이 μΌμŠ΅λ‹ˆλ‹€.

μ•„λž˜μ— λΉ λ₯Έ AsyncScraper 클래슀λ₯Ό μž‘μ„±ν–ˆμŠ΅λ‹ˆλ‹€.

κ°€μ Έ 였기 λ‘œκΉ…, λ‚ μ§œ μ‹œκ°„
μˆ˜μž… aiohttp
κ°€μ Έ 였기 asyncio
uvloop κ°€μ Έ 였기

asyncio.set_event_loop_policy (uvloop.EventLoopPolicy ())

둜거 = logging.getLogger (__ name__)
logger.setLevel (logging.INFO)
logging.basicConfig (ν˜•μ‹ = '% (asctime) s-% (name) s-% (levelname) s-% (message) s')
logger.addHandler (logging.StreamHandler ())

클래슀 AsyncScraper (객체) :
headers = { "User-Agent": 'Mozilla / 5.0 (Macintosh, Intel Mac OS X 10_9_2) AppleWebKit / 537.36 (Gecko와 같은 KHTML) Chrome / 34.0.1847.131 Safari / 537.36'}
def __init __ (self, number_workers = 100, max_connections = 1000, timeout = 10) :
self.number_workers = number_workers
self.max_connections = max_connections
self.timeout = μ‹œκ°„ 초과
self.work_queue = asyncio.Queue ()
self.cookie_jar = aiohttp.CookieJar (unsafe = True)
self.session = aiohttp.ClientSession (connector = aiohttp.TCPConnector (limit = self.max_connections, verify_ssl = False), cookie_jar = self.cookie_jar)

def __del __ (self) :
self.session.close ()

async def get_response (self, url) :
μ‹œν—˜:
aiohttp.Timeout (self.timeout) μ‚¬μš© :
μ‘λ‹΅μœΌλ‘œ self.session.get (url, allow_redirects = True, headers = AsyncScraper.headers)와 λΉ„ 동기화 :
content = await response.text ()
return { 'error': "", 'status': response.status, 'url': url, 'content': content, 'timestamp': str (datetime.datetime.utcnow ())}
μ˜ˆμ™Έλ₯Ό μ œμ™Έν•˜κ³  였λ₯˜ :
return { 'error': err, 'status': "", 'url': url, 'content': "", 'timestamp': str (datetime.datetime.utcnow ())}

async def consumer (self, worker_id) :
κ²°κ³Ό = []
self.work_queue.empty ()λŠ” μ•„λ‹ˆμ§€λ§Œ :
queue_url = self.work_queue.get () λŒ€κΈ°

      logger.debug("processing {} from worker_{}".format(queue_url, worker_id))
      response = await self.get_response(queue_url)
      logger.debug("received {} from worker_{}".format(queue_url, worker_id))
      if response['error'] is "":
          results.append(response)
  logger.debug("finished processing {} urls via worker_{}".format(len(results), worker_id))
  return results

def get_all (self, urls) :
[url의 url에 λŒ€ν•œ self.work_queue.put_nowait (url)]
tasks = asyncio.gather (* [self.consumer (worker_id) for worker_id in range (self.number_workers)], return_exceptions = True)
루프 = asyncio.get_event_loop ()
κ²°κ³Ό = loop.run_until_complete (μž‘μ—…)
return [__ for _ in results for __ in _]
두 가지 μ£Όμš” λ¬Έμ œκ°€ μžˆμŠ΅λ‹ˆλ‹€.

λ‹¨μˆœ URL λͺ©λ‘ (예 : 100k)을 μ „λ‹¬ν•˜λ©΄ μ‹œκ°„ 초과 였λ₯˜κ°€ λ°œμƒν•©λ‹ˆλ‹€.

그런 λ‹€μŒ URL을 1,000 개 λ‹¨μœ„λ‘œ 일괄 μ²˜λ¦¬ν•˜κ³  일괄 처리 κ°„μ˜ 응닡 μ‹œκ°„μ„ μΈ‘μ •ν–ˆμŠ΅λ‹ˆλ‹€. 그리고 μ‹œκ°„μ΄ 지남에 따라 μ„±λŠ₯이 μ €ν•˜λœλ‹€λŠ” 것을 λͺ…ν™•ν•˜κ²Œ μΈ‘μ • ν•  μˆ˜μžˆμ—ˆμŠ΅λ‹ˆλ‹€.

반볡 0은 16.991 μ΄ˆμ— μ™„λ£Œλ˜μ—ˆμŠ΅λ‹ˆλ‹€.
39.376 μ΄ˆμ— 반볡 1 μ™„λ£Œ
반볡 2λŠ” 35.656 μ΄ˆμ— μ™„λ£Œλ˜μ—ˆμŠ΅λ‹ˆλ‹€.
19.716sμ—μ„œ 반볡 3 μˆ˜ν–‰
29.331sμ—μ„œ 반볡 4 μˆ˜ν–‰
19.708sμ—μ„œ 반볡 5 μˆ˜ν–‰
19.572 μ΄ˆμ— 6 번 반볡
29.907sμ—μ„œ 반볡 7 μˆ˜ν–‰
23.379 μ΄ˆμ— 8 번 반볡
21.762 μ΄ˆμ— 9 번 반볡
22.091 μ΄ˆμ— 10 번 반볡
22.940 μ΄ˆμ— 11 번 반볡
31.285 μ΄ˆμ— 12 번 반볡
반볡 13은 24.549 μ΄ˆμ— μ™„λ£Œλ˜μ—ˆμŠ΅λ‹ˆλ‹€.
반볡 14λŠ” 26.297 μ΄ˆμ— μ™„λ£Œλ˜μ—ˆμŠ΅λ‹ˆλ‹€.
23.816 μ΄ˆμ— 15 번 반볡
29.094 μ΄ˆμ— 16 번 반볡
24.885 μ΄ˆμ— 17 번 반볡
26.456 μ΄ˆμ— 18 번 반볡
27.412sμ—μ„œ 19 번 반볡
29.969 μ΄ˆμ— 20 번 반볡
28.503 μ΄ˆμ— 21 번 반볡
28.699 μ΄ˆμ— 22 번 반볡
31.570 μ΄ˆμ— 23 번 반볡
31.898sμ—μ„œ 26 번 반볡
33.553 μ΄ˆμ— 27 번 반볡
34.022 μ΄ˆμ— 28 번 반볡
33.866 μ΄ˆμ— 29 번 반볡
36.351sμ—μ„œ 30 번 반볡
40.060 μ΄ˆμ— 31 번 반볡
35.523 μ΄ˆμ— 32 번 반볡
36.607 μ΄ˆμ— 33 번 반볡
36.325 μ΄ˆμ— 34 번 반볡
38.425 μ΄ˆμ— 35 번 반볡
39.106 μ΄ˆμ— 36 번 반볡
38.972 μ΄ˆμ— 37 번 반볡
39.845 μ΄ˆμ— 38 번 반볡
40.393sμ—μ„œ 39 회 반볡
40.734 μ΄ˆμ— 40 번 반볡
47.799 μ΄ˆμ— 41 번 반볡
43.070sμ—μ„œ μˆ˜ν–‰λ˜λŠ” 반볡 42
43.365 μ΄ˆμ— 43 번 반볡
42.081 μ΄ˆμ— 44 번 반볡
44.118 μ΄ˆμ— 45 번 반볡
44.955 μ΄ˆμ— 46 번 반볡
45.400 μ΄ˆμ— 47 번 반볡
45.987sμ—μ„œ 48 번 반볡
46.041sμ—μ„œ μˆ˜ν–‰ 된 반볡 49
45.899 μ΄ˆμ— 50 회 반볡
49.008sμ—μ„œ μˆ˜ν–‰λ˜λŠ” 반볡 51
49.544 μ΄ˆμ— 52 회 반볡
55.432 μ΄ˆμ— 53 번 반볡
52.590 μ΄ˆμ— 54 번 반볡
50.185 μ΄ˆμ— 55 번 반볡
52.858 μ΄ˆμ— 56 번 반볡
52.698sμ—μ„œ 57 회 반볡
53.048 μ΄ˆμ— 58 회 반볡
54.120 μ΄ˆμ— 59 번 반볡
54.151 μ΄ˆμ— 60 번 반볡
55.465 μ΄ˆμ— 61 번 반볡
56.889 μ΄ˆμ— 62 번 반볡
56.967 μ΄ˆμ— 63 번 반볡
57.690 μ΄ˆμ— 64 번 반볡
57.052 μ΄ˆμ— 65 번 반볡
67.214sμ—μ„œ μˆ˜ν–‰λ˜λŠ” 반볡 66
58.457 μ΄ˆμ— 67 번 반볡
60.882 μ΄ˆμ— 68 번 반볡
58.440 μ΄ˆμ— 69 번 반볡
60.755 μ΄ˆμ— 70 번 반볡
58.043sμ—μ„œ μˆ˜ν–‰λ˜λŠ” 반볡 71
65.076 μ΄ˆμ— 72 번 반볡
63.371 μ΄ˆμ— 73 번 반볡
62.800 μ΄ˆμ— 74 번 반볡
62.419 μ΄ˆμ— 75 번 반볡
61.376 μ΄ˆμ— 76 번 반볡
63.164sμ—μ„œ 77 번 반볡
65.443 μ΄ˆμ— 78 번 반볡
64.616 μ΄ˆμ— 79 번 반볡
69.544 μ΄ˆμ— 80 번 반볡
68.226sμ—μ„œ μˆ˜ν–‰λ˜λŠ” 반볡 81
78.050 μ΄ˆμ— 82 번 반볡
67.871 μ΄ˆμ— 83 번 반볡
69.780 μ΄ˆμ— 84 번 반볡
67.812 μ΄ˆμ— 85 번 반볡
68.895 μ΄ˆμ— 86 번 반볡
71.086sμ—μ„œ μˆ˜ν–‰ 된 반볡 87
68.809 μ΄ˆμ—μ„œ μˆ˜ν–‰ 된 반볡 88
70.945 μ΄ˆμ— 89 번 반볡
72.760 μ΄ˆμ— 90 번 반볡
71.773sμ—μ„œ μˆ˜ν–‰λ˜λŠ” 반볡 91
72.522 μ΄ˆμ— 92 번 반볡

μ—¬κΈ°μ„œ μ‹œκ°„μ€ 1,000 개의 URL을 μ²˜λ¦¬ν•˜λŠ” 반볡 μ‹œκ°„μ— ν•΄λ‹Ήν•©λ‹ˆλ‹€. μ‘°μ–Έν•˜μ‹­μ‹œμ˜€. 감사

β€”
이 μŠ€λ ˆλ“œλ₯Ό κ΅¬λ…ν–ˆκΈ° λ•Œλ¬Έμ—μ΄ λ©”μ‹œμ§€κ°€ μ „μ†‘λ˜μ—ˆμŠ΅λ‹ˆλ‹€.
이 이메일에 직접 λ‹΅μž₯ν•˜κ±°λ‚˜ GitHub https://github.com/aio-libs/aiohttp/issues/1821 μ—μ„œ λ³΄κ±°λ‚˜ https://github.com/notifications/unsubscribe-auth/AAkjzsPpQtk7SDgKmTUKUblSZ0Bfu1lVks5rw8GTgaJpZM4M_fXe μ—μ„œ μŠ€λ ˆλ“œλ₯Ό μŒμ†Œκ±°

μ €λŠ” '2.0.5'λ₯Ό μ‚¬μš©ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€. μ—΄λ¦° TCP 연결을 μ–΄λ–»κ²Œ ν™•μΈν•©λ‹ˆκΉŒ?

μ–΄λ–€ λ²„μ „μ˜ νŒŒμ΄μ¬μ„ μ‚¬μš©ν•˜μ‹­λ‹ˆκΉŒ?

연결을 ν™•μΈν•˜λ €λ©΄ "netstat"λͺ…령을 μ‚¬μš©ν•˜μ—¬ λͺ‡ 가지 츑정을 μˆ˜ν–‰ν•˜μ‹­μ‹œμ˜€.

2017 λ…„ 4 μ›” 17 일 μ˜€ν›„ 12μ‹œ 50 뢄에 Vishal Goklani [email protected] 은 λ‹€μŒκ³Ό 같이 μΌμŠ΅λ‹ˆλ‹€.

μ €λŠ” '2.0.5'λ₯Ό μ‚¬μš©ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€. μ—΄λ¦° TCP 연결을 μ–΄λ–»κ²Œ ν™•μΈν•©λ‹ˆκΉŒ?

β€”
λŒ“κΈ€μ„ λ‹¬μ•˜ κΈ° λ•Œλ¬Έμ— μˆ˜μ‹  ν•œ κ²ƒμž…λ‹ˆλ‹€.
이 이메일에 직접 λ‹΅μž₯ν•˜κ±°λ‚˜ GitHub https://github.com/aio-libs/aiohttp/issues/1821#issuecomment-294571709 μ—μ„œ λ³΄κ±°λ‚˜ https://github.com/notifications/unsubscribe-auth/ μŠ€λ ˆλ“œλ₯Ό μŒμ†Œκ±°ν•©λ‹ˆλ‹€.

파이썬 3.6.0을 μ‚¬μš©ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€.

μ½”λ“œμ—μ„œ λͺ…λ°±ν•œ μ‹€μˆ˜λ₯Όν•˜κ³  μžˆμŠ΅λ‹ˆκΉŒ?

λ‚˜λŠ” λͺ…λ°±ν•œ 것을 보지 λͺ»ν•œλ‹€. aiohttp의 μ–΄λ–€ 뢀뢄이 문제의 원인인지 λͺ…ν™•νžˆν•˜κ³  μ‹ΆμŠ΅λ‹ˆλ‹€.
λ˜ν•œ python3.6은 SSL μ†ŒμΌ“μ„ λˆ„μΆœν•©λ‹ˆλ‹€.

2017 λ…„ 4 μ›” 17 일 μ˜€ν›„ 3:02에 Vishal Goklani [email protected] 은 λ‹€μŒκ³Ό 같이 μΌμŠ΅λ‹ˆλ‹€.

μ½”λ“œμ—μ„œ λͺ…λ°±ν•œ μ‹€μˆ˜λ₯Όν•˜κ³  μžˆμŠ΅λ‹ˆκΉŒ?

β€”
λŒ“κΈ€μ„ λ‹¬μ•˜ κΈ° λ•Œλ¬Έμ— μˆ˜μ‹  ν•œ κ²ƒμž…λ‹ˆλ‹€.
이 이메일에 직접 λ‹΅μž₯ν•˜κ±°λ‚˜ GitHub https://github.com/aio-libs/aiohttp/issues/1821#issuecomment-294607188 μ—μ„œ λ³΄κ±°λ‚˜ https://github.com/notifications/unsubscribe-auth/ μŠ€λ ˆλ“œλ₯Ό μŒμ†Œκ±°ν•©λ‹ˆλ‹€.

ν…ŒμŠ€νŠΈλ₯Ό 돕기 μœ„ν•΄ μ œκ°€ νŠΉλ³„νžˆ ν•  μˆ˜μžˆλŠ” 일이 μžˆμŠ΅λ‹ˆκΉŒ? netstat둜 무엇을 μ›ν•˜λŠ”μ§€ 잘 λͺ¨λ₯΄κ² μŠ΅λ‹ˆλ‹€.

μ—΄λ¦° μ—°κ²° μˆ˜κ°€ μ¦κ°€ν•©λ‹ˆκΉŒ?

Linux의 경우-첫 번째, 두 번째, 쀑간 및 λ§ˆμ§€λ§‰ URL 청크λ₯Ό μ²˜λ¦¬ν•˜λŠ” λ™μ•ˆ μ½˜μ†”μ—μ„œ μ‹€ν–‰

PID = pid_of_server
netstat -npt | grep $ PID / | ν™”μž₯μ‹€ -l

λ‚˜λŠ” 이것을 λ§Œλ‚¬λ‹€. μ œν•œμ΄ 100 인 TCPConnecterλ₯Ό μ‚¬μš©ν•˜λŠ” 10,000 개의 비동기 μš”μ²­μ€ μ²˜μŒμ—λŠ” 잘 μ‹œμž‘λ˜μ§€λ§Œ μ¦‰μ‹œ netstat λ₯Ό 톡해 ν‘œμ‹œλ˜λŠ” 연결이 μ‚¬λΌμ§‘λ‹ˆλ‹€. κΈ΄ κΌ¬λ¦¬μ΄μ§€λ§Œ κ²°κ΅­ 0 에 λ„λ‹¬ν•˜κ³  λ‚˜λ¨Έμ§€ λͺ¨λ“  μš”μ²­μ΄ λ°œμƒν•©λ‹ˆλ‹€.

asyncio.Semaphore λ₯Ό μ‚¬μš©ν•˜μ—¬ μ œν•œ 속도λ₯Ό μ§€μ •ν•˜λ©΄μ΄ 문제λ₯Ό ν•΄κ²°ν•  μˆ˜μžˆλŠ” 것 κ°™μŠ΅λ‹ˆλ‹€ ( netstat 보고 κΈ°κ°„ λ™μ•ˆ μ œν•œμ— κ°€κΉŒμ›€). λ‚˜λŠ” 비ꡐ적 aio python을 μ‚¬μš©ν•˜μ§€λ§Œ, κ·Έλž˜μ„œ λΉ„μš©μ΄ μ–Όλ§ˆμΈμ§€ ν™•μ‹€ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

νŽΈμ§‘ : Python 3.5.2κ°€μžˆλŠ” Ubuntu 16.04μ—μ„œ λ‹€μŒμ„ μ‚¬μš©ν•˜μ—¬ λ³΄μ•˜μŠ΅λ‹ˆλ‹€.

aiohttp==2.0.7
appdirs==1.4.3
async-timeout==1.2.1
chardet==3.0.3
multidict==2.1.5
packaging==16.8
pyparsing==2.2.0
six==1.10.0
yarl==0.10.2

@vgoklani @mal μ‹œκ°„ 초과λ₯Ό λΉ„ν™œμ„±ν™”ν•˜λŠ” λ™μΌν•œ ν…ŒμŠ€νŠΈλ₯Ό μ‹œλ„ν•΄ λ³Ό 수 μžˆμŠ΅λ‹ˆκΉŒ? 이상적인 것은 μ•„λ‹ˆμ§€λ§Œ 였λ₯˜κ°€ μž‘μ—… μ·¨μ†Œ λ˜λŠ” λ‹€λ₯Έ 이유둜 μΈν•œ 것인지 ν™•μΈν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€.

session.request ν˜ΈμΆœμ—μ„œ timeout=None λ₯Ό μ‚¬μš©ν•˜μ—¬ λ‹€μ‹œ μ‹€ν–‰ν–ˆμ§€λ§Œ λ™μž‘μ΄ λ³€κ²½λ˜μ§€ μ•Šμ€ 것 κ°™μœΌλ©° 연결이 μ—¬μ „νžˆ λŠμ–΄μ‘ŒμŠ΅λ‹ˆλ‹€. ν…ŒμŠ€νŠΈ μΌ€μ΄μŠ€λ₯Ό μ•½κ°„ μ •λ¦¬ν•˜κ³  λ‘œμ»¬μ—μ„œ μž¬ν˜„ ν•  수 μžˆλ„λ‘ν–ˆμŠ΅λ‹ˆλ‹€. λ„μ›€μ΄λ˜κΈ°λ₯Ό λ°”λžλ‹ˆλ‹€ : https://gist.github.com/mal/53506cd81fa27c39afc4f7fbef7b7b5a

FWIWλŠ” λ‘œμ»¬μ—μ„œ asyncio.Semaphoreλ₯Ό μ‚¬μš©ν•˜μ—¬ μ•½ 4 λ°° 더 λΉ λ₯΄κ²Œ μš”μ²­μ„ μ‹€ν–‰ν•©λ‹ˆλ‹€.

3.5.2둜 μ‹œλ„ν•˜μ—¬ SSL λˆ„μΆœκ³Ό 관련이 μžˆλŠ”μ§€ ν™•μΈν•˜λŠ” 것이 μ’‹μŠ΅λ‹ˆλ‹€. λ˜ν•œ μ—¬λŸ¬ μž‘μ—…μ„ λ³‘λ ¬λ‘œ μˆ˜ν–‰ν•˜κΈ° μœ„ν•΄ https://gist.github.com/thehesiod/7081ab165b9a0d4de2e07d321cc2391d 와 같은 νŒ¨ν„΄μ„ μ‚¬μš©ν•©λ‹ˆλ‹€

@thehesiod 3.5.2λ₯Ό μ‹€ν–‰ν•˜λŠ” λ™μΌν•œ λ¬Έμ œκ°€ μžˆμŠ΅λ‹ˆλ‹€. 이 슀 λ‹ˆνŽ«μ„ λ°€μƒˆ μ‹€ν–‰ν–ˆμŠ΅λ‹ˆλ‹€.

async def page_get(url):
    while True:
        try:
            t = time.time()
            async with aiohttp.request("GET", url) as req:
                resp_content = await req.read()
            print(time.time() - t, "seconds taken")
        except Exception as e:
            print(str(datetime.datetime.now()) + " - Connection error: {0}".format(str(e)))
        await asyncio.sleep(2)

if __name__ == "__main__":
    loop = asyncio.get_event_loop()
    loop.run_until_complete(asyncio.wait([page_get('http://www.google.com')]))

0.05777549743652344 초 μ†Œμš”
0.05143165588378906 초 걸림
0.045487165451049805 초 걸림
0.0573725700378418 초 μ†Œμš”
0.049524545669555664 초 걸림

였늘 λ‚΄κ°€ 그것을 ν™•μΈν–ˆμ„ λ•Œ λ‚˜λŠ” λ‹€μŒμ„ μ–»μ—ˆμŠ΅λ‹ˆλ‹€.

1.3857007026672363 초 걸림
0.47487688064575195 초 걸림
0.23848772048950195 초 걸림
2.2507810592651367 초 μ†Œμš”
0.25020551681518555 초 걸림
0.12477540969848633 초 μ†Œμš”
2.4836790561676025 초 걸림
1.1492459774017334 초 걸림

@thehesiod λ‚΄κ°€ 3.5.2 , 3.5.3 에 λŒ€ν•΄ κ²Œμ‹œ ν•œ ν…ŒμŠ€νŠΈ μΌ€μ΄μŠ€λ₯Ό μ‹€ν–‰ν•˜κ³  3.6.1 쒋은 μΈ‘μ • 값에 λŒ€ν•΄ λͺ¨λ‘ 7k 마크 μ£Όλ³€μ—μ„œ λ™μΌν•œ μ €ν•˜λ₯Ό λ³΄μ—¬μ€λ‹ˆλ‹€.

pyvmmonitor둜 λΉ λ₯΄κ³  느릴 λ•Œ μŠ€λƒ… 샷을 찍어도 λ κΉŒμš”?

μ–΄λ–€ 이유둜 λ“  pyvmmonitorλŠ” 곡을 μΉ˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€ (X11 문제, Python λͺ¨λ“ˆ λˆ„λ½, μ–ΈκΈ‰λ˜μ§€ μ•Šμ€ 곡유 객체 파일 λˆ„λ½). λ„μ›€μ΄λœλ‹€λ©΄ cProfilesλ₯Ό μ œκ³΅ν•˜κ²Œλ˜μ–΄ κΈ°μ©λ‹ˆλ‹€.ν•˜μ§€λ§Œ pyvmmonitor 좜λ ₯이 ν•„μš”ν•œ 경우 κ°€μž₯ 쒋은 방법은 ν…ŒμŠ€νŠΈ μΌ€μ΄μŠ€λ₯Ό 직접 μ‹€ν–‰ν•˜λŠ” 것 κ°™μŠ΅λ‹ˆλ‹€. μ£„μ†‘ν•©λ‹ˆλ‹€.

λ¬Όλ‘  κ·Έλ ‡κ²Œ λ§ν•˜μžλ§ˆμž 무엇이 잘λͺ»λ˜μ—ˆλŠ”지 κΉ¨λ‹¬μ•˜μŠ΅λ‹ˆλ‹€. > _ <

이제 ν…ŒμŠ€νŠΈ μΌ€μ΄μŠ€ μ—λŠ” λΉ λ₯΄κ³  느린 λ³€ν˜• (fast = semaphore, slow = limit param)κ³Ό 각각 μ‹€ν–‰λ˜λŠ” pstat 파일이 ν¬ν•¨λ©λ‹ˆλ‹€.

μ’‹μŠ΅λ‹ˆλ‹€. 도움이 될 κ²ƒμž…λ‹ˆλ‹€. κ°μ‚¬ν•©λ‹ˆλ‹€!

느린 κ²½μš°μ—λŠ” μ–΄λ–€ 이유둜 λ“  μ‹œκ°„μ˜ 60 %κ°€ select.epoll μ†ŒλΉ„λ©λ‹ˆλ‹€. λ…ΈνŠΈλΆ λͺ¨λ‹ˆν„°μ—μ„œλŠ” 아직 λΉ λ₯Έ μΌ€μ΄μŠ€μ—μ„œλ„ 찾을 수 μ—†μŠ΅λ‹ˆλ‹€. λ˜ν•œ slow.pyμ—μ„œ 연결을 ν’€λ‘œ λ°˜ν™˜ν•˜κΈ° 전에 연결을 λΉ„μš°μ§€ μ•ŠλŠ” κ²ƒμœΌλ‘œ λ‚˜νƒ€λ‚¬μŠ΅λ‹ˆλ‹€ (λ³Έλ¬Έ 읽기). 이제 ClientResponse.__aexit__ μ˜ν•΄ μžλ™μœΌλ‘œ μˆ˜ν–‰λ˜λŠ”μ§€ μžŠμ–΄ λ²„λ ΈμŠ΅λ‹ˆλ‹€. λΉ λ₯Έ 속도와 느린 속도 μ‚¬μ΄μ—λŠ” μ œν•œμ„ ν†΅κ³Όν•˜μ§€ λͺ»ν•˜λ―€λ‘œ '느림'이 aiohttpκ°€ 풀에 λŒ€ν•œ 연결을 λ°˜ν™˜ν•˜κΈ°λ₯Ό 기닀리고 μžˆλ‹€κ³  μƒκ°ν•©λ‹ˆλ‹€. @ fafhrd91 아이디어가 μžˆμŠ΅λ‹ˆκΉŒ?

@mal SSLκ³Ό λΉ„ SSL을 확인 ν–ˆμŠ΅λ‹ˆκΉŒ? 문제λ₯Ό μ’νžˆλŠ” 데 도움이 될 κ²ƒμž…λ‹ˆλ‹€

SSL 만 https://github.com/python/cpython/pull/2270 으둜 μ‹œλ„ν•˜λ €λŠ” 경우

μ§€μ—°λ˜μ–΄ μ£„μ†‘ν•©λ‹ˆλ‹€. μ§€λ‚œμ£Όμ— νœ΄κ°€ μ€‘μ΄μ—ˆμŠ΅λ‹ˆλ‹€. SSL λŒ€ λΉ„ SSL을 μ‹œλ„ν•˜μ§€ μ•Šμ•˜μ§€λ§Œ λ‚΄κ°€ μ‚¬μš©ν–ˆλ˜ ν…ŒμŠ€νŠΈ μΌ€μ΄μŠ€λŠ” HTTPSκ°€ μ•„λ‹Œ 일반 HTTPμž…λ‹ˆλ‹€. HTTPS의 μΆ”κ°€ μ˜€λ²„ ν—€λ“œλ‘œ μ„±λŠ₯이 더 μ’‹μ•„μ§ˆ 것이라고 μ˜μ‹¬ ν•  μ΄μœ κ°€ μžˆμŠ΅λ‹ˆκΉŒ?

그래. κ·Έλƒ₯ https인지 ν™•μΈν•œλ‹€κ³  μƒκ°ν•˜μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€. κΈ°μ‘΄ 문제둜만 μ„€λͺ… ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

μ—¬λŸ¬λΆ„μ€ μƒˆλ‘œμš΄ aiohttp 2.2.0 λ¦΄λ¦¬μŠ€μ— λŒ€ν•΄ ν…ŒμŠ€νŠΈ ν•  수 μžˆμŠ΅λ‹ˆκΉŒ?

2.2.0 문제λ₯Ό μ‚¬μš©ν•˜μ—¬ ν…ŒμŠ€νŠΈ μΌ€μ΄μŠ€λ₯Ό λ‹€μ‹œ μ‹€ν–‰ν•˜κΈ° λ§Œν•˜λ©΄λ©λ‹ˆλ‹€. 😞

κ·Έλƒ₯-싀행을 λ‹€μ‹œ ν…ŒμŠ€νŠΈ μΌ€μ΄μŠ€ 에 λŒ€ν•œ 2.3.6 λ‚΄λΆ€ ν•œκ³„κ°€ μžˆμ—ˆλ‹€ 10,000의 총 μ‹œκ°„μ˜ κ²°κ³Όλ₯Ό μ‚¬μš©ν•˜μ—¬ λ¬Έμ œλŠ”μ΄ μ΅œμ‹  μ•ˆλͺ©μœΌλ‘œ πŸ™ μ—¬μ „νžˆ 쑴재 함을 확인할 수 μžˆμŠ΅λ‹ˆλ‹€ ~ 4 λ°° 느린 ( 20.13s ) μˆ˜λ™μœΌλ‘œ κ΅¬ν˜„ 된 μ„Έλ§ˆν¬μ–΄ μ ‘κ·Ό 방식 ( 5.83 )보닀.

@ aio-libs / aiohttp-committers의 아무도 λ¨Όμ € 문제λ₯Ό ν•΄κ²°ν•˜μ§€ μ•ŠμœΌλ©΄ μ‹œκ°„μ„ 찾으렀고 λ…Έλ ₯ν•  κ²ƒμž…λ‹ˆλ‹€.

@dionhaefner κ°€ https://github.com/DHI-GRAS/itsybitsy/issues/1μ—μ„œ μˆ˜μ • ν•œ 것 κ°™μŠ΅λ‹ˆλ‹€. 여기에 μ •λ³΄κ°€μžˆμ„ 수 μžˆμŠ΅λ‹ˆκΉŒ?

μ •ν™•νžˆ μˆ˜μ •λ˜μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€. limit ν‚€μ›Œλ“œ λŒ€μ‹  속도 μ œν•œμ„ μœ„ν•΄ Semaphoreλ₯Ό μ‚¬μš©ν•˜κΈ° μœ„ν•΄ @mal 의 ν•΄κ²° 방법을 μ‚¬μš©ν–ˆμŠ΅λ‹ˆλ‹€.

sem = asyncio.Semaphore(max_connections)
connector = aiohttp.TCPConnector(limit=None)
session = aiohttp.ClientSession(connector=connector)

async def get_page(url):
    async with sem:
        async with session.get(url):
            ...

λ‚˜λ₯Ό μœ„ν•΄ 잘 μˆ˜ν–‰ν•©λ‹ˆλ‹€.

@dteh 응닡 μ‹œκ°„μ΄ 크게 λ‹€λ₯Ό 수 μžˆμœΌλ―€λ‘œ google.com에 λŒ€ν•œ 연결을 ν…ŒμŠ€νŠΈ μΌ€μ΄μŠ€λ‘œ μ‚¬μš©ν•˜κΈ°κ°€ μ–΄λ ΅μŠ΅λ‹ˆλ‹€. 둜컬 μ„œλ²„λ‘œ λ‹€μ‹œ μ‹œλ„ν•˜λŠ” 것이 μ’‹μŠ΅λ‹ˆλ‹€.

@mal μ €λŠ” @asvetlov κ°€ λΉ„ μ„Έλ§ˆν¬μ–΄ κ²½μš°μ— λŒ€ν•΄ μ–ΈκΈ‰ν•˜λ„λ‘ ν• 

asyncio.Semaphore , asyncio.Queue 및 aiohttp.BaseConnector.connect κ΅¬ν˜„μ€ λ™μ‹œ μ—°κ²° 수λ₯Ό μ œν•œν•˜λŠ” 역압을 ν—ˆμš©ν•˜λŠ” λ™μΌν•œ νŒ¨ν„΄μ„ κ³΅μœ ν•˜κ³  맀우 λ™μΌν•œ κ΅¬ν˜„μ„ κ°–μŠ΅λ‹ˆλ‹€. κ·Έλž˜μ„œ:

1) aiohttp.BaseConnector.connect μ—λŠ” μ—°κ²° μ œν•œμ„ κ΅¬ν˜„ν•˜λŠ” 버그가 μžˆμŠ΅λ‹ˆλ‹€.
2) .get 와 .connect ν•¨μˆ˜ 사이에 연결이 μ œν•œ 될 λ•Œ λ‚˜νƒ€λ‚˜λŠ” 버그가 있으며 μ™ΈλΆ€ μ„Έλ§ˆν¬μ–΄λ₯Ό μ‚¬μš©ν•˜μ—¬ ν•΄κ²°λ©λ‹ˆλ‹€ (배압은 μ²˜μŒμ— λ§Œλ“€μ–΄μ§‘λ‹ˆλ‹€).
3) 기타.

@thehesiod λ‚΄κ°€ 이것을 λ³Έ 지 limit 맀개 λ³€μˆ˜κ°€ 무엇을 μ˜λ―Έν•˜λŠ”μ§€ μ˜λ¬Έμ„ κ°€μ§ˆ κ²ƒμž…λ‹ˆλ‹€. μ™œλƒν•˜λ©΄ (λ©”λͺ¨λ¦¬μ—μ„œ) 식별 된 μ‚¬μš© 사둀λ₯Ό 지원할 κ²ƒμ΄λΌλŠ” μ„€λͺ…이 있기 λ•Œλ¬Έμž…λ‹ˆλ‹€. κ·Έλ ‡κ²Œ μ„€κ³„λ˜μ§€ μ•Šμ•˜λ‹€λ©΄ κ³ λ €ν•  μˆ˜μžˆλŠ” κΈ°λŠ₯μΌκΉŒμš”?

λ‚˜μ—κ²ŒλŠ”μ΄ λ¬Έμ œκ°€ μž‘λ™ν•˜μ§€λ§Œ μ™„λ²½ν•˜μ§€ μ•Šμ„ μˆ˜μžˆλŠ” μ†”λ£¨μ…˜ 배포λ₯Ό κ³ λ €ν• λ§ŒνΌ μΆ©λΆ„νžˆ 차단 된 것 κ°™μŠ΅λ‹ˆλ‹€. λ‚˜λŠ” 그것이 1 λ…„ λ™μ•ˆ 거기에 있고 λ§Žμ€ 뢈만이 μ—†μ—ˆμ§€λ§Œ ... aiohttp둜 ν”„λ‘œλ•μ…˜μ„ μ‹€ν–‰ν•˜λ €λŠ” μ‚¬λžŒλ“€μ„ μƒμƒν•΄λ³΄μ‹­μ‹œμ˜€. 그런 문제둜 인해 ν•  수 μ—†μŠ΅λ‹ˆλ‹€.

@asvetlov μ €λŠ”μ΄ 문제λ₯Ό λ‹€μ‹œ ν™•μΈν•˜κ³  ν™•μΈν•œ λ‹€μŒμ΄ μˆ˜λ™ μ„Έλ§ˆν¬μ–΄ λ©”μ»€λ‹ˆμ¦˜μ„ μœ μ§€ κ΄€λ¦¬λ˜λŠ” λͺ¨λ“  λ²„μ „μ˜ aiohttp에 직접 적용 ν•  것을 μ œμ•ˆν•©λ‹ˆλ‹€ (ν•΄κ²°ν•˜λŠ” κ°€μž₯ 쒋은 방법 인 것 κ°™μŠ΅λ‹ˆλ‹€). ν•„μš”ν•œ 경우 λ‚˜μ€‘μ— κ°œμ„  / ꡐ체 ν•  수 μžˆμŠ΅λ‹ˆλ‹€. μ–΄λ–»κ²Œ 생각해?

aiohttp λ²„κ·Έκ°€μžˆλŠ” 경우 @pfreixes은 μ£Όμ„μœΌλ‘œ - 그것은 κ³ μ •λ˜μ–΄μ•Όν•œλ‹€.
λ¨Όμ € 무슨 일이 μΌμ–΄λ‚˜κ³  μžˆλŠ”μ§€ μ•Œμ•„ λ‚΄μ•Όν•©λ‹ˆλ‹€.

@mal μ œν•œ 맀개 λ³€μˆ˜λŠ” 일반적으둜 μ–΄λ–€ μœ ν˜•μ˜ μ••λ ₯을 μ μš©ν•˜λŠ” 것이 μ•„λ‹ˆλΌ λ™μ‹œ μ—°κ²° 수λ₯Ό μ œν•œν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€. 참고둜 aiohttpλ₯Ό μ‚¬μš©ν•˜μ—¬ μˆ˜λ…„ λ™μ•ˆ μ—¬λŸ¬ μ„œλΉ„μŠ€μ— 걸쳐 prod ν™˜κ²½μ—μ„œ 맀일 수백만 건의 μš”μ²­μ„ μž‘μ„±ν–ˆμœΌλ©° μž‘μ—…μž ν’€ 및 μ„Έλ§ˆν¬μ™€ 같은 것을 μ‚¬μš©ν•˜μ—¬μ΄ λ¬Έμ œκ°€ λ°œμƒν•˜μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€.

λ¬Έμ œκ°€ κΈ°λŒ€μ˜ λ¬Έμ œμΌκΉŒμš”? μ΄κ²ƒμ˜ 핡심은 "이것이 λ²„κ·Έμž…λ‹ˆκΉŒ, μ•„λ‹ˆλ©΄μ΄ μ‚¬μš© 사둀λ₯Ό μ§€μ›ν•˜λŠ” 데 μ‚¬μš©λ˜λŠ” λ‹€λ₯Έ λ°©λ²•μž…λ‹ˆκΉŒ?"인 것 κ°™μŠ΅λ‹ˆλ‹€. 그리고 아무도 ν™•μ‹€ν•˜μ§€ μ•Šμ€ 것 κ°™μŠ΅λ‹ˆλ‹€. μ§€κΈˆ λ‹Ήμž₯은 μ‚¬μš©μžμ—κ²Œ λ²„κ·Έμ²˜λŸΌ λ³΄μ΄λŠ” μ˜ˆμƒμΉ˜ λͺ»ν•œ ν–‰λ™μœΌλ‘œ 인해 μ•½κ°„μ˜ μ’Œμ ˆκ°μ—μ„œ λ‹¨μˆœνžˆ 라이브러리λ₯Ό μ‚¬μš©ν•˜μ§€ μ•ŠλŠ” 것에 이λ₯΄κΈ°κΉŒμ§€ λ‹€μ–‘ν•œ 응닡이 λ°œμƒν•œλ‹€κ³  μ£Όμž₯ν•©λ‹ˆλ‹€.

@mal μ½”λ“œλ₯Ό 더 읽은 ν›„ 두 μ½”λ“œ 경둜λ₯Ό μ–Όλ§ˆλ‚˜ λΉ„μŠ·ν•˜κ²Œ λ§Œλ“€ μ—ˆλŠ”μ§€ 깨닫지 λͺ»ν–ˆμŠ΅λ‹ˆλ‹€. 두 경우 λͺ¨λ‘ λ™μΌν•œ 수의 λ―Έν•΄κ²° μž‘μ—…μ΄ 있고, ν•œ κ²½μš°μ—λŠ” μ„Έλ§ˆν¬μ–΄μ—μ„œ 차단 ν•΄μ œλ₯Ό 기닀리고 μžˆμŠ΅λ‹ˆλ‹€. TCPConnector μ œν•œμ— λ‹€λ₯Έ. λΉ λ₯Έ μΌ€μ΄μŠ€κ°€ LIMITλ₯Ό μ‚¬μš©ν•˜λ„λ‘ 또 λ‹€λ₯Έ 변경을 μˆ˜ν–‰ν•˜μ—¬ 두 μΌ€μ΄μŠ€κ°€ μœ μ‚¬ν•˜κ³  aiohttp의 문제λ₯Ό κ°€λ¦¬ν‚€λŠ” λΉ λ₯Έ μΌ€μ΄μŠ€μ˜ μ„±λŠ₯에 영ν–₯을 λ―ΈμΉ˜μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€.

κ·Έλž˜μ„œ 이것은 λ‹€μ†Œ ν₯λ―Έ λ‘­μŠ΅λ‹ˆλ‹€. μ„±λŠ₯ 좔적에 따라 selectors.py:select λ©”μ„œλ“œλ‘œ 인해 μž‘μ—…μ΄ 느리게 μ‹€ν–‰λœλ‹€λŠ” 것을 μ•Œκ³  μžˆμœΌλ―€λ‘œ (λΉ λ₯Έ 좔적에 ν‘œμ‹œλ˜μ§€λ„ μ•ŠμŒ) aiohttpκ°€ μ œμ•ˆν•œλŒ€λ‘œ 연결을 μ°¨μ„ μœΌλ‘œ μ œν•œν•˜λŠ” κ²ƒμ²˜λŸΌ λ“€λ¦½λ‹ˆλ‹€. λ‚˜λŠ” 이제 이것이 ν™•μ‹€νžˆ aiohttp의 μ„±λŠ₯ 문제라고 μƒκ°ν•©λ‹ˆλ‹€. BaseConnector의 웨이터 λ©”μ»€λ‹ˆμ¦˜ λ•Œλ¬Έμ΄λΌκ³  μƒκ°ν•©λ‹ˆλ‹€. μ²˜μŒμ— LIMIT 연결이 생성 된 λ‹€μŒ LIMIT * 99 κ°€ "λŒ€κΈ°μž"둜 λλ‚˜λŠ” 것을 상상할 수 μžˆμŠ΅λ‹ˆλ‹€. 이것이 κ°„λ‹¨ν•œ μ„Έλ§ˆν¬μ–΄ λ˜λŠ” 쑰건으둜 λŒ€μ²΄ 될 수 μžˆλŠ”μ§€ κΆκΈˆν•©λ‹ˆλ‹€.

κ·€ν•˜μ˜ μ˜ˆμ— λŒ€ν•΄ 가정을 ν•œ 것에 λŒ€ν•΄ μ‚¬κ³Όλ“œλ¦½λ‹ˆλ‹€. 이 문제λ₯Ό μ•Œλ € μ£Όμ…”μ„œ λ‹€μ‹œ ν•œ 번 κ°μ‚¬λ“œλ¦½λ‹ˆλ‹€! λ‚˜λŠ” 였늘 이것을 μ•½κ°„ μ‹€ν—˜ ν•  μ‹œκ°„μ΄μžˆμ„ 것이라고 μƒκ°ν•˜μ§€λ§Œ @asvetlov κ°€ 이것을 λ³„λ„λ‘œ 좔ꡬ ν•  수 있기λ₯Ό λ°”λžλ‹ˆλ‹€. λ‚˜λŠ” κΈ°κ³ μžλŠ” μ•„λ‹ˆμ§€λ§Œ 이해 κ΄€κ³„μžμž…λ‹ˆλ‹€. :)

κ·Έλž˜μ„œ 두 μ‚¬λ‘€μ˜ 속도λ₯Ό 크게 λ†’μ΄λŠ” PR을 λ§Œλ“€μ—ˆμŠ΅λ‹ˆλ‹€. μ΄κ²ƒμ΄ν•˜λŠ” 일은 μ˜ˆμ™Έκ°€ μ•„λ‹Œ κ²½μš°μ— 웨이터 λͺ©λ‘μ„ 톡해 λ¦¬μŠ€νŒ…μ„ ν”Όν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€.

λ‚΄ μ»΄ν“¨ν„°μ—μ„œλŠ” 느린 경우 ~ 13 μ΄ˆμ—μ„œ 3 초둜 λ³€κ²½λ˜μ—ˆμŠ΅λ‹ˆλ‹€.

λˆ„κ΅¬λ“ μ§€ λ‚΄ PR의 κ²°κ³Όλ₯Ό ν™•μΈν•˜κ³  μ‹ΆμŠ΅λ‹ˆκΉŒ?

# 2937 및 # 2964둜 μˆ˜μ •ν•΄μ•Όν•©λ‹ˆλ‹€.

이 μŠ€λ ˆλ“œλŠ” λ‹«νžŒ ν›„ 졜근 ν™œλ™μ΄ μ—†μ—ˆκΈ° λ•Œλ¬Έμ— μžλ™μœΌλ‘œ μž κ²ΌμŠ΅λ‹ˆλ‹€. κ΄€λ ¨ 버그에 λŒ€ν•΄ [μƒˆ 문제]λ₯Όμ—¬μ‹­μ‹œμ˜€.
이 ν† λ‘ μ—μ„œ μ€‘μš”ν•œ 점이 μžˆλ‹€κ³  μƒκ°λ˜λ©΄ [μƒˆ 호]에 ν•΄λ‹Ή μ˜ˆμ™Έ 사항을 ν¬ν•¨ν•˜μ‹­μ‹œμ˜€.

이 νŽ˜μ΄μ§€κ°€ 도움이 λ˜μ—ˆλ‚˜μš”?
0 / 5 - 0 λ“±κΈ‰