Uma Black Friday
sem catástrofes
Jéssica Bonson
Principal Engineer no Olist
TDC Floripa 2020, Trilha Microservices
Slide 2
Slide 2 text
Jéssica Pauli de C Bonson
● +-8 anos de exp em pesquisa/desenvolvimento
● graduação/mestrado em Ciências da Computação
● foco em dev backend, machine learning e big data
Jogos
RPG
Canto
Hobbies:
Slide 3
Slide 3 text
Maior loja nos principais marketplaces do Brasil.
Arquitetura em microsserviços e serverless.
Python. Go. PostgreSQL. AWS. Heroku.
20+ APIs
120+ serviços
3m+ produtos
30k+ logistas
10m+ anúncios
200k+ pedidos
em maio/2020
Django-silk
https://github.com/jazzband/django-silk
Profiling e inspeção
Slide 15
Slide 15 text
Siege https://github.com/JoeDog/siege
Teste de carga e benchmark
Slide 16
Slide 16 text
Locust https://locust.io/
Teste de carga com scripting em Python
Slide 17
Slide 17 text
Como melhorar?
Slide 18
Slide 18 text
Acesso ao Banco de Dados
Slide 19
Slide 19 text
Exemplo
Para 100 Books, onde cada um tem uma FK para um Publisher...
queryset = Book.objects.all()
for book in queryset:
print(str({'name': book.name, 'publisher': book.publisher.name}))
Slide 20
Slide 20 text
Exemplo
Para 100 Books, onde cada um tem uma FK para um Publisher...
queryset = Book.objects.all()
for book in queryset:
print(str({'name': book.name, 'publisher': book.publisher.name})) # 101 queries
Slide 21
Slide 21 text
Exemplo: select_related
Para 100 Books, onde cada um tem uma FK para um Publisher...
queryset = Book.objects.all()
for book in queryset:
print(str({'name': book.name, 'publisher': book.publisher.name})) # 101 queries
queryset = Book.objects.select_related('publisher').all()
for book in queryset:
print(str({'name': book.name, 'publisher': book.publisher.name})) # 1 query
Slide 22
Slide 22 text
Exemplo
Para 10 Stores, onde cada uma tem 10 Books, em uma relação many-to-many...
queryset = Store.objects.all()
for store in queryset :
books = [book.name for book in store.books.all()]
print(str({'name': store.name, 'books': books}))
Slide 23
Slide 23 text
Exemplo
Para 10 Stores, onde cada uma tem 10 Books, em uma relação many-to-many...
queryset = Store.objects.all()
for store in queryset :
books = [book.name for book in store.books.all()]
print(str({'name': store.name, 'books': books})) # 11 queries
Slide 24
Slide 24 text
Exemplo: prefetch_related
Para 10 Stores, onde cada uma tem 10 Books, em uma relação many-to-many...
queryset = Store.objects.all()
for store in queryset:
books = [book.name for book in store.books.all()]
print(str({'name': store.name, 'books': books})) # 11 queries
queryset = Store.objects.prefetch_related('books')
for store in queryset:
books = [book.name for book in store.books.all()]
print(str({'name': store.name, 'books': books})) # 2 queries
Slide 25
Slide 25 text
Exemplo: prefetch_related com filtro
Para 10 Stores, onde cada uma tem 10 Books, em uma relação many-to-many...
queryset = Store.objects.prefetch_related('books')
for store in queryset:
books = [book.name for book in store.books.filter(price__range=(250, 300))]
print(str({'name': store.name, 'books': books}))
Slide 26
Slide 26 text
Exemplo: prefetch_related com filtro
Para 10 Stores, onde cada uma tem 10 Books, em uma relação many-to-many...
queryset = Store.objects.prefetch_related('books')
for store in queryset:
books = [book.name for book in store.books.filter(price__range=(250, 300))]
print(str({'name': store.name, 'books': books})) # 12 queries
Slide 27
Slide 27 text
queryset = Store.objects.prefetch_related(
Prefetch('books', queryset=Book.objects.filter(price__range=(250, 300))))
for store in queryset:
books = [book.name for book in store.books.all()]
print(str({'name': store.name, 'books': books})) # 2 queries
Exemplo: prefetch_related com filtro
Slide 28
Slide 28 text
Exemplo
Slide 29
Slide 29 text
Suporte a Partial Response
Slide 30
Slide 30 text
django-rest-framework-jsonmask
Slide 31
Slide 31 text
Exemplo: Endpoint de autenticação
Slide 32
Slide 32 text
Como usar?
● Herdar rest_framework_jsonmask.views.OptimizedQuerySetMixin
● Herdar rest_framework_jsonmask.serializers.FieldsListSerializerMixin
Slide 33
Slide 33 text
Renderização
Slide 34
Slide 34 text
django-rest-framework-rapidjson ou drf-ujson-renderer
/seller-orders/
Antes: Time per request: 1030.060 [ms] (mean)
Depois: Time per request: 973.138 [ms] (mean)
/orders/
Antes: Time per request: 12512.722 [ms] (mean)
Depois: Time per request: 1837.474 [ms] (mean)
Slide 35
Slide 35 text
Melhorias de Banco de Dados
● Adicionar/Remover índices no BD
● Reestruturar relações no BD
● Ativar full text search do Postgres
● Réplica de leitura do BD
● Dumps de dados antigos de histórico para NoSQL
● Particionamento
Slide 36
Slide 36 text
Melhorias de Arquitetura
● Usar cache
● Usar código assíncrono
● Evitar ponto único de falha
● Dividir APIs e serviços que ficarem muito grandes
● Evitar contadores em paginação
● Implementar padrão circuit-breaker
● Conteinerização