Backend Software Architecture Checklist: How to Build a Product from Scratch

Du vaknar en morgon för att ta din kopp kaffe och voilà, Eureka-ögonblicket är här. Du fick äntligen reda på din affärsmodell och allt faller på plats. Du vet att investerare kommer att älska det, och du kan bara inte vänta med att börja bygga produkten. Den första moverfördelen är din att ta.

Dessa ögonblick är sällsynta, men när de händer måste du starta vid rätt tidpunkt. Allt du behöver är rätt guide som hjälper dig att ta reda på vad du bör och inte ska göra. Det här är inte en tid att experimentera, det är dags att köra. Det är DIN tid nu!

OBS - Följande är relaterat till att bygga programvaruarkitekturer från grunden. Så om du är intresserad av att lära känna den inblandade tekniken, fortsätt sedan. Annars kan du dela med dem som definitivt kommer att älska det här: P

Var den här guiden kom ifrån

Jag har själv arbetat med en handfull tidiga produkter, och för att vara ärlig gjorde jag misstag. Jag önskade alltid att det fanns en checklista att följa när jag byggde en produkt från grunden.

Det är så många saker involverade i att bygga en arkitektur från grunden att du helt kommer att glömma vissa delar. Och de kommer tillbaka för att bita dig i senare skeden av produktcykeln.

Jag bestämde mig äntligen för att skapa den här checklistan över saker som du bör tänka på innan du trycker på distributionsknappen för första gången.

Så utan ytterligare uppbyggnad, här är checklistan du bör gå igenom när du bygger en Backend Architecture för en produkt från grunden.

Välj rätt språk och ram (för ditt projekt)

Att välja rätt språk och ram för din produkt är svårt, och det finns ingen speciell silverkula för detta. Mitt råd är att välja ett språk som du är mest bekväm med och känna till invecklingarna in och ut.

Med detta sagt är det sällsynt, för det finns väldigt få människor som är Javascript Ninjas, eller Python Panthers, eller vad som helst funky namn finns där ute.

Så välj ett språk som har riktigt bra stöd i branschen, som Javascript, Python, Java eller Go för att nämna några. Du kan välja vilket språk som helst, bara välja vilket som passar dig bäst.

Och kom ihåg - du bygger en MVP (Minimum Viable Product), och kommer att vara i färd med att skapa en POC (Proof of Concept). Så ta ut din produkt så snart som möjligt. Du behöver inte fastna i frågor som kan komma från det nya språket i stan. För att undvika dessa problem, välj ett mer använt, väldokumenterat språk.

Slutligen kan du skala vid ett senare tillfälle. Om du är i fasen med att göra POC, bygg bara och få det gjort. Men om du bygger något riktigt specifikt, och det finns ett språk och en rambyggnad speciellt för det, bör du definitivt välja den tekniken.

Men för det mesta kan problemen vi försöker lösa lätt hanteras med något av ovan nämnda språk och deras respektive ramar. Så välj bara en och starta din produkt.

En bra resurs som hjälper dig att bestämma -

//content.techgig.com/top-5-programming-languages-for-backend-web-development/articleshow/67337449.cms

Implementera autentisering och mikrotjänster för auktorisering

Det finns många sätt att autentisera och auktorisera en användare. Du kan prova Session Tokens, JWT (JSON Web Tokens) eller OAuth, för att nämna några. Varje alternativ har sina egna fördelar och nackdelar. Så låt oss titta närmare på några av dem.

JSON Web Tokens

JWT är snabba och enkla att implementera. Detta beror på att symbolerna aldrig lagras någonstans på ditt system. De är bara kodade, krypterade och skickas till användaren. Så att validera en JWT är snabbare än någon annan metod.

Men då, eftersom de inte är lagrade på systemet, kan du inte faktiskt göra att en token upphör att gälla före dess faktiska utgångstid, och det kan vara ett problem i vissa fall.

Så ta reda på fördelarna och nackdelarna med varje autentiseringssystem och välj det som bäst passar dina behov. Jag personligen föredrar JWT (men det är mitt eget val).

Tillstånd

Glöm aldrig att genomföra behörighet för användare. Du vill inte ha inloggad User1 för att ändra informationen om User2. Detta kan orsaka rent kaos i ditt system.

Identifiera slutpunkterna som behöver auktorisering och implementera dem direkt. Du vill inte att status för din databas ska skadas så här. Kom ihåg skillnaden mellan 401 och 403.

Följande är vissa slutpunkter som du definitivt bör överväga när du skapar ditt autentiseringssystem (jag skapade en i Django med JWT). Det kan finnas vissa tillägg / raderingar för ditt användningsfall, men det är de du bör överväga att bygga.

Många ramar ger dem ur lådan, men tänk på dem innan du bygger dem på egen hand. Kontrollera authentication_classes och permission_classes i Django Rest Framework för ytterligare referens.

Ta en titt på den här Django REST Framework-resursen -

//www.django-rest-framework.org/tutorial/4-authentication-and-permissions/

Skapa en abstrakt basmodell som ärvs av alla andra modeller i din databas

Kom ihåg DRY-principen - upprepa inte dig själv? Det bör följas till grunden i Software Engineering.

Baserat på ovanstående tankeprocess kommer det att finnas vissa kolumner i din databas som kommer att finnas i varje tabell. Därför är det bättre att skapa en abstrakt klass för dem så att andra modellklasser kan ärva från dem.

Låt oss gå igenom den här koden och vad den betyder:

  • id - Även om det inte är skrivet här skapas det automatiskt av Django-ramverket. Men om den inte finns i din, skriv ner den i den här klassen. Det är bara ett automatiskt ökat fält som kan användas som en primär nyckel i din databasrelation.
  • created_at - Detta innebär när fältet / raden infogades i din tabell och det fylls av själva ramverket. Du behöver inte ställa in det uttryckligen.
  • updated_at - Detta innebär när fältet / raden senast ändrades / uppdaterades i din tabell, och igen fylls det av själva ramen.
  • delete_at + is_deleted - Så det här är ett kontroversiellt fält. Jag har inte ett exakt svar på om det borde vara där eller inte - för att vara ärlig raderas inget på internet någonsin. Detta fält, om det är fyllt, visar att raden raderas från systemet (även om uppgifterna finns kvar i systemet för framtida referenser och kan tas bort från databasen och lagras i säkerhetskopior)
  • uuid - Det beror på om du vill lägga det här i ditt bord eller inte. Om du behöver exponera den primära nyckeln i din tabell för ett externt system, är det bättre att exponera den här snarare än det automatiskt ökade heltalfältet. Du kanske undrar varför ...? Tja, varför skulle du vilja berätta för ett externt system att du har 10378 beställningar i ditt bord? Men återigen är det ett personligt val.

Ställ in en mikrotjänst för aviseringar

Varje produkt måste skicka påminnelser och meddelanden till användaren för engagemang och transaktionsändamål. Så varje produkt behöver detta.

Du bör definitivt överväga att bygga en Microservice som tillhandahåller aviseringstjänster (som Push Notification, E-post och SMS) till dina slutanvändare.

Detta borde vara en separat Microservice helt och hållet. Bygg inte detta i din autentiseringsmikrotjänst eller din applikationstjänst (den faktiska affärslogiken).

Det finns många tredjepartsbibliotek / tjänster som kan användas för att bygga det för din applikation. Utnyttja dem och bygg den på toppen av det.

Kom ihåg att bygga alla de tre funktionerna:

  • Push-aviseringar (APNS + FCM),
  • E-post (integrera bara en SMTP-klient för start)
  • och SMS

OBS - Har två kanaler för att skicka SMS, transaktions- och reklam. Skicka aldrig ett PR-SMS på en transaktionskanal, eftersom det finns chanser att du kommer att stämmas av en välinformerad och motiverad användare.

Ett enkelt sätt att konfigurera din SMTP-klient i din applikation är att använda detta i dina inställningar:

Jag gjorde det på Django, men du kan göra detsamma på ditt valda språk och ram.

Ställ in felloggning

Använd en mellanvara för att logga fel som uppstår i ditt produktionssystem. Ditt produktionssystem kommer inte att övervakas av människor som sitter där för att se applikationsloggarna 24/7. Så du behöver ett system som loggar de interna serverfelen på en central plats. Sedan kan du gå och kontrollera dem dagligen eller skapa en webbkrok så att du kan bli varnad vid rätt tidpunkt och ta hand om dem.

Det finns många verktyg för felloggning från tredje part på marknaden. Välj bara någon som passar dina behov. Jag använder mest Sentry / Airbrake.

Överväg att konfigurera webbhooks, som jag nämnde ovan. De kommer att informera dina användare om fel och till exempel kan du lägga upp dessa fel när de inträffar på vissa slaka kanaler. Sedan kan du kontrollera dessa kanaler regelbundet och rätta till dem på grund av deras svårighetsgrad.

Airbrakes officiella hemsida - //airbrake.io/

Sentrys officiella hemsida - //sentry.io/welcome/

Implementförfrågan - svar och applikationsloggning

Scenario - En användare kommer till ditt stöd och säger att de inte har fått transaktionskvittot för köpet de gjorde på din webbplats. Vad kommer du göra?

Om du har lagt Application Logging i ditt system, oroa dig inte. Vad menar jag nu med det? Det är alltid bättre att visa ett exempel än att försöka förklara med ord. Så här är det:

Jag har loggat in att jag ska skicka e-postmeddelandet till den nämnda e-postadressen. Jag kan kontrollera i applikationsloggarna för att se om e-postmeddelandet faktiskt skickades till klienten genom att kontrollera om det finns en sådan logg i systemet. Se till att lägga in omfattande loggar i ditt system så att du kan spåra begäran.

Dessutom är det en bra idé att placera ett async-system på plats som plockar ut sådana begärandesvar och applikationsloggar från ditt system och dumpar dem på en central plats. Där kan de bearbetas för att vara lättare att tolka.

ELK-stacken är ett bra alternativ för detta: ElasticSearch - Logstash - Kibana.

Mer om ELK-stacken - //www.elastic.co/what-is/elk-stack

OBS - När du loggar in begäran och svar, ta hand om följande:

  • Logga inte lösenord.
  • Logga inte in tokens (åtkomsttoken som används för autentisering)
  • Logga inte OTP: er

Introducera strypning i dina API: er och hastighetsbegränsning på dina applikationsservrar

Scenario - Du har precis lanserat din tjänst och har marknadsfört produkten på sociala medieplattformar. En svart hatthacker fick reda på det och ville bara spela med ditt system. Så de planerade en DOS-attack (Denial of Service) på ditt system.

För att bekämpa detta kan du ställa in hastighetsbegränsning baserat på olika faktorer ovanpå dina belastningsutjämnare för dina applikationsservrar. Detta tar hand om DOS-attacker och förhindrar att den skadliga användaren attackerar dina servrar.

Scenario - API-slutpunkten / otp / validering som tar fyrsiffriga OTP: er för autentisering av användaren och ger tillbaka tokens som ska användas för autentiserade API: er. En skadlig användare får mobilnumret för en av dina kunder och börjar slå API-slutpunkten med brute force attack som ändrar IP: erna, en DDOS-attack (Distribuerad Denial of Service). Hastighetsbegränsaren kan inte stoppa användaren, eftersom IP: n fortsätter att förändras med varje begäran som görs.

För att stoppa detta kan du också stryka på API: erna baserat på användaren. Du kan konfigurera hur många förfrågningar som kan göras av en viss användare till en API-slutpunkt. För OTP-validering är ett stort antal 5 förfrågningar per 10 minuter. Detta kommer att hindra den skadliga användaren från att utföra en brutal DDOS-attack på ovanstående API.

Strypning i Djangos REST Framework -

//www.django-rest-framework.org/api-guide/throttling/

Upprätta och konfigurera asynkron kommunikation från första dagen

Scenario - Du måste skicka ett välkomstmeddelande till användaren när de registrerar sig i din ansökan. Frontendklienten träffar Register API, du skapar användaren i backend efter valideringar, och detta startar processen för att skicka ett välkomstmeddelande.

Att skicka detta välkomstmeddelande tar tid, kanske några sekunder. Men varför skulle du vilja att mobilklienten ska fastna för en sådan process? Detta kan hända i bakgrunden utan att användaren fastnar av någon särskild anledning på registretsidan. Varje sekund är dyrbar och du vill inte att användaren ska förlora dessa värdefulla sekunder.

Så skicka bara e-postmeddelandet via en asynkron uppgift. Använd arbetstagare, uppgifter, meddelandemäklare och resultat för att utföra detta.

Ett bra exempel på detta från Python-världen är selleriarbetare. Lägg bara uppgiften som behöver utföras i en meddelandemäklare (Rabbit MQ / SQS, etc). Selleri lyssnar på detta och skickar uppgiften till den utsedda arbetaren. Den arbetaren behandlar sedan begäran och lägger resultatet i en resultatbackend som kan vara ett cachesystem / databassystem. (Redis / PostgreSQL till exempel).

Du kan övervaka dessa uppgifter och köer med många tredjepartsbibliotek. Ett bra exempel på detta är selleri blomma som övervakar allt detta.

Du kan läsa mer om RabbitMQ här - //www.rabbitmq.com/

Och selleri - //docs.celeryproject.org/en/stable/django/first-steps-with-django.html

Och slutligen, selleri blomma - //flower.readthedocs.io/en/latest/

Ställ in cron-jobb

Scenario - Du har precis lanserat din produkt och du måste skicka rekommendationer till dina användare om nya produkter på din plattform. Du skickar dessa på grundval av deras köphistorik varje helg.

Ovanstående uppgift kan enkelt utföras med hjälp av ett cron-jobb. Det är lätt att konfigurera i alla ramar. Det viktiga att tänka på är att du inte ska placera cron-jobb direkt i crontab-filen på din server. Du bör låta ramverket hantera det.

Detta beror på att distributionsingenjören / Devopsingenjören ska vara den enda personen som har tillgång till systemet så här av säkerhetsskäl. Även om du inte behöver implementera det så är det bra att ha saker från början.

I Django-världen kan du använda celerybeat för att konfigurera dina crons med hjälp av selleriarbetare.

Läs mer om selleri Beat här - // docs.celeryproject.org/en/latest/userguide/periodic-tasks.html

Hantera dina hemligheter ordentligt (parameterfil)

Det finns många sätt att hantera parameterhemligheter i dina produktionsservrar. Några av dem är:

  • Skapa en hemlig fil och lagra den i en privat s3-hink och dra densamma under distributionen av din applikation.
  • Ställa in parametrarna i miljövariabler under distributionen av din applikation (lagra dem i s3 igen)
  • Att lägga hemligheterna i någon hemlig hanteringstjänst (t.ex. //aws.amazon.com/secrets-manager/) och använda dem för att få hemligheterna i din applikation.

Du kan välja vilken som helst av dessa metoder enligt din komfort och ditt användningsfall. (Du kan välja att behålla olika hemliga filer även för lokala miljöer, produktions- och produktionsmiljöer.)

Version dina API: er från dag ett

Detta är något som du definitivt bör överväga från dag 1. Du kommer aldrig att veta hur ofta dina affärsmodeller kan förändras och du måste ha framåt-bakåtkompatibilitet i din ansökan. Så du bör versionera dina API: er för att säkerställa att allt fungerar smidigt för alla.

Du kan ha olika appar för olika versioner och låta nginx hantera det för din applikation. Eller så kan du ha versionversion i själva applikationen och låta rutterna i din applikationsserver hantera den. Du kan välja vilken metod som helst för att implementera den - huvudpoängen är att versionversionen är aktiverad från början.

Bestäm om hårda och mjuka uppdateringskontroller för dina klienter

Så vad är skillnaden mellan hårda och mjuka uppdateringar?

Hårda uppdateringar avser när användaren tvingas uppdatera klientversionen till ett högre versionsnummer än vad som är installerat på deras mobil.

Mjuka uppdateringar hänvisar till när användaren visas en uppmaning om att en ny version är tillgänglig och de kan uppdatera sin app till den nya versionen om de vill.

Hårda uppdateringar rekommenderas inte, men det finns tillfällen när du behöver genomdriva dem. Hur som helst bör du definitivt överväga hur du ska implementera detta för dina applikationer.

Du kan göra detta genom att implementera eller konfigurera det i Play Store eller App Store. Ett annat sätt är att skapa ett API i din backend-applikation som kommer att träffas varje gång mobilappen startas. Detta kommer att skicka två nycklar: hard_update -> true / false och soft_update -> true / false, beroende på användarens version och de hårda och mjuka uppdateringsversionerna i ditt backend-system.

Ett bra ställe att lagra dessa versioner finns i din cache (Redis / Memcache), som du kan ändra direkt utan att behöva distribuera din applikation.

Inför kontinuerlig integration (CI) från dag ett

Scenario - en av praktikanterna som arbetar i ditt projekt är inte tillräckligt skicklig för att skriva produktionsnivåkod. De kan ha förändrat något som kan bryta någon kritisk komponent i ditt projekt. Hur kan du se till att allt är ok i sådana fall?

Introducera kontinuerlig integration. Den kommer att köra linters och testa fall på varje begå och bryter om några regler bryts. Detta kommer i sin tur att blockera dragbegäran från att slås samman tills alla luddningsregler och testfall passerar. Det är trevligt att ha saker, och det hjälper faktiskt också på lång sikt, så kom ihåg det.

Det finns många alternativ på marknaden. Du kan antingen välja att implementera en på egen hand (Jenkins CI / CD), eller så kan du använda TravisCI, CircleCI, etc. för samma sak.

Läs om TravisCI här - //travis-ci.org/

Och CircleCI - //circleci.com/

Aktivera Docker-support (personlig preferens)

Skapa en Dockerfile och docker-compose.yml för din applikation så att alla kör applikationen med Docker från början. En av de främsta anledningarna till att använda ett sådant tillvägagångssätt är att ha konsekvens i din lokala / iscenesättnings- / produktionsmiljö, så att ingen utvecklare någonsin kan säga detta igen:

Men det sprang på min maskin.

Det är inte svårt att använda den från dag 1. I början använder du bara Docker för din lokala miljö så att installationen av din applikation kan bli riktigt smidig. Men kom ihåg hur du kan köra det både med och utan Docker i produktion.

Här är mer information om Docker Hub - //hub.docker.com/

Använd ett APM-verktyg

Ett applikationsövervakningsverktyg är ett måste om du vill övervaka programmets API: er, transaktioner, databasanslutningar och så vidare.

Scenario - din cronservers hårddisk är nästan full och den kan inte köra cron-jobb. Eftersom den inte kan hitta plats på skivan går dina crons inte. Så hur kan du få ett meddelande när detta händer?

Det finns många APM-verktyg som du kan använda för att övervaka detta. Du kan konfigurera dem efter när du behöver meddelas. Du kommer att få meddelanden på det medium du väljer när ett sådant kaos händer på ditt system - och lita på mig att det händer hela tiden. Så var bättre förberedd för det. New Relic är ett bra alternativ.

Läs mer om New Relic här - //newrelic.com/

Använd ElasticSearch för att driva applikationsomfattande sökningar i dina klientappar

Enligt wikipedia,

Elasticsearch är en sökmotor baserad på Lucene-biblioteket. Det tillhandahåller en distribuerad sökmotor med fulltext-sökmotor med ett HTTP-webbgränssnitt och schemafria JSON-dokument. Elasticsearch är utvecklat i Java.

I början kommer du att bli frestad att använda traditionella databasfrågor för att få resultat i sökfältet för klientappen. Varför? För det är enkelt.

Men traditionella databaser är inte avsedda för sådana utförande frågor. Ta reda på en bra tid att migrera din sökning till ElasticSearch och introducera en datapipeline i ditt system. Den matar den elastiska sökningen med data och ansluter sedan sökningen från ElasticSearch till applikationsservern.

Här är en bra översikt över Elasticsearch för att komma igång.

Och ElasticSearch Docs - //www.elastic.co/guide/index.html

Sätt en brandvägg i din produktionsserver

Du borde definitivt göra det här - det är ett måste. Sätt en brandvägg i din produktionsserver och stäng alla portar utom de som ska användas för API: er (https-anslutningar). Rutt API-slutpunkterna med en omvänd proxyserver, som NGiNX eller Apache. Ingen port bör vara tillgänglig för omvärlden än den som tillåts av NGiNX.

Varför ska du använda NGiNX:

  • //www.nginx.com/resources/wiki/community/why_use_it/
  • //blog.serverdensity.com/why-we-use-nginx/
  • //www.freecodecamp.org/news/an-introduction-to-nginx-for-developers-62179b6a458f/

Avslutar

Ovan nämnda punkter baseras på mina egna preferenser och jag har utvecklat dem genom åren. Det kommer att finnas små skillnader här och där, men begreppen förblir desamma.

Och i slutändan gör vi allt detta för att ett smidigt system ska byggas från början i produktion så snart som möjligt efter att du har kommit på idén.

Jag försökte skriva ner all min kunskap som jag har fått genom åren, och jag kan ha felnågra ställen .Jag f du tror att du kan erbjuda bättre information , är du välkommen att kommentera. Och som alltid vänligen dela om du tycker att det här är till hjälp.