Python과 동기화된 수십억 개의 전자 메일 메시지

전자 우편 동기화 엔진을 개발하는 것은 매우 어렵다.Python은 그것을 쉽게 한다.
닐라스에서 우리의 사랑은 비밀이 아니다.우리의 전자 우편 동기화 엔진은 완전히 Python으로 구축되어 고객을 위해 100여 억 개의 전자 우편을 동기화하고 서비스하는 것을 책임진다.
왜?답은 간단하다. 파이썬은 표준적이고 믿을 만하며, (우리 같은 초창기 회사에는) 지루하다.이것은 우리가 전 세계 각지의 개발자들에게 유연하고 안정적인 API를 제공할 수 있는 간단한 해결 방안이다.
PyBay 2017에서 저는 왜 Python의 무미건조성은 천성적으로 합작에 유리한지 이야기했습니다. 복잡한 제품을 구축하는 회사에 있어서 Python 구동 솔루션은 혁신에 가장 안정적인 기반을 다졌습니다.

모든 것Python 전자 우편은 매우 어렵다


이메일 프로토콜은 SaaS 응용 프로그램과 간단한 동기화를 위해 하나의 프로토콜만 사용하면 대량의 문서가 필요하다는 변덕스러움으로 유명하다.개발자가 전자 우편이 다양한 전자 우편 표준과 협동하여 작동하기를 원한다면, 해석, 인코딩, 신분 검증 등 문제 외에도 많은 문제를 고려해야 한다. 예를 들어 Exchange, Exchange ActiveSync, Gmail IMAP 프로토콜을 함께 사용하도록 하는 것이다.잠재적 문제의 목록은 매우 광범위하여 간단한 해결 방안이 거의 없다.

이런 복잡한 문제들은 전자메일과 같은 50년 역사의 기술에 수반되는 불가피한 짐일 뿐이다.표준이 바뀌고 새로운 복잡한 기술이 도입됐지만 유류 협의를 시종일관 고려해야 한다.

도전하다


Nylas가 처음 시작되었을 때, 우리는 어떻게 하나 를 구축하는지 고려해야 했다.본질적으로 말하자면 두 가지 선택이 있다. 1) 가장 적은 데이터를 저장하고 두 플랫폼 간의 번역층을 충당하고, 2) 메일박스의 내용을 거울로 삼아 가능한 한 많은 요청을 직접 제공한다.
첫 번째 선택은 더 싸지만, 정상적인 운행 시간에 의존하는 조직에 신뢰성을 제공하는 능력을 복잡하게 할 것이다.그래서 우리는 더 비싸지만 옵션 2를 선택했다.우리는 데이터베이스를 분할하고 반단편 구조를 사용함으로써 이 점을 실현한다.이런 구조는 우리의 서비스를 서로 다른 기계군에 포지셔닝하지만, 그것들은 모두 같은 밑바닥 코드와 모델을 공유하여 집적하기 편리하게 한다.
sync engine API
이러한 구조는 전자메일, 동기화 라벨, 폴더 등 더 큰 도전에 더욱 잘 대응할 수 있게 한다.최종 결과: Nylas Sync 엔진.Nylas Sync 엔진은 개발자가 응용 프로그램에 메시지를 통합할 수 있도록 RESTful API를 제공합니다.테스트와 이전을 포함하여 90000여 줄의Python 코드가 있으며 프로토콜 생태계, 프로토콜 지점, 해석, 인코딩 등 문제를 해결하는 데 도움이 된다.

과학 기술 분야에서 심심한 것은 좋은 일이다


우리의 구조를 구축하기 위해서, 우리는 파이썬과 그 많은 라이브러리와 같은 확장 가능한 프로그래밍 언어를 사용해야 한다.예를 들어, 우리는 전자 우편 배달을 촉진하기 위해 분석 라이브러리 를 광범위하게 사용한다.Haproxy,nginx,gunicorn,MySQL,ProxySQL,Ansible,Redis 등 다른 도구를 제외하고 우리는 Flask,Gevent,SQLAlchemy와pytest를 사용한다.창고로 말하자면, 우리가 상당히 평범한 선택을 한 것 같다.우리는 해냈다. 이것은 고의적인 것이다.
우리가 무미건조한 도구를 사용하는 것은 간단한 이유 때문이다. 우리는 작은 회사이기 때문에 이렇게 많은 자원을 혁신 발전을 추진하는 데 사용할 수 밖에 없다.사실 우리의 디자인 이념의 일부분은 댄 맥킨리의 글flanker에서 비롯되었다. (만약 당신이 아직 읽지 않았다면, 당신은 읽어야 한다. 대단합니다.) 그는 글에서 모든 회사가 파산하기 전에 유한한 혁신 능력을 가지고 있다고 건의했다.이 개념은 Nylas의 초기 결정을 추진하고 고객이 여러 개의 통합이 아니라 하나의 통합을 구축할 수 있어도 핵심 API 이념을 전달했다.이것은 우리를 오랫동안 시련을 겪은 기술로 밀어붙였다. 우리는 우리가 걱정할 필요가 없다는 것을 안다. 이것은 우리가 다른 곳에서 더 많은 것을 할 수 있게 한다.
예를 들어, MySQL을 사용하여 데이터베이스를 관리합니다.우리는 일찌감치 MySQL을 올바른 선택이라고 생각했다. 왜냐하면 우리는 그것을 잘 알고 잠재적인 DBA가 그것을 잘 알고 있기 때문이다. 우리는 다른 문제를 위해 혁신 에너지를 절약해야 한다.물론 MySQL에 의존하는 것은 우리가 성장할 수 있는 고민이 많다는 것을 의미하지만“Choose Boring Technology”에 실린 블로그 글 참조), 우리는 ProxySQL, 수평 절분과 다른 기술의 스마트 응용을 통해 이러한 문제를 극복할 수 있다.
MySQL의 장점과 앞으로 ProxySQL과 다른 도구를 사용하여 수정하는 방법을 이해하면 데이터베이스를 더욱 작고 관리하기 쉬운 부분으로 간소화할 수 있을 뿐만 아니라 정지가 거의 필요 없고 데이터베이스를 완전히 재설계할 필요도 없다.사실, ProxySQL과 SQLAlchemy가 제공하는 약간의 마력을 통해 우리는 MySQL을 사용하여 사무표에 메일박스에 동기화된 모든 변경 사항을 쉽게 기록하고 재방송한다.이것은 우리의 동기화, 네트워크 갈고리, 흐름 API 등에 강력한 지원을 제공했다.
이렇게 많은 의존 항목이 있는데, 우리는 데비안 패키지에 봉인된Python virtualenv를 사용하여 응용 프로그램을 배치합니다.구체적으로 말하자면, 우리가 사용하는 도구는 Growing up with MySQL 이다. 이것은 우리가 데비안의 패키지 관리자 dpkg을 사용하여 의존항을 배치하고 공작물을 검사한 후에 그것들을 dh-virtualenv 까지 밀어낼 수 있게 한다.cQueen에서 설명한 것처럼 간단한 배포 스크립트는 다음과 같습니다.
scp my-package.deb remote-host.example.org:
ssh remote-host.example.org

# Run the next commands on remote-host.example.org
dpkg -i my-package.deb

/usr/share/python/myproject/bin/python
>>> import myproject # it works!
이런 공구가 있으면 우리는 바퀴를 재발명하는 것이 아니라 믿을 만한 기술 창고를 누릴 수 있다.그것은 단지 전자 우편을 동기화하고 발송하는 데 도움을 줄 뿐 아니라, 모든 사람들이 정상적인 운행 시간, 규모, 안정성에 대한 기대를 만족시킬 뿐이다.

아마존 S3 동기화 및 확인


우리는 차량 대열의 다핵 기계에서 Python을 사용한다.이것은 우리가 이 다중 핵을 충분히 이용하기 위해 여러 개의 프로세스를 실행해야 한다는 것을 의미한다.이를 위해, 우리는 , 하나의 협동 프로그램 라이브러리를 사용하여 하나의 프로세스에서 약 100개의 계정을 동기화합니다.이것은 우리를 위해 대량의 메모리와 운영체제 스케줄링을 절약했다.다음은 프로세스의 모양입니다.
모든 녹색 상자는 녹색 작은 상자다.Greenlet은 기능이 강한 소형 Python 도구로 우리가 미세한 제어 흐름을 할 수 있도록 한다. 예를 들어 Greenlet이 Gmail 동기화 흐름을 관리하고 Greenlet이 쓰레기, 달력, 연락처를 동기화하는 등이다.이 모든 것을 감시하기 위해서, 우리는 모든 흐름에서 실행되는 특수한 그린렛을 사용합니다. 이벤트 로그가 정해진 시간 내에 실행되지 않으면, 이벤트 로그를 보냅니다.이러한 상황이 발생할 때, 우리gevent는 응용 프로그램 호출 창고에 대해 샘플링과 기록을 해서 응용 프로그램이 끊어져 분석할 위치를 확정한다.Python에서 샘플러는 다음과 같이 보입니다.
import collections
import signal

class Sampler(object):
   def __init__(self, interval=0.001):
     self.stack_counts = collections.defaultdict(int)
     self.interval = 0.001

    def _sample(self, signum, frame):
     stack = []
     while frame is not None:
         formatted_frame = '{}({})'.format(frame.f_code.co_name,
                                             frame.f_globals.get('__name__'))
         stack.append(formatted_frame)
         frame = frame.f_back

     formatted_stack = ';'.join(reversed(stack))
     self.stack_counts[formatted_stack] += 1
     signal.setitimer(signal.ITIMER_VIRTUAL, self.interval, 0)

    def start(self):
     signal.signal(signal.VTALRM, self._sample)
     signal.setitimer(signal.ITIMER_VIRTUAL, self.interval, 0)
이 견본들은 화염도를 입력하여 프로세스가 무엇을 하는지, CPU가 어떻게 사용되는지, 그린렛이 지원하는 것이 무엇인지 보여줄 수 있다.

샘플링 분석기 실행 우리의 다음 작업


그러나 어떤 조직이 알고 있듯이 즐거움은 도전을 극복하는 데 국한되지 않는다.앞으로 몇 년 동안 우리는 파이썬 생태계에 더 많은 투자를 할 계획이다.예를 들어 코드의 복잡성이 증가함에 따라 우리는 이 관리를 줄이는 데 도움이 되기를 바란다.특히mypy 대들보로 유형검사를 실시한다.이것은 증량 프로젝트이지만, 우리는 mypy의 복잡성을 낮추는 기능을 가지고 있어서 매우 기쁘다.
Python 3로의 마이그레이션도 시작합니다.마지막으로, 우리는 사무 로그를 we’re using mypy 사건의 주간으로 이동하는 것을 고려한다.이것은 우리로 하여금 마이크로 서비스 기반의 구조로 전환할 수 있게 하고 모든 서비스가 데이터베이스와 직접 통신하도록 요구하지 않음을 통해 우리에게 더욱 큰 유연성을 제공할 수 있게 할 것이다.
우리에게 Python은 단순성, 라이브러리의 다양성, 서버와의 좋은 협업 능력 때문에 거의 어디에나 있다.궁금한 개발자들에게는 파이썬이 코드를 어떻게 간소화하거나 새로운 응용 프로그램의 기초를 어떻게 구성하는지에 대해 알아야 할 내용이 많다.그리고 강력하고 효과가 있는 지역사회 때문에 이런 가능성을 어떻게 활용하는지 배우는 것은 상당히 간단할 수 있다.이 지역사회는 우리가 이렇게 광범위하게 Python을 사용하는 주요 원인 중의 하나이며, 또한 우리가 이 지역사회가 무엇을 할 수 있는지, 그리고 우리가 그것을 위해 어떻게 공헌할 수 있는지를 기대하는 주요 원인 중의 하나이다.우리에게 Python은 표준적이고 확장 가능하며 시간 테스트를 거쳤으며, 가장 중요한 것은 어떤 초창기 회사에도 지루하다는 것이다.우리는 그것이 여기서 어디로 향하는지 지체없이 보고 싶었다.
여기에서 전체 프레젠테이션을 확인하십시오.
본고는 최초Kafka에 발표되었다.

좋은 웹페이지 즐겨찾기