re arquitetando o re arquitetando o stack overflow stack
play

Re-arquitetando o Re-arquitetando o Stack Overflow Stack Overflow - PowerPoint PPT Presentation

Re-arquitetando o Re-arquitetando o Stack Overflow Stack Overflow ou como construmos o Stack Overflow for Teams Roberta Arcoverde 1 /whois /whois recifense programadora h 15 anos principal software developer na stack overflow


  1. Re-arquitetando o Re-arquitetando o Stack Overflow Stack Overflow ou como construímos o Stack Overflow for Teams Roberta Arcoverde 1

  2. /whois /whois recifense programadora há 15 anos principal software developer na stack overflow co-host do hipsters.tech @rla4 2

  3. desde 2008 50+ milhões de usuários únicos/mês 18 milhões de perguntas 27 milhões de respostas top 50 sites mais acessados do mundo 3

  4. 3k Teams criados, 50k usuários 10 meses em desenvolvimento lançado em maio/2018 equipe tinha originalmente 3 devs, agora são 7 melhor nome de time da história: Teams Team � 4

  5. https://stackoverflow.com/ c/demo 5

  6. https://stackoverflow.com/ c/demo 5

  7. https://stackoverflow.com/ c/demo 5

  8. https://stackoverflow.com/ c/demo 5

  9. https://stackoverflow.com/ c/demo 5

  10. https://stackoverflow.com/ c/demo 5

  11. https://stackoverflow.com 6

  12. https://stackoverflow.com 6

  13. >170 sites >170 sites 7

  14. números do dia 03/05 números do dia 03/05 278.912.108 HTTP requests 67.188.355 page views 3.506.670.995.363 bytes (3.5 TB) enviados 953.860.308 SQL queries executadas 5.250.697.564 redis hits 600.000 websockets ativos 19 ms de tempo de renderização da Question page 54.290.431 page views, ou 80% do total 123 ms de tempo de renderização geral 8

  15. 9 WEB SERVERS ~350 req/s ~5% CPU por servidor 4 SQL SERVERS Stack Overflow Stack Exchange, Meta, Talent 528 M 498 M queries/dia queries/dia LIVE HOT STANDBY LIVE HOT STANDBY 9

  16. imagem gentilmente cedida por Marco (@sklivvz) em http://www.slideshare.net/howtoweb/marco-cecconi-stack-overflow-architecture 10

  17. 11

  18. como? como? spoilers: é boring 12

  19. performance performance é uma é uma feature feature 13

  20. tech stack tech stack c# asp.net mvc* sql server dapper, ef core typescript vanilla redis *migrando pra .NET Core elasticsearch ha proxy 14

  21. 15

  22. � ♀ 15

  23. multi tenant application multi tenant application um único app pool para todos os sites roteado via host headers 16

  24. 17

  25. https://nickcraver.com/blog/2016/02/03/stack-overflow-a-technical-deconstruction/ 18

  26. Q&A pra dados Q&A pra dados privados? privados? 19

  27. (o nome original do SO for Teams era Channels) nasce uma ideia! (sim, o screenshot é legítimo) 20

  28. times são sites que existem dentro do Stack Overflow tratá-los como se fossem novos sites na rede, porém visíveis apenas a partir do public class Post { public class Post { public int Id { get ; } public int Id { get ; } public string Title { get ; } public string Title { get ; } ... public int ? TeamId { get ; } } ... } // reusar banco // criar novo banco // criar novo código // reusar código 21

  29. https://stackoverflow.com/help/search-inline https://askubuntu.com/help/search-inline https://stackoverflow.com/c/demo/help/search-inline 1 [StackRoute("help/search-inline")] 2 public async Task<ActionResult> SearchInline ( string q) 3 { 4 var searchSite = GetSearchSite(); 5 var results = await searchSite.HelpPostIndex.SearchAsync(searchSite, q); 6 var sm = new SearchModel 7 { 8 SearchString = q, 9 Results = results 10 }; 11 12 return PartialView("~/Views/Help/SearchInline.cshtml", sm); 13 } 22

  30. Modelo Modelo evitar forks, DRY, minimizar alterações no core do projeto 23

  31. Modelo Modelo evitar forks, DRY, minimizar alterações no core do projeto Escalabilidade Escalabilidade capacity planning, o que acontece se tivermos 1k, 10k, 100k times? 23

  32. Modelo Modelo evitar forks, DRY, minimizar alterações no core do projeto Escalabilidade Escalabilidade capacity planning, o que acontece se tivermos 1k, 10k, 100k times? Segurança Segurança default private, mudança de mindset, crash na aplicação > vazamento de dados 23

  33. Plano A: um banco para Plano A: um banco para cada Team cada Team � � Bases isoladas entre Escalabilidade. AG Teams distribuídos começam a Dados isolados dos degradar rapidamente dados públicos a partir de 1k bancos Mínimo de alterações Hardware e no código (usar modelo instrumentação para existente pra novos gerenciar milhares de sites) bases de dados 24

  34. Plano B: um banco para Plano B: um banco para todos os Teams todos os Teams � � Escalabilidade Sem isolamento entre Dados isolados dos Teams dados públicos Reescrever boa parte das consultas Consultas não são mais as mesmas para sites vs Teams 25

  35. Plano C: um schema por Plano C: um schema por time no mesmo banco time no mesmo banco � � Dados isolados entre Precisamos escrever Teams infra de Dados isolados dos provisionamento dados públicos dinâmico Escalabilidade é... decente Baixo custo de reescrita 26

  36. 27

  37. 28

  38. Escalabilidade Escalabilidade basicamente: saindo de 170 para 10k+ sites SQL Server 1 banco per-site 1 banco pra todos os Teams, 1 schema per-Team Elasticsearch 1 índice per-site 1 índice per-team, até 5k Provisionamento tarefa agendada cria sempre um buffer de 100 schemas para futuros Teams 29

  39. Segurança Segurança onde manter os dados dos Teams? como comunicar o site público com o Team? migrar *tudo* pra lugares seguros notificações emails monitoramento internal API websockets tags 30

  40. 31

  41. como as redes se como as redes se comunicam? comunicam? 32

  42. Proxying Proxying Já usávamos no /jobs Requisição é "clonada" e enviada para a CFZ Response é jogada direto no stream de saída 800 LoC Por que não usar APIs/serviços? custo de serialização mais código, menos uniformidade 33

  43. 1 [StackRoute("c/{slug}")] 2 [StackRoute("c/{slug}/{*pathInfo}")] 3 public async Task<ActionResult> Proxy ( string slug) 4 { 5 if (!Current.Settings.Channels.Enabled) 6 { 7 return PageNotFound(); 8 } 9 ... 10 if (Current.Request.IsProxied()) 11 { 12 // yo dawg, I heard you like proxies so we put a proxy in your proxy 13 // so you can channel yo inner channels... Let's not allow this 14 return PageNotFound(); 15 } 16 17 var returnUrl = Current.Request.Url.PathAndQuery; 18 if (!Current.SiteChannels.Contains(channelSite.Id)) 19 { 20 // user does not have access to this channel 21 return RedirectToJoinPage(); 22 } 23 ... 24 25 return await this .BlindProxy(channelSite, path); 26 } 27 28 // BlindProxy: 29 // valida a requisição (authorization); 30 // constrói um Request; 31 // envia via HTTP para o Team app; 32 // retorna o resultado 33 // profit :D 34

  44. 1 1 [StackRoute("c/{slug}")] [StackRoute("c/{slug}")] 2 2 [StackRoute("c/{slug}/{*pathInfo}")] [StackRoute("c/{slug}/{*pathInfo}")] 3 3 public async Task<ActionResult> Proxy ( string slug) public async Task<ActionResult> Proxy ( string slug) 4 4 { { 5 5 if (!Current.Settings.Channels.Enabled) if (!Current.Settings.Channels.Enabled) 6 6 { { 7 7 return PageNotFound(); return PageNotFound(); 8 8 } } 9 9 ... ... 10 10 if (Current.Request.IsProxied()) if (Current.Request.IsProxied()) 11 11 { { 12 12 // yo dawg, I heard you like proxies so we put a proxy in your proxy // yo dawg, I heard you like proxies so we put a proxy in your proxy 13 13 // so you can channel yo inner channels... Let's not allow this // so you can channel yo inner channels... Let's not allow this 14 14 return PageNotFound(); return PageNotFound(); 15 15 } } 16 16 17 17 var returnUrl = Current.Request.Url.PathAndQuery; var returnUrl = Current.Request.Url.PathAndQuery; 18 18 if (!Current.SiteChannels.Contains(channelSite.Id)) if (!Current.SiteChannels.Contains(channelSite.Id)) 19 19 { { 20 20 // user does not have access to this channel // user does not have access to this channel 21 21 return RedirectToJoinPage(); return RedirectToJoinPage(); 22 22 } } 23 23 ... ... 24 24 25 25 return await this .BlindProxy(channelSite, path); return await this .BlindProxy(channelSite, path); 26 26 } } 27 27 28 28 // BlindProxy: // BlindProxy: 29 29 // valida a requisição (authorization); // valida a requisição (authorization); 30 30 // constrói um Request; // constrói um Request; 31 31 // envia via HTTP para o Team app; // envia via HTTP para o Team app; 32 32 // retorna o resultado // retorna o resultado 33 33 // profit :D // profit :D 34

Recommend


More recommend