Exportación a almacenamento de obxectos
Un obxecto JSON por obxectivo cumprido nun bucket seu. Esta é a vía para todos os almacéns de datos que non sexan BigQuery.
1. O oco que cobre
Ata agora só había unha vía de MousePlayer a un almacén de datos e levaba a Google. Se usa Snowflake, Redshift ou ClickHouse, non había ningunha, aínda que os tres len almacenamento de obxectos sen problemas.
Por iso a ponte escribe en almacenamento de obxectos e non en cada almacén de datos por separado. Snowflake, Redshift e ClickHouse reciben datos de S3 e BigQuery de Google Cloud Storage. Unha exportación chega a todos.
| Onde | Como se accede |
|---|---|
| Amazon S3 | Signature Version 4, co bucket no host |
| Cloudflare R2 | Signature Version 4 contra o endpoint da conta |
| Google Cloud Storage | pola súa API compatible con S3 cunha clave HMAC |
| MinIO, Wasabi, Backblaze B2 e outros | Signature Version 4 contra o seu endpoint |
| Azure Blob Storage | unha ligazón SAS do contedor, sen sinatura no noso lado |
2. Por que Azure é distinto e por que é mellor
Azure Blob non usa Signature Version 4; asina con SharedKey. Poderiamos crear outro esquema de sinatura. No seu lugar a ponte acepta unha ligazón SAS do contedor — un URL que xera na súa conta de almacenamento coa sinatura xa dentro.
Isto significa menos código pola nosa parte e menos confianza necesaria pola súa. Nunca vemos unha clave de conta: entréganos un permiso que limitou vostede a un contedor, cunha caducidade escollida e revogable en calquera momento sen tocar nada máis.
Convén aplicar a mesma limitación en S3: dea á clave de acceso permiso para escribir só neste único prefixo e nada máis. Unha clave que só pode engadir a mouseplayer/goals/ non pode ler os outros buckets aínda que se filtre.
3. Un obxecto por obxectivo e a clave é unha data
O almacenamento de obxectos non permite engadir ao final. Un ficheiro diario tería que reescribirse enteiro cada vez e dous obxectivos simultáneos sobrescribiríanse. Por iso cada obxectivo cumprido convértese nun obxecto propio.
O custo son moitos obxectos pequenos; a estrutura da clave fai que funcione:
prefix/YYYY/MM/DD/channel/session-goal.json
Un almacén de datos le un día como unha partición e unha carga histórica é unha exploración de prefixos, non unha consulta. Se quere particionar por proxecto e non por data, poña o ID da canle no prefixo.
Cada obxecto é unha liña JSON
Sen sangrado deliberadamente, para ler un prefixo completo como NDJSON sen abrir os obxectos un por un. Marca de tempo, proxecto, sesión, ID de cliente, obxectivo, valor, moeda e ligazón para reproducir a gravación.
Un valor baleiro é null, non cero
Un obxectivo sen valor monetario escribe null. Nun almacén de datos un cero sumaríase nun total que nunca existiu; a diferenza entre «sen importe acordado» e «importe cero» sobrevive á exportación.
4. Se responde 403, lea isto primeiro
Unha petición S3 rexeitada di moi pouco e hai un motivo polo que a nosa mensaxe de erro di máis que S3: a rexión entra na sinatura. Unha rexión incorrecta e unha clave incorrecta producen o mesmo 403, así que a sospeita evidente, a clave, só é correcta a metade das veces.
Tres cousas que comprobar, nesta orde:
- A rexión, exactamente como a indica o bucket. R2 e Google Cloud Storage usan
autoe non a comproban; os demais si. - O permiso do prefixo. Unha clave limitada a
mouseplayer/non pode escribir enmouseplayer-goals/porque a barra final importa nun ARN de recurso. - O endpoint, para R2 e almacenamentos compatibles con S3. Pegue o host sen
https://; retirámolo de todos os xeitos, pero unha ruta engadida é outro bucket.
O ID da clave de acceso gárdase sen cifrar deliberadamente. Viaxa en cada petición asinada por deseño, polo que cifralo sería esforzo sen protección. O segredo cífrase, non se mostra de novo e nunca entra na cola interna da tarefa.
Todas as marcas mencionadas aquí pertencen aos seus respectivos propietarios. MousePlayer non ten relación comercial con estes provedores.