{"id":91090,"date":"2020-08-08T13:42:11","date_gmt":"2020-08-08T11:42:11","guid":{"rendered":"https:\/\/prohoster.info\/blog\/administrirovanie\/arhitektura-s3-3-goda-evolyuczii-mail-ru-cloud-storage"},"modified":"2020-08-08T13:42:11","modified_gmt":"2020-08-08T11:42:11","slug":"arhitektura-s3-3-goda-evolyuczii-mail-ru-cloud-storage","status":"publish","type":"post","link":"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/arhitektura-s3-3-goda-evolyuczii-mail-ru-cloud-storage","title":{"rendered":"Architettura S3: 3 anni di evoluzione di Mail.ru Cloud Storage","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"Architettura S3: 3 anni di evoluzione di Mail.ru Cloud Storage\" src=\"\/wp-content\/uploads\/2020\/08\/a53775776b3fc969cc15c9d13a64039d.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<em><noindex><a rel=\"nofollow\" href=\"https:\/\/www.deviantart.com\/st-pete\/art\/Storage-Corridor-408874509\">Corridoio di Archiviazione<\/a><\/noindex> da St-Pete<\/em><\/p>\n<p><\/p>\n<p>Ciao a tutti! Sono Mons Anderson, architetto della piattaforma <noindex><a rel=\"nofollow\" href=\"https:\/\/mcs.mail.ru\/\">Mail.ru Cloud Solutions<\/a><\/noindex>, condivider\u00f2 come abbiamo costruito il nostro storage S3, come funziona, quali soluzioni si sono rivelate efficaci e quali cambieremmo se iniziassimo questo progetto da zero oggi.<\/p>\n<p><\/p>\n<p>Articolo redatto sulla base di una presentazione a <noindex><a rel=\"nofollow\" href=\"https:\/\/corp.mail.ru\/ru\/press\/events\/databases-2\/\">@Databases Meetup<\/a><\/noindex> da Mail.ru Cloud Solutions &amp; Tarantool. In questo articolo parleremo di:<\/p>\n<p><\/p>\n<ul>\n<li>come era strutturato lo storage di Mail.ru, su cui abbiamo costruito lo storage S3;<\/li>\n<li>cosa abbiamo aggiunto per creare Mail.ru Cloud Storage;<\/li>\n<li>come funziona il modello di archiviazione ad oggetti e quali passaggi sono stati svolti per il rilascio in produzione;<\/li>\n<li>sulle ottimizzazioni del sistema operativo: failover e scalabilit\u00e0;<\/li>\n<li>come abbiamo implementato lo sharding e il resharding;<\/li>\n<li>e anche sul lavoro con i certificati SSL.<\/li>\n<\/ul>\n<p><\/p>\n<p>Se non vuoi leggere, puoi <noindex><a rel=\"nofollow\" href=\"https:\/\/youtu.be\/NEgm1nsv-qg\">scoprire<\/a><\/noindex>.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h2 id=\"kak-bylo-ustroeno-hranilische-mailru-poverh-kotorogo-my-stroili-s3-hranilische\">come era strutturato lo storage di Mail.ru, su cui abbiamo costruito lo storage S3<\/h2>\n<p><\/p>\n<p>Lo sviluppo del nostro S3 \u00e8 iniziato sopra lo storage del Cloud Mail.ru, quindi \u00e8 opportuno raccontare prima come \u00e8 strutturato e cosa pu\u00f2 fare.<\/p>\n<p><\/p>\n<p>Lo storage del Cloud Mail.ru \u00e8 composto da server con dischi. In media, un moderno server di archiviazione ha 36 dischi da 12\u201314 terabyte. In passato i dischi erano pi\u00f9 piccoli, ma negli ultimi tre anni le capacit\u00e0 dei dischi sono aumentate e oggi si avvicinano a mezzo petabyte di dati grezzi. <\/p>\n<p><\/p>\n<p>I dischi dei vari server di archiviazione vengono uniti in quelle che chiamiamo \u00abcoppie\u00bb (pair). Una coppia \u00e8 un'unit\u00e0 di archiviazione dei file. In sostanza, \u00e8 un disco montato in una certa partizione su un percorso specifico, dove possono essere collocati file identificati da hash. <\/p>\n<p><\/p>\n<p>Coppia \u00e8 un nome storico, che \u00e8 rimasto fino ad oggi, anche se attualmente in una coppia non ci sono necessariamente solo due dischi. Possono essercene tre, cos\u00ec come varie configurazioni ibride, per esempio 3\/2. <\/p>\n<p>\n<img decoding=\"async\" alt=\"Architettura S3: 3 anni di evoluzione di Mail.ru Cloud Storage\" src=\"\/wp-content\/uploads\/2020\/08\/544ab79846539262e2d4dff6ab95ffff.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><em>Coppie (pair) \u2014 unit\u00e0 di archiviazione degli oggetti<\/em><\/p>\n<p><\/p>\n<p>Tutte le coppie sono memorizzate in PairDB \u2014 un'applicazione basata su Tarantool. Tutte le basi nel nostro storage, fin dalle origini, sono Tarantool; non utilizziamo altri database.<\/p>\n<p><\/p>\n<p>PairDB memorizza tutte le coppie, il loro stato, lo spazio libero, le capacit\u00e0 di failover, gli ultimi errori. Pu\u00f2 anche accedere autonomamente alle coppie, aggiornare il loro stato e controllare se sono operative o meno. In altre parole, PairDB \u00e8 un'istantanea generale dello stato di tutti i dischi del nostro sistema.<\/p>\n<p>\n<img decoding=\"async\" alt=\"Architettura S3: 3 anni di evoluzione di Mail.ru Cloud Storage\" src=\"\/wp-content\/uploads\/2020\/08\/d50781b8b51ed5fe126bc84e19c934d1.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><em>Pair DB: database con lo stato delle coppie<\/em><\/p>\n<p><\/p>\n<p>Sui pair sono memorizzati i file, e per sapere su quale coppia si trova un file, \u00e8 necessario un ulteriore database \u2014 FileDB. Questo memorizza il mapping, la corrispondenza: il file X \u00e8 memorizzato sulla coppia Y, assieme a un piccolo numero di attributi necessari.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Architettura S3: 3 anni di evoluzione di Mail.ru Cloud Storage\" src=\"\/wp-content\/uploads\/2020\/08\/b1a64737cf7f916bff446c10c1f01d4c.jpeg\" style=\"display:block;margin: 0 auto;\" \/><em>File DB: luogo dove viene memorizzato il file<\/em><\/p>\n<p>Un altro elemento importante \u00e8 il servizio Nylon, un router per l'interazione con i database. \u00c8 un unico punto di accesso, permette di lavorare attraverso un'interfaccia unificata sia con PairDB che con FileDB. Si tratta di un servizio stateless, esegue il bilanciamento delle richieste, comprende su quale shard di FileDB bisogna andare, e sa quali coppie sono attive e quali no.<\/p>\n<p>\n<img decoding=\"async\" alt=\"Architettura S3: 3 anni di evoluzione di Mail.ru Cloud Storage\" src=\"\/wp-content\/uploads\/2020\/08\/3e2225f229c8cfa462d620d2b5fb581e.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><em>Nylon: router per l'interazione con i database<\/em><\/p>\n<p><\/p>\n<p>Inoltre, \u00e8 necessario un modo per caricare i contenuti nello storage. A tale scopo, esiste un servizio chiamato Streamer. Questo fornisce due metodi HTTP: il metodo PUT per caricare contenuti nello storage e il metodo GET per scaricarli. HTTP \u00e8 un protocollo piuttosto popolare e comodo per il trasferimento di dati. <\/p>\n<p><\/p>\n<p>Quando ci rivolgiamo a Streamer, questo si collega a PairDB tramite Nylon, determina a quale coppia \u00e8 possibile caricare il file e poi trasferisce i dati tramite WebDAV a quella coppia. <\/p>\n<p><\/p>\n<p>In sostanza, qualsiasi server di archiviazione \u00e8 nginx pi\u00f9 dischi montati su percorsi specificati. Possiamo caricare un file nello storage da Streamer, eliminarlo, rinominarlo o verificarne l'integrit\u00e0. Quindi, questo \u00e8 un'interfaccia comoda per interagire a basso livello con lo storage. <\/p>\n<p>\n<img decoding=\"async\" alt=\"Architettura S3: 3 anni di evoluzione di Mail.ru Cloud Storage\" src=\"\/wp-content\/uploads\/2020\/08\/3722a89ed44cace36e9cb1f8bee4bd1e.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><em>Streamer: punto di accesso nello storage<\/em><\/p>\n<p><\/p>\n<h2 id=\"chto-my-dobavili-chtoby-sdelat-s3-hranilische\">Cosa abbiamo aggiunto per creare lo storage S3<\/h2>\n<p><\/p>\n<p>Quindi, abbiamo esaminato la struttura di base dello storage al momento in cui ci siamo preparati a lanciare lo storage S3. Usando il metodo PUT, potevamo collocare contenuti arbitrari e ricevere come identificatore di questi dati un hash. Con questo identificatore, era quindi possibile tornare a recuperare il file originale. Ma ci\u00f2 non \u00e8 sufficiente per realizzare S3. Nel protocollo S3, oltre alla semplice archiviazione degli oggetti, ci sono:<\/p>\n<p><\/p>\n<ul>\n<li>archiviazione dei metadati \u2014 propriet\u00e0 aggiuntive degli oggetti;<\/li>\n<li>organizzazione dell'accesso agli oggetti tramite HTTP;<\/li>\n<li>raggruppamento degli oggetti in collezioni \u2014 bucket;<\/li>\n<li>Endpoint HTTP-S3. S3 organizza i dati in strutture specifiche \u2014 bucket, ognuno dei quali fornisce un punto di accesso per memorizzare file.<\/li>\n<\/ul>\n<p><\/p>\n<p>Per realizzare questa logica, era necessario un servizio separato. Volevamo anche prevedere l'architettura per una futura crescita del servizio con scalabilit\u00e0 lineare.<\/p>\n<p><\/p>\n<h2 id=\"pervye-komponenty\">I primi componenti<\/h2>\n<p><\/p>\n<p>Demonio che implementa l'API S3. Si tratta dell'API S3 standard di Amazon, che supporta operazioni XML per i metadati e consente di trasferire direttamente i contenuti. Non abbiamo dovuto inventare nulla, tutto \u00e8 descritto e documentato.<\/p>\n<p><\/p>\n<p>Abbiamo anche posizionato Nginx davanti al servizio. Lo abbiamo utilizzato per la terminazione SSL, il bilanciamento del carico e per alcune logiche in Lua (metriche, logging e tracing).<\/p>\n<p><\/p>\n<p>Per la memorizzazione dei metadati S3 abbiamo scelto anche Tarantool. Nella prima versione, il demone S3 accedeva a questo database per i metadati, mentre i contenuti venivano memorizzati in un grande storage tramite Streamer.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Architettura S3: 3 anni di evoluzione di Mail.ru Cloud Storage\" src=\"\/wp-content\/uploads\/2020\/08\/03dddec282b5bb41eb63748ccfb6c9a4.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<em>Nginx + API S3 + metadati<\/em><\/p>\n<p><\/p>\n<h2 id=\"obektnaya-model-hraneniya\">Modello oggetti di memorizzazione<\/h2>\n<p><\/p>\n<p>Vediamo come funziona S3. L'utente pu\u00f2 creare un bucket, una collezione di oggetti. Il bucket \u00e8 indirizzato tramite il nome host e rappresenta un sottodominio del servizio. All'interno del bucket, l'utente pu\u00f2 creare oggetti. L'identificatore dell'oggetto \u00e8 l'URL. Il contenuto dell'oggetto \u00e8 un blob, un array di dati binari che memorizzeremo nello storage. Ogni oggetto ha anche attributi: il nome \u2013 quell'URL, ACL (Access Control List), altri attributi aggiuntivi o arbitrari \u2013 tutto questo viene conservato nei metadati. <\/p>\n<p><\/p>\n<p>Uno schema normalizzato di questi dati potrebbe apparire cos\u00ec: ci sono progetti che possiedono bucket, che possiedono oggetti e gli oggetti possono essere composti. Poich\u00e9 uno dei modi per caricare un oggetto \u00e8 a parti, ci sono due tabelle ausiliarie per il caricamento: uploads e chunks. Inoltre, i progetti hanno credenziali di accesso e billing. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Architettura S3: 3 anni di evoluzione di Mail.ru Cloud Storage\" src=\"\/wp-content\/uploads\/2020\/08\/e2bede45ba4044f658b47a9840fd5224.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<em>Schema dei dati<\/em><\/p>\n<p><\/p>\n<p>Poich\u00e9 stavamo creando un servizio B2B con accesso a pagamento, era necessario un sistema di billing in questo schema.<br \/>\nIl servizio di billing \u00e8 stato anch'esso implementato su Tarantool. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Architettura S3: 3 anni di evoluzione di Mail.ru Cloud Storage\" src=\"\/wp-content\/uploads\/2020\/08\/d5b1a63e2273e933c95deecdb054bfe6.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<h2 id=\"dorabotki-s3-hranilischa-shagi-k-prodakshenu\">Sviluppi dello storage S3: passi verso la produzione<\/h2>\n<p><\/p>\n<p>Abbiamo gi\u00e0 realizzato un modello funzionante che pu\u00f2 essere utilizzato: gli oggetti e i metadati erano memorizzati, ma mancavano ancora alcuni aspetti per il lancio in produzione.<\/p>\n<p><\/p>\n<p>Innanzitutto, la necessit\u00e0 di un sistema di rate limiting. Se avessimo avviato il servizio senza di esso, in caso di carico massimo avremmo potuto sovraccaricare imprevedibilmente qualche parte del sistema. Il rate limit deve funzionare in questo modo: ogni richiesta S3 arriva su un host specifico, quest'host \u00e8 l'identificatore del bucket, e il bucket appartiene a un cliente. Dobbiamo definire una funzione per il bucket che permetta di calcolare il rate limit. <\/p>\n<p><\/p>\n<p>Inoltre, il sistema di rate limiting deve essere sufficientemente performante per gestire il carico che arriva su S3.<\/p>\n<p><\/p>\n<p>Qui abbiamo di nuovo utilizzato Tarantool. I rate limit sono un cluster di 21 istanze, le istanze sono suddivise in gruppi, distribuite su tre nodi fisici e unite in un grande cluster topologico. Le modifiche di configurazione vengono propagate automaticamente su di esso: si impostano i rate limit, i default e la configurazione. Ogni bucket \u00e8 servito esclusivamente da un'istanza. Quando una richiesta per un bucket specifico arriva, si calcola l'istanza responsabile per quel bucket. All'interno di questo nodo si conta il rate attuale delle richieste utilizzando un algoritmo simile al Token Bucket. Successivamente, il sistema di rate limiting, sulla base delle attuali metriche di carico e delle propriet\u00e0 stabilite per il bucket specifico, decide se la richiesta pu\u00f2 essere eseguita o meno. Il controllo dei limiti viene effettuato nella fase pi\u00f9 precoce dell'esecuzione della richiesta S3, proteggendo tutti gli altri elementi del sistema da un carico eccessivo. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Architettura S3: 3 anni di evoluzione di Mail.ru Cloud Storage\" src=\"\/wp-content\/uploads\/2020\/08\/1b91e5d1fe067c859ba9b36d58827579.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Inoltre, sotto carico \u00e8 piuttosto difficile fare a meno della cache. In S3 si prevede l'accesso ripetuto agli stessi oggetti, quindi si tratta di uno storage caldo. Di norma, l'accesso a un singolo file viene gestito da un'intera catena: Streamer, FileDB, PairDB, Storage. Ma durante i ripetuti accessi a un file, ottimizziamo l'accesso a questi contenuti tramite una cache locale.<\/p>\n<p><\/p>\n<p>La cache \u00e8 multilivello e implementata utilizzando nginx, dischi SSD locali e RAM. Qui non abbiamo utilizzato Tarantool, perch\u00e9 \u00e8 pi\u00f9 comodo restituire oggetti dal filesystem, in questo modo possiamo fare tiering della cache. Inoltre, abbiamo grandi oggetti con una dimensione massima di 32 gigabyte, mentre in Tarantool \u00e8 possibile memorizzare solo oggetti di piccole dimensioni.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Architettura S3: 3 anni di evoluzione di Mail.ru Cloud Storage\" src=\"\/wp-content\/uploads\/2020\/08\/faa02bd52a1d70642589d775f22c5e75.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Questo primo sistema, con cui siamo partiti, aveva una capacity (capacit\u00e0) calcolata, sufficiente per esplorare e comprendere il prodotto e dimostrare che avrebbe funzionato. <\/p>\n<p><\/p>\n<h2 id=\"dorabotki-boevoy-sistemy-feylover-i-masshtabirovanie\">Sviluppi del sistema in produzione: failover e scaling<\/h2>\n<p><\/p>\n<p>Il sistema era gi\u00e0 operativo, ma all'inizio avevamo trascurato alcune cose \u2013 era necessario aggiungere failover e scaling. <\/p>\n<p><\/p>\n<p>Il nostro demone S3 ha recuperato i metadati tramite il protocollo Tarantool. Abbiamo sostituito il database originale con Tarantool, che fungeva da proxy-router per le richieste di metadati. Dal punto di vista dell'applicazione che implementa l'API, nulla \u00e8 cambiato: ha continuato a interagire con il database tramite il protocollo Tarantool, ma il router \u00e8 stato in grado di garantire un failover attivo. Ci\u00f2 significa che abbiamo potuto monitorare l'accessibilit\u00e0 del nodo, gestire le pause durante i passaggi e guasti, e cos\u00ec via. In tutto questo, non abbiamo modificato l'applicazione stessa. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Architettura S3: 3 anni di evoluzione di Mail.ru Cloud Storage\" src=\"\/wp-content\/uploads\/2020\/08\/978ff8a458f8d48b98672121cf6eca5d.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<h2 id=\"podrobnee-o-tom-kak-my-realizovali-shardirovanie\">Scopri di pi\u00f9 su come abbiamo implementato lo sharding<\/h2>\n<p><\/p>\n<p>La prossima questione a cui abbiamo dovuto pensare \u00e8 stata lo sharding. Il sistema stava crescendo, il numero di oggetti aumentava e bisognava garantire opportunit\u00e0 per una futura crescita.<\/p>\n<p><\/p>\n<p>Torniamo allo schema dei dati: ci sono progetti, bucket, credenziali e fatturazione. Questi sono oggetti che, con alta probabilit\u00e0, non cresceranno oltre un singolo'istanza sia in termini di volume che di richieste. Pertanto, non ha senso shardarli, cos\u00ec abbiamo trasferito questi oggetti su un'istanza separata che rimarr\u00e0 non shardata. Questo consente una gestione pi\u00f9 coerente di progetti e bucket, poich\u00e9 c'\u00e8 un'unica entit\u00e0 non shardata. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Architettura S3: 3 anni di evoluzione di Mail.ru Cloud Storage\" src=\"\/wp-content\/uploads\/2020\/08\/c5a1c1a875e756e3dceb5f885fbda2c8.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Ci sono anche oggetti nel sistema che crescono linearmente: inizialmente ce n'erano centinaia di migliaia, ora il loro numero si misura in miliardi. Tali oggetti e le loro parti dovevano essere trasferiti in un cluster shardato. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Architettura S3: 3 anni di evoluzione di Mail.ru Cloud Storage\" src=\"\/wp-content\/uploads\/2020\/08\/00bb418cc61ad2e3e8797caf5d1ab202.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Abbiamo diviso lo schema, ma gli oggetti devono lavorare con i bucket: ogni oggetto appartiene a un bucket specifico, in pi\u00f9 sull'bucket \u00e8 attivo il controllo ACL. Pertanto, per ogni shard di oggetti manteniamo una copia ombra di ogni bucket. Inoltre, durante la modifica degli oggetti e l'esecuzione delle richieste, \u00e8 necessario calcolare il volume per la fatturazione, quindi su ogni shard ci sono contatori per la fatturazione.<\/p>\n<p><\/p>\n<p>Abbiamo anche aggiunto alcune altre tabelle e componenti:<\/p>\n<p><\/p>\n<ul>\n<li>un cestino, per eliminare vecchi progetti che vengono rimossi o messi in pausa;<\/li>\n<li>una coda per attivit\u00e0 in background, cio\u00e8 l'archiviazione principale pu\u00f2 eseguire attivit\u00e0 in background che \u00e8 necessario svolgere nel cluster;<\/li>\n<li>supporto per lifecycle \u2014 un meccanismo che consente di lavorare con oggetti e gestire il loro ciclo di vita.<\/li>\n<\/ul>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Architettura S3: 3 anni di evoluzione di Mail.ru Cloud Storage\" src=\"\/wp-content\/uploads\/2020\/08\/933e98dc559eb8e6bac14003215a6836.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Poich\u00e9 parte dei dati \u00e8 stata trasferita sugli shard, \u00e8 stata necessaria una proxy di sharding. Si sarebbe potuto riutilizzare il router per questo ruolo, ma una proxy di sharding separata, responsabile esclusivamente dello sharding dei dati, consente al router di recuperare i dati in modo completo, senza pensare allo sharding.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Architettura S3: 3 anni di evoluzione di Mail.ru Cloud Storage\" src=\"\/wp-content\/uploads\/2020\/08\/4b181ed4629180e15558f25b1e4d5718.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Spiegher\u00f2 separatamente perch\u00e9 non abbiamo scelto una soluzione pronta, ma volevamo creare una funzione di sharding personalizzata. <\/p>\n<p><\/p>\n<p>Vediamo come \u00e8 strutturata. Abbiamo 256 shard disponibili. Per ogni bucket, assegniamo un intervallo utilizzando una certa funzione di coerenza. \u00c8 semplice: proprio come si determina l'appartenenza a uno shard tramite una funzione di coerenza, cos\u00ec si determina lo shard iniziale e si assegna un intervallo:<\/p>\n<p><\/p>\n<p><code>f(bucket, shards) = subset<\/code><\/p>\n<p><\/p>\n<p>Ci\u00f2 significa che, prendendo un bucket, si pu\u00f2 dire che esso e i suoi dati saranno sempre collocati in un sottoinsieme specifico di tutti gli shard. Questo riduce l'impatto di alcuni bucket sugli altri e semplifica l'esecuzione delle richieste map-reduce, quando ad esempio \u00e8 necessario elencare gli oggetti di un bucket. Per farlo, \u00e8 necessario interrogare tutti gli shard dove questi oggetti sono memorizzati. Se gli oggetti fossero distribuiti su tutti gli shard, qualsiasi elencazione influenzerebbe l'intero sistema; qui invece colpisce solo un sottoinsieme specifico.<\/p>\n<p><\/p>\n<p>Dopo, ogni oggetto appartiene a un bucket specifico, quindi quando richiediamo un oggetto, lo facciamo attraverso il suo nome in un bucket specifico. Possiamo quindi definire una funzione per l'oggetto non su tutto l'intervallo di shard disponibili, ma solo su un sottoinsieme del suo bucket:<\/p>\n<p><\/p>\n<p><code>f(object, subset) = shard<\/code><\/p>\n<p><\/p>\n<p>Prendiamo un oggetto specifico, passando come argomenti alla funzione non tutti gli shard, ma un sottoinsieme del suo bucket - e otteniamo uno shard specifico. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Architettura S3: 3 anni di evoluzione di Mail.ru Cloud Storage\" src=\"\/wp-content\/uploads\/2020\/08\/10480ad2430c228c511ff3cdc5071596.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Quindi, lo sharding \u00e8 implementato, c'\u00e8 una proxy di sharding. Rimane da utilizzare il router e il database con i metadati per interagire con la proxy di sharding. Ad esempio, per la creazione di oggetti di copie ombra: quando creiamo un bucket, lo storage principale deve creare un rappresentante di questo bucket su tutti gli shard dove deve essere presente.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Architettura S3: 3 anni di evoluzione di Mail.ru Cloud Storage\" src=\"\/wp-content\/uploads\/2020\/08\/bb34d1f747903a3c2f08f582e4424787.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<h2 id=\"kak-my-realizovali-resharding\">Come abbiamo implementato il resharding<\/h2>\n<p><\/p>\n<p>Il problema pi\u00f9 grande dello sharding \u00e8 il resharding. Era importante farlo senza downtime, poich\u00e9 il sistema era gi\u00e0 in produzione. Mostrer\u00f2 come abbiamo risolto il problema utilizzando un esempio di un compito simile con la migrazione dei dati da un progetto a un altro.<\/p>\n<p><\/p>\n<p>Di seguito \u00e8 riportato lo schema del nostro cluster, realizzato dopo l'implementazione del sharding. Abbiamo nginx, S3 API, un router, un database primario con progetti, un proxy di sharding e i relativi shard.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Architettura S3: 3 anni di evoluzione di Mail.ru Cloud Storage\" src=\"\/wp-content\/uploads\/2020\/08\/0e6bd16c7fc47437b3b7d96b6d9809a4.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Sopra ho trascurato di menzionare che, a un certo punto del progetto, c'era un obiettivo di prodotto: \"Avviare un ulteriore storage, Icebox, simile a Hotbox, ma per dati freddi\". In sostanza, si trattava dello stesso tipo di storage, ma con URL diversi e senza cache.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Architettura S3: 3 anni di evoluzione di Mail.ru Cloud Storage\" src=\"\/wp-content\/uploads\/2020\/08\/9ce9085e1d03e9a99b6b8ccc0717c653.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Icebox \u00e8 stato utilizzato meno di Hotbox, quindi \u00e8 rimasto senza sharding per un lungo periodo. Alla fine, abbiamo deciso di eliminarlo e unire Hotbox e Icebox in un unico servizio, semplicemente separando le classi di storage. <\/p>\n<p><\/p>\n<p>I bucket negli storage non si sovrapponevano, potevano essere facilmente fusi e spostati, ma i clienti utilizzavano entrambi gli storage, quindi era necessario risolvere il problema dell'assenza di downtime. Non era possibile semplicemente spegnere e copiare. Abbiamo effettuato la migrazione in pi\u00f9 fasi.<\/p>\n<p><\/p>\n<p>Per iniziare, abbiamo sincronizzato gli storage primari. Avevamo Tarantool e potevamo, al momento della creazione di un oggetto, fare in modo che: <\/p>\n<p><\/p>\n<ul>\n<li>una richiesta di creazione di un bucket arrivasse al database, ad esempio in Hotbox;<\/li>\n<li>Tarantool controllava in un altro database (in questo caso, in Icebox) se esisteva gi\u00e0 quel bucket;<\/li>\n<li>se il bucket esisteva, il database segnalava che non poteva essere creato e si sincronizzava come esistente.<br \/>\n<img decoding=\"async\" alt=\"Architettura S3: 3 anni di evoluzione di Mail.ru Cloud Storage\" src=\"\/wp-content\/uploads\/2020\/08\/6694c9804f09942416c1717b455b9fd3.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<em>Sincronizzazione dei bucket<\/em><\/li>\n<\/ul>\n<p><\/p>\n<p>Nel database che doveva ricevere tutti i dati, \u00e8 stato introdotto un segnale per progetti e bucket che indicava dove si trovava quell'oggetto. Poteva essere memorizzato localmente, cio\u00e8 in Hotbox, in Icebox\u2014 in questo caso, non vi erano dati nel nuovo storage\u2014 oppure poteva essere in uno stato di migrazione.<\/p>\n<p><\/p>\n<p>Se un progetto o un bucket aveva il segnale 'Migrating', durante la migrazione la richiesta veniva eseguita prima nel nuovo storage, dove i dati dovevano trovarsi, e se non erano presenti, le richieste venivano reindirizzate allo storage alternativo.<\/p>\n<p><\/p>\n<p>Dopo abbiamo reindirizzato il traffico. Poich\u00e9 l'API poteva gestire sia le richieste di Icebox che quelle di Hotbox, siamo riusciti a reindirizzare il traffico senza downtime, semplicemente trasferendo gli host e aggiungendo le relative voci in Nginx. <\/p>\n<p><\/p>\n<p>Dopo che il traffico \u00e8 stato reindirizzato, abbiamo potuto rimuovere Nginx e l'API di Icebox.<br \/>\nSuccessivamente, abbiamo rimosso Icebox nginx e S3 API\u2014 e tutto ha iniziato a funzionare:<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Architettura S3: 3 anni di evoluzione di Mail.ru Cloud Storage\" src=\"\/wp-content\/uploads\/2020\/08\/62d9f960fc1f11b875a8f8a5aa8e8152.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Dopo la migrazione dei dati, non abbiamo pi\u00f9 bisogno del vecchio storage e rimuoviamo i resti del sistema precedente, cos\u00ec come il supporto per lo stato di migrazione nel codice.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Architettura S3: 3 anni di evoluzione di Mail.ru Cloud Storage\" src=\"\/wp-content\/uploads\/2020\/08\/1a3129136f7ccacfdcff260f10cb0605.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Utilizzando gli stessi principi, \u00e8 stata effettuata anche la re-shardizzazione dal vecchio storage a quello sharded:<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Architettura S3: 3 anni di evoluzione di Mail.ru Cloud Storage\" src=\"\/wp-content\/uploads\/2020\/08\/13b6f11add40c21a3b9afc05dd0dfea9.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Abbiamo contrassegnato tutti i bucket come<\/p>\n<p><\/p>\n<ul>\n<li>Non-sharded <code>. Tutte le richieste ad essi andavano all'originale, storage non sharded.<\/code>I nuovi bucket venivano creati immediatamente con lo stato<\/li>\n<li>Sharded <code>. Uno per uno, prendevamo i bucket, impostavamo lo stato<\/code>.<\/li>\n<li>Migrating <code>e trasferivamo i dati.<\/code> Le richieste venivano gestite secondo il principio:<\/li>\n<\/ul>\n<p><\/p>\n<p>Leggiamo nel nuovo, poi nel vecchio.<\/p>\n<p><\/p>\n<ul>\n<li>Creiamo solo nel nuovo.<\/li>\n<li>Aggiorniamo in due fasi: se nel nuovo non c'\u00e8 nulla, trasferiamo dal vecchio al nuovo, poi aggiorniamo.<\/li>\n<li>Gestione dei certificati SSL<\/li>\n<\/ul>\n<p><\/p>\n<h2 id=\"rabota-s-ssl-sertifikatami\">Sul frontend utilizziamo Nginx. Nel nostro caso, non \u00e8 il solito Nginx, ma OpenResty, Nginx con supporto per LuaJIT.<\/h2>\n<p><\/p>\n<blockquote><p>Un altro elemento del sistema \u00e8 la gestione dei certificati SSL. In uno storage S3 puoi impostare un tuo dominio per accedere a un bucket specifico, semplicemente attraverso<\/p><\/blockquote>\n<p>. Ma senza HTTPS al giorno d'oggi non \u00e8 possibile: un dominio personale implica un certificato SSL personale. <code>CNAME<\/code>Come ho gi\u00e0 detto, per il bilanciamento e la terminazione SSL ci occupiamo di Nginx. Nel nostro caso, non si tratta del consueto Nginx, ma di OpenResty, Nginx con supporto per LuaJIT. <\/p>\n<p><\/p>\n<p>Questo ci ha permesso di insegnare al nostro Nginx a restituire certificati arbitrari in modo abbastanza semplice. Inoltre, era necessario restituire i certificati in modo dinamico (senza bisogno di scriverli nel file di configurazione). Abbiamo utilizzato l'estensione<\/p>\n<p><\/p>\n<p>ssl_certificate_by_lua <code>, che consente di leggere il certificato da una fonte arbitraria direttamente durante il handshake TLS. Come archivio di certificati abbiamo anche utilizzato Tarantool: questo permette di gestire i certificati da remoto e assicura una restituzione estremamente veloce.<\/code>\u00c8 stato implementato anche un demone separato, il cui compito \u00e8 il regolare aggiornamento dei certificati rilasciati tramite Let's Encrypt.<\/p>\n<p><\/p>\n<p>\u00c8 stato implementato anche un demone separato, il cui compito \u00e8 quello di aggiornare regolarmente i certificati emessi tramite Let's Encrypt.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Architettura S3: 3 anni di evoluzione di Mail.ru Cloud Storage\" src=\"\/wp-content\/uploads\/2020\/08\/8d61c1cb3084d9eb4eb8faa745e212db.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<h2 id=\"chto-by-ya-sohranil-a-chto-sdelal-po-drugomu-esli-razrabatyvat-hranilische-zanovo\">Cosa avremmo dovuto utilizzare fin dall'inizio<\/h2>\n<p><\/p>\n<h3 id=\"chto-nuzhno-bylo-ispolzovat-s-samogo-nachala\">Sharding subito<\/h3>\n<p><\/p>\n<p><strong>Sharding immediato<\/strong>. Resharding ha presentato diverse problematiche. \u00c8 facile da realizzare, ma se si avviano progetti che necessitano di scalabilit\u00e0, \u00e8 meglio partire direttamente con un cluster sharded, anche se con il numero minimo di nodi. Implementare il resharding all'inizio \u00e8 quasi gratuito rispetto a farlo in un sistema operativo.<\/p>\n<p><\/p>\n<p><strong>Lavorare con Tarantool attraverso i bilanciatori<\/strong>. Ora colleghiamo subito tutti i nuovi database ai bilanciatori. Questo consente di ampliare le funzionalit\u00e0 e ottenere una maggiore resilienza. <\/p>\n<p><\/p>\n<p><strong>Failover automatico<\/strong>. Avrei installato tutti gli strumenti necessari per il failover automatico, poich\u00e9 i primi fallimenti dopo il lancio erano dovuti alla sua assenza. Dopo l'esperienza con S3, tutti i prodotti successivi sono stati lanciati tenendo conto di questo.<\/p>\n<p><\/p>\n<p><strong>Funzionalit\u00e0 di versionamento di S3<\/strong>. Inizialmente sembrava che non fosse una funzionalit\u00e0 molto richiesta. Integrare questa possibilit\u00e0 nell'architettura di un sistema operativo esistente \u00e8 estremamente complesso.<\/p>\n<p><\/p>\n<p><strong>Fatturazione separata<\/strong>. Il modo in cui abbiamo integrato la fatturazione nel nostro sistema ha funzionato bene all'inizio, ma in seguito \u00e8 diventato un ostacolo; sarebbe stato meglio integrarlo come servizio completamente separato.<\/p>\n<p><\/p>\n<h3 id=\"chto-bylo-udachnym-resheniem\">Cosa si \u00e8 rivelato essere una buona soluzione<\/h3>\n<p><\/p>\n<p><strong>Modello dati<\/strong>. La storia ha dimostrato che, man mano che il servizio cresceva, ci si adattava abbastanza bene al modello di dati di Amazon, permettendo cos\u00ec di implementare le funzionalit\u00e0 presenti l\u00ec.<\/p>\n<p><\/p>\n<p><strong>Schema di sharding<\/strong>. Sosterrei operative simili per lo sharding a intervallo per i bucket, poich\u00e9 ci\u00f2 consente di distribuire bene le richieste tra i diversi bucket in un grande cluster.<\/p>\n<p><\/p>\n<p><strong>Utilizzo di Tarantool<\/strong>. Tarantool ha fornito un grande aiuto nello sviluppo e nella modifica del servizio; abbiamo lavorato facilmente con i dati, trasformando e shardando il deposito, senza dover salire al livello dell'applicazione. <\/p>\n<p><\/p>\n<blockquote><p>Questa relazione \u00e8 stata presentata per la prima volta al <noindex><a rel=\"nofollow\" href=\"https:\/\/corp.mail.ru\/ru\/press\/events\/databases-2\/\">@Databases Meetup<\/a><\/noindex> by Mail.ru Cloud Solutions&amp;Tarantool. Vedi <noindex><a rel=\"nofollow\" href=\"https:\/\/www.youtube.com\/watch?v=jM4hL2u6JM0&amp;list=PLQzTaxmOHjntyNRPWhaWHqlHp8UN_wgQ3\">video<\/a><\/noindex> altri interventi e iscriviti agli avvisi degli eventi su Telegram <noindex><a rel=\"nofollow\" href=\"https:\/\/t.me\/k8s_mail\">Attorno a Kubernetes in Mail.ru Group<\/a><\/noindex>.<\/p><\/blockquote>\n<p>Puoi anche guardare la mia vecchia presentazione su S3 o leggere l'articolo del mio collega sullo storage a blocchi.<\/p>\n<p><\/p>\n<ul>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/www.youtube.com\/watch?v=O0iIADHgBVc\">Reverse engineering dell'architettura di Amazon S3 e come appariva lo storage S3 di MCS 3 anni fa<\/a><\/noindex>.<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/mailru\/blog\/472694\/\">Pi\u00f9 di Ceph: soluzione di storage a blocchi nel cloud MCS<\/a><\/noindex>.<\/li>\n<\/ul>\n<p>Fonte: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/mailru\/blog\/513356\/\">habr.com<\/a> <\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>Storage Corridor by St-Pete \u0412\u0441\u0435\u043c \u043f\u0440\u0438\u0432\u0435\u0442! \u042f Mons Anderson, \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u043e\u0440 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b Mail.ru Cloud Solutions, \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443, \u043a\u0430\u043a \u043c\u044b \u043f\u043e\u0441\u0442\u0440\u043e\u0438\u043b\u0438 \u043d\u0430\u0448\u0435 S3-\u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435, \u043a\u0430\u043a \u043e\u043d\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442, \u043a\u0430\u043a\u0438\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u043e\u043a\u0430\u0437\u0430\u043b\u0438\u0441\u044c \u0443\u0434\u0430\u0447\u043d\u044b\u043c\u0438, \u0430 \u043a\u0430\u043a\u0438\u0435 \u0441\u0442\u043e\u0438\u043b\u043e \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c, \u0435\u0441\u043b\u0438 \u0431\u044b \u043c\u044b \u043d\u0430\u0447\u0430\u043b\u0438 \u0442\u0430\u043a\u043e\u0439 \u0436\u0435 \u043f\u0440\u043e\u0435\u043a\u0442 \u0441 \u043d\u0443\u043b\u044f \u0441\u0435\u0439\u0447\u0430\u0441. \u0421\u0442\u0430\u0442\u044c\u044f \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043b\u0435\u043d\u0430 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u0434\u043e\u043a\u043b\u0430\u0434\u0430 \u043d\u0430 @Databases Meetup by Mail.ru Cloud Solutions &amp; Tarantool. [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":91091,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-91090","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.0.1 - aioseo.com -->\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/arhitektura-s3-3-goda-evolyuczii-mail-ru-cloud-storage\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.0.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"it_IT\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u0410\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430 S3: 3 \u0433\u043e\u0434\u0430 \u044d\u0432\u043e\u043b\u044e\u0446\u0438\u0438 Mail.ru Cloud Storage | ProHoster\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/arhitektura-s3-3-goda-evolyuczii-mail-ru-cloud-storage\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2020-08-08T11:42:11+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2020-08-08T11:42:11+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47Architettura S3: 3 anni di evoluzione di Mail.ru Cloud Storage | ProHoster","description":"","canonical_url":"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/arhitektura-s3-3-goda-evolyuczii-mail-ru-cloud-storage","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"it_IT","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u0410\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430 S3: 3 \u0433\u043e\u0434\u0430 \u044d\u0432\u043e\u043b\u044e\u0446\u0438\u0438 Mail.ru Cloud Storage | ProHoster","og:url":"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/arhitektura-s3-3-goda-evolyuczii-mail-ru-cloud-storage","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2020-08-08T11:42:11+00:00","article:modified_time":"2020-08-08T11:42:11+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"91090","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":null,"breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-02-28 12:34:25","updated":"2022-10-02 13:27:50","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts\/91090","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/comments?post=91090"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts\/91090\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/media\/91091"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/media?parent=91090"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/categories?post=91090"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/tags?post=91090"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}