ΠŸΡ€ΠΈΠΌΠ΅Ρ€ event-driven прилоТСния Π½Π° основС Π²Π΅Π±Ρ…ΡƒΠΊΠΎΠ² Π² ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π½ΠΎΠΌ S3-Ρ…Ρ€Π°Π½ΠΈΠ»ΠΈΡ‰Π΅ Mail.ru Cloud Solutions

ΠŸΡ€ΠΈΠΌΠ΅Ρ€ event-driven прилоТСния Π½Π° основС Π²Π΅Π±Ρ…ΡƒΠΊΠΎΠ² Π² ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π½ΠΎΠΌ S3-Ρ…Ρ€Π°Π½ΠΈΠ»ΠΈΡ‰Π΅ Mail.ru Cloud Solutions
Rube Goldberg coffee machine

Event-driven architecture ΠΏΠΎΠ²Ρ‹ΡˆΠ°Π΅Ρ‚ Ρ†Π΅Π½ΠΎΠ²ΡƒΡŽ ΡΡ„Ρ„Π΅ΠΊΡ‚ΠΈΠ²Π½ΠΎΡΡ‚ΡŒ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌΡ‹Ρ… рСсурсов, ΠΏΠΎΡ‚ΠΎΠΌΡƒ Ρ‡Ρ‚ΠΎ ΠΎΠ½ΠΈ Π·Π°Π΄Π΅ΠΉΡΡ‚Π²ΡƒΡŽΡ‚ΡΡ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π² Ρ‚ΠΎΡ‚ ΠΌΠΎΠΌΠ΅Π½Ρ‚, ΠΊΠΎΠ³Π΄Π° ΠΎΠ½ΠΈ Π½ΡƒΠΆΠ½Ρ‹. БущСствуСт масса Π²Π°Ρ€ΠΈΠ°Π½Ρ‚ΠΎΠ², ΠΊΠ°ΠΊ это Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΈ Π½Π΅ ΡΠΎΠ·Π΄Π°Π²Π°Ρ‚ΡŒ Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹Π΅ ΠΎΠ±Π»Π°Ρ‡Π½Ρ‹Π΅ сущности Π² качСствС worker-ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΉ. И сСгодня я расскаТу Π½Π΅ ΠΏΡ€ΠΎ FaaS, Π° ΠΏΡ€ΠΎ Π²Π΅Π±Ρ…ΡƒΠΊΠΈ. Π― ΠΏΠΎΠΊΠ°ΠΆΡƒ ΡƒΡ‡Π΅Π±Π½Ρ‹ΠΉ ΠΏΡ€ΠΈΠΌΠ΅Ρ€ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ событий с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Π²Π΅Π±Ρ…ΡƒΠΊΠΎΠ² ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π½ΠΎΠ³ΠΎ Ρ…Ρ€Π°Π½ΠΈΠ»ΠΈΡ‰Π°.

ΠŸΠ°Ρ€Π° слов ΠΎΠ± ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π½ΠΎΠΌ Ρ…Ρ€Π°Π½ΠΈΠ»ΠΈΡ‰Π΅ ΠΈ ΠΎ Π²Π΅Π±Ρ…ΡƒΠΊΠ°Ρ…. ΠžΠ±ΡŠΠ΅ΠΊΡ‚Π½Ρ‹Π΅ Ρ…Ρ€Π°Π½ΠΈΠ»ΠΈΡ‰Π° ΠΏΠΎΠ·Π²ΠΎΠ»ΡΡŽΡ‚ Ρ…Ρ€Π°Π½ΠΈΡ‚ΡŒ Π»ΡŽΠ±Ρ‹Π΅ Π΄Π°Π½Π½Ρ‹Π΅ Π² ΠΎΠ±Π»Π°ΠΊΠ΅ Π² Π²ΠΈΠ΄Π΅ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ΠΎΠ², доступных ΠΏΠΎ S3 ΠΈΠ»ΠΈ Π΄Ρ€ΡƒΠ³ΠΎΠΌΡƒ API (Π² зависимости ΠΎΡ‚ Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ) Ρ‡Π΅Ρ€Π΅Π· HTTP/HTTPS. Π’Π΅Π±Ρ…ΡƒΠΊΠΈ (webhooks) Π² ΠΎΠ±Ρ‰Π΅ΠΌ случаС β€” это ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΡΠΊΠΈΠ΅ ΠΎΠ±Ρ€Π°Ρ‚Π½Ρ‹Π΅ Π²Ρ‹Π·ΠΎΠ²Ρ‹ ΠΏΠΎ HTTP. ΠžΠ±Ρ‹Ρ‡Π½ΠΎ ΠΎΠ½ΠΈ Π·Π°ΠΏΡƒΡΠΊΠ°ΡŽΡ‚ΡΡ событиСм, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, ΠΎΡ‚ΠΏΡ€Π°Π²ΠΊΠΎΠΉ ΠΊΠΎΠ΄Π° Π² Ρ€Π΅ΠΏΠΎΠ·ΠΈΡ‚ΠΎΡ€ΠΈΠΉ ΠΈΠ»ΠΈ ΠΊΠΎΠΌΠΌΠ΅Π½Ρ‚Π°Ρ€ΠΈΠ΅ΠΌ, ΠΏΡƒΠ±Π»ΠΈΠΊΡƒΠ΅ΠΌΡ‹ΠΌ Π² Π±Π»ΠΎΠ³Π΅. Когда происходит событиС, исходный сайт отправляСт HTTP-запрос Π½Π° URL-адрСс, ΡƒΠΊΠ°Π·Π°Π½Π½Ρ‹ΠΉ для Π²Π΅Π±Ρ…ΡƒΠΊΠ°. Π’ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π΅ ΠΌΠΎΠΆΠ½ΠΎ ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ Ρ‚Π°ΠΊ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ события Π½Π° ΠΎΠ΄Π½ΠΎΠΌ сайтС Π²Ρ‹Π·Ρ‹Π²Π°Π»ΠΈ дСйствия Π½Π° Π΄Ρ€ΡƒΠ³ΠΎΠΌ (wiki). Π’ случаС, ΠΊΠΎΠ³Π΄Π° исходным сайтом выступаСт ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π½ΠΎΠ΅ Ρ…Ρ€Π°Π½ΠΈΠ»ΠΈΡ‰Π΅, Π² Ρ€ΠΎΠ»ΠΈ событий Π²Ρ‹ΡΡ‚ΡƒΠΏΠ°ΡŽΡ‚ измСнСния Π΅Π³ΠΎ содСрТимого.

ΠŸΡ€ΠΈΠΌΠ΅Ρ€Ρ‹ простых кСйсов, ΠΊΠΎΠ³Π΄Π° ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Ρ‚Π°ΠΊΡƒΡŽ Π°Π²Ρ‚ΠΎΠΌΠ°Ρ‚ΠΈΠ·Π°Ρ†ΠΈΡŽ:

  1. Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ ΠΊΠΎΠΏΠΈΠΉ всСх ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ΠΎΠ² Π² Π΄Ρ€ΡƒΠ³ΠΎΠΌ ΠΎΠ±Π»Π°Ρ‡Π½ΠΎΠΌ Ρ…Ρ€Π°Π½ΠΈΠ»ΠΈΡ‰Π΅. Копии Π΄ΠΎΠ»ΠΆΠ½Ρ‹ ΡΠΎΠ·Π΄Π°Π²Π°Ρ‚ΡŒΡΡ Β«Π½Π° Π»Π΅Ρ‚ΡƒΒ», ΠΏΡ€ΠΈ любом Π΄ΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΠΈ ΠΈΠ»ΠΈ ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠΈ Ρ„Π°ΠΉΠ»ΠΎΠ².
  2. АвтоматичСскоС созданиС сСрий ΠΌΠΈΠ½ΠΈΠ°Ρ‚ΡŽΡ€ графичСских Ρ„Π°ΠΉΠ»ΠΎΠ², Π΄ΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΠ΅ водяных Π·Π½Π°ΠΊΠΎΠ² ΠΊ фотографиям, Π΄Ρ€ΡƒΠ³ΠΈΠ΅ ΠΌΠΎΠ΄ΠΈΡ„ΠΈΠΊΠ°Ρ†ΠΈΠΈ ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠΉ.
  3. ΠžΠΏΠΎΠ²Π΅Ρ‰Π΅Π½ΠΈΠ΅ ΠΎ ΠΏΡ€ΠΈΡ…ΠΎΠ΄Π΅ Π½ΠΎΠ²Ρ‹Ρ… Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚ΠΎΠ² (ΠΊ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Ρƒ, распрСдСлСнная бухгалтСрская слуТба Π²Ρ‹ΠΊΠ»Π°Π΄Ρ‹Π²Π°Π΅Ρ‚ Π² ΠΎΠ±Π»Π°ΠΊΠΎ ΠΎΡ‚Ρ‡Π΅Ρ‚Ρ‹, Π° Ρ„ΠΈΠ½ΠΌΠΎΠ½ΠΈΡ‚ΠΎΡ€ΠΈΠ½Π³ ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅Ρ‚ оповСщСния ΠΎ Π½ΠΎΠ²Ρ‹Ρ… ΠΎΡ‚Ρ‡Π΅Ρ‚Π°Ρ…, провСряСт ΠΈ Π°Π½Π°Π»ΠΈΠ·ΠΈΡ€ΡƒΠ΅Ρ‚ ΠΈΡ…).
  4. Π§ΡƒΡ‚ΡŒ Π±ΠΎΠ»Π΅Π΅ слоТныС кСйсы ΠΏΠΎΠ΄Ρ€Π°Π·ΡƒΠΌΠ΅Π²Π°ΡŽΡ‚, ΠΊ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Ρƒ, Ρ„ΠΎΡ€ΠΌΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ запроса ΠΊ Kubernetes, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ создаСт ΠΏΠΎΠ΄ с Π½ΡƒΠΆΠ½Ρ‹ΠΌΠΈ ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€Π°ΠΌΠΈ, ΠΏΠ΅Ρ€Π΅Π΄Π°Π΅Ρ‚ Π² Π½Π΅Π³ΠΎ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Ρ‹ Π·Π°Π΄Π°Ρ‡ΠΈ ΠΈ послС ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ сворачиваСт ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€.

Π’ качСствС ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π° ΠΌΡ‹ сдСлаСм Π²Π°Ρ€ΠΈΠ°Π½Ρ‚ Π·Π°Π΄Π°Ρ‡ΠΈ 1, ΠΊΠΎΠ³Π΄Π° измСнСния Π² Π±Π°ΠΊΠ΅Ρ‚Π΅ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π½ΠΎΠ³ΠΎ Ρ…Ρ€Π°Π½ΠΈΠ»ΠΈΡ‰Π° Mail.ru Cloud Solutions (MCS) с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Π²Π΅Π±Ρ…ΡƒΠΊΠΎΠ² ΡΠΈΠ½Ρ…Ρ€ΠΎΠ½ΠΈΠ·ΠΈΡ€ΡƒΡŽΡ‚ΡΡ Π² ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π½ΠΎΠΌ Ρ…Ρ€Π°Π½ΠΈΠ»ΠΈΡ‰Π΅ AWS. Π’ Ρ€Π΅Π°Π»ΡŒΠ½ΠΎΠΌ Π½Π°Π³Ρ€ΡƒΠΆΠ΅Π½Π½ΠΎΠΌ кСйсС слСдуСт ΠΏΡ€Π΅Π΄ΡƒΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Π°ΡΠΈΠ½Ρ…Ρ€ΠΎΠ½Π½ΡƒΡŽ Ρ€Π°Π±ΠΎΡ‚Ρƒ Π·Π° счСт рСгистрации Π²Π΅Π±Ρ…ΡƒΠΊΠΎΠ² Π² ΠΎΡ‡Π΅Ρ€Π΅Π΄ΠΈ, Π½ΠΎ для ΡƒΡ‡Π΅Π±Π½ΠΎΠΉ Π·Π°Π΄Π°Ρ‡ΠΈ ΠΌΡ‹ сдСлаСм Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΡŽ Π±Π΅Π· этого.

Π‘Ρ…Π΅ΠΌΠ° Ρ€Π°Π±ΠΎΡ‚Ρ‹

ΠŸΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ» взаимодСйствия Π΄Π΅Ρ‚Π°Π»ΡŒΠ½ΠΎ описан Π² руководствС ΠΏΠΎ S3-Π²Π΅Π±Ρ…ΡƒΠΊΠ°ΠΌ Π½Π° MCS. Π’ схСмС Ρ€Π°Π±ΠΎΡ‚Ρ‹ Π΅ΡΡ‚ΡŒ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠ΅ элСмСнты:

  • БСрвис ΠΏΡƒΠ±Π»ΠΈΠΊΠ°Ρ†ΠΈΠΈ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ находится Π½Π° сторонС S3-Ρ…Ρ€Π°Π½ΠΈΠ»ΠΈΡ‰Π° ΠΈ ΠΏΡƒΠ±Π»ΠΈΠΊΡƒΠ΅Ρ‚ HTTP-запросы ΠΏΡ€ΠΈ срабатывании webnhook.
  • Π‘Π΅Ρ€Π²Π΅Ρ€ ΠΏΡ€ΠΈΠ΅ΠΌΠ° Π²Π΅Π±Ρ…ΡƒΠΊΠΎΠ², ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΡΠ»ΡƒΡˆΠ°Π΅Ρ‚ обращСния сСрвиса ΠΏΡƒΠ±Π»ΠΈΠΊΠ°Ρ†ΠΈΠΈ ΠΏΠΎ HTTP ΠΈ выполняСт ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠ΅ дСйствия. Π‘Π΅Ρ€Π²Π΅Ρ€ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ написан Π½Π° любом языкС, Π² нашСм ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π΅ ΠΌΡ‹ напишСм сСрвСр Π½Π° Go.

ΠžΡΠΎΠ±Π΅Π½Π½ΠΎΡΡ‚ΡŒ Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ Π²Π΅Π±Ρ…ΡƒΠΊΠΎΠ² Π² S3 API β€” рСгистрация сСрвСра ΠΏΡ€ΠΈΠ΅ΠΌΠ° Π²Π΅Π±Ρ…ΡƒΠΊΠΎΠ² Π½Π° сСрвисС ΠΏΡƒΠ±Π»ΠΈΠΊΠ°Ρ†ΠΈΠΈ. Π’ частности, сСрвСр ΠΏΡ€ΠΈΠ΅ΠΌΠ° Π²Π΅Π±Ρ…ΡƒΠΊΠΎΠ² Π΄ΠΎΠ»ΠΆΠ΅Π½ ΠΏΠΎΠ΄Ρ‚Π²Π΅Ρ€Π΄ΠΈΡ‚ΡŒ подписку Π½Π° сообщСния сСрвиса ΠΏΡƒΠ±Π»ΠΈΠΊΠ°Ρ†ΠΈΠΈ (Π² Π΄Ρ€ΡƒΠ³ΠΈΡ… рСализациях Π²Π΅Π±Ρ…ΡƒΠΊΠΎΠ² ΠΎΠ±Ρ‹Ρ‡Π½ΠΎ ΠΏΠΎΠ΄Ρ‚Π²Π΅Ρ€ΠΆΠ΄Π°Ρ‚ΡŒ подписку Π½Π΅ трСбуСтся).

БоотвСтствСнно, сСрвСр ΠΏΡ€ΠΈΠ΅ΠΌΠ° Π²Π΅Π±Ρ…ΡƒΠΊΠΎΠ² Π΄ΠΎΠ»ΠΆΠ΅Π½ ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Ρ‚ΡŒ Π΄Π²Π΅ основных ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ:

  • ΠΎΡ‚Π²Π΅Ρ‡Π°Ρ‚ΡŒ Π½Π° запрос сСрвиса ΠΏΡƒΠ±Π»ΠΈΠΊΠ°Ρ†ΠΈΠΈ ΠΎ ΠΏΠΎΠ΄Ρ‚Π²Π΅Ρ€ΠΆΠ΄Π΅Π½ΠΈΠΈ рСгистрации,
  • ΠΎΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Ρ‚ΡŒ приходящиС события.

Установка сСрвСра ΠΏΡ€ΠΈΠ΅ΠΌΠ° Π²Π΅Π±Ρ…ΡƒΠΊΠΎΠ²

Для запуска сСрвСра ΠΏΡ€ΠΈΠ΅ΠΌΠ° Π²Π΅Π±Ρ…ΡƒΠΊΠΎΠ² Π½ΡƒΠΆΠ΅Π½ Linux-сСрвСр. Π’ Π΄Π°Π½Π½ΠΎΠΉ ΡΡ‚Π°Ρ‚ΡŒΠ΅ для ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π° ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌ Π²ΠΈΡ€Ρ‚ΡƒΠ°Π»ΡŒΠ½Ρ‹ΠΉ инстанс, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ Ρ€Π°Π·Π²Π΅Ρ€Ρ‚Ρ‹Π²Π°Π΅ΠΌ Π½Π° MCS.

Установим Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎΠ΅ ПО ΠΈ запустим сСрвСр ΠΏΡ€ΠΈΠ΅ΠΌΠ° Π²Π΅Π±Ρ…ΡƒΠΊΠΎΠ².

ubuntu@ubuntu-basic-1-2-10gb:~$ sudo apt-get install git
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following packages were automatically installed and are no longer required:
  bc dns-root-data dnsmasq-base ebtables landscape-common liblxc-common 
liblxc1 libuv1 lxcfs lxd lxd-client python3-attr python3-automat 
python3-click python3-constantly python3-hyperlink
  python3-incremental python3-pam python3-pyasn1-modules 
python3-service-identity python3-twisted python3-twisted-bin 
python3-zope.interface uidmap xdelta3
Use 'sudo apt autoremove' to remove them.
Suggested packages:
  git-daemon-run | git-daemon-sysvinit git-doc git-el git-email git-gui 
gitk gitweb git-cvs git-mediawiki git-svn
The following NEW packages will be installed:
  git
0 upgraded, 1 newly installed, 0 to remove and 46 not upgraded.
Need to get 3915 kB of archives.
After this operation, 32.3 MB of additional disk space will be used.
Get:1 http://MS1.clouds.archive.ubuntu.com/ubuntu bionic-updates/main 
amd64 git amd64 1:2.17.1-1ubuntu0.7 [3915 kB]
Fetched 3915 kB in 1s (5639 kB/s)
Selecting previously unselected package git.
(Reading database ... 53932 files and directories currently installed.)
Preparing to unpack .../git_1%3a2.17.1-1ubuntu0.7_amd64.deb ...
Unpacking git (1:2.17.1-1ubuntu0.7) ...
Setting up git (1:2.17.1-1ubuntu0.7) ...

ΠšΠ»ΠΎΠ½ΠΈΡ€ΡƒΠ΅ΠΌ ΠΏΠ°ΠΏΠΊΡƒ с сСрвСром ΠΏΡ€ΠΈΠ΅ΠΌΠ° Π²Π΅Π±Ρ…ΡƒΠΊΠΎΠ²:

ubuntu@ubuntu-basic-1-2-10gb:~$ git clone
https://github.com/RomanenkoDenys/s3-webhook.git
Cloning into 's3-webhook'...
remote: Enumerating objects: 48, done.
remote: Counting objects: 100% (48/48), done.
remote: Compressing objects: 100% (27/27), done.
remote: Total 114 (delta 20), reused 45 (delta 18), pack-reused 66
Receiving objects: 100% (114/114), 23.77 MiB | 20.25 MiB/s, done.
Resolving deltas: 100% (49/49), done.

Запустим сСрвСр:

ubuntu@ubuntu-basic-1-2-10gb:~$ cd s3-webhook/
ubuntu@ubuntu-basic-1-2-10gb:~/s3-webhook$ sudo ./s3-webhook -port 80

Подписка Π½Π° сСрвис ΠΏΡƒΠ±Π»ΠΈΠΊΠ°Ρ†ΠΈΠΈ

Π—Π°Ρ€Π΅Π³ΠΈΡΡ‚Ρ€ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ свой сСрвСр ΠΏΡ€ΠΈΠ΅ΠΌΠ° Π²Π΅Π±Ρ…ΡƒΠΊΠΎΠ² ΠΌΠΎΠΆΠ½ΠΎ Ρ‡Π΅Ρ€Π΅Π· API Π»ΠΈΠ±ΠΎ web-интСрфСйс. Для простоты Π±ΡƒΠ΄Π΅ΠΌ Ρ€Π΅Π³ΠΈΡΡ‚Ρ€ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Ρ‡Π΅Ρ€Π΅Π· web-интСрфСйс:

  1. ИдСм Π² Ρ€Π°Π·Π΄Π΅Π» Π±Π°ΠΊΠ΅Ρ‚ΠΎΠ² Π² ΠΊΠ°Π±ΠΈΠ½Π΅Ρ‚Π΅ управлСния.
  2. Π—Π°Ρ…ΠΎΠ΄ΠΈΠΌ Π² Π±Π°ΠΊΠ΅Ρ‚, для ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ³ΠΎ Π±ΡƒΠ΄Π΅ΠΌ Π½Π°ΡΡ‚Ρ€Π°ΠΈΠ²Π°Ρ‚ΡŒ wΠ΅bhooks, ΠΈ Π½Π°ΠΆΠΈΠΌΠ°Π΅ΠΌ Π½Π° ΡˆΠ΅ΡΡ‚Π΅Ρ€Π΅Π½ΠΊΡƒ:

ΠŸΡ€ΠΈΠΌΠ΅Ρ€ event-driven прилоТСния Π½Π° основС Π²Π΅Π±Ρ…ΡƒΠΊΠΎΠ² Π² ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π½ΠΎΠΌ S3-Ρ…Ρ€Π°Π½ΠΈΠ»ΠΈΡ‰Π΅ Mail.ru Cloud Solutions

ΠŸΠ΅Ρ€Π΅Ρ…ΠΎΠ΄ΠΈΠΌ Π½Π° Π²ΠΊΠ»Π°Π΄ΠΊΡƒ Webhooks ΠΈ Π½Π°ΠΆΠΈΠΌΠ°Π΅ΠΌ Π”ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ:

ΠŸΡ€ΠΈΠΌΠ΅Ρ€ event-driven прилоТСния Π½Π° основС Π²Π΅Π±Ρ…ΡƒΠΊΠΎΠ² Π² ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π½ΠΎΠΌ S3-Ρ…Ρ€Π°Π½ΠΈΠ»ΠΈΡ‰Π΅ Mail.ru Cloud Solutions
ЗаполняСм поля:

ΠŸΡ€ΠΈΠΌΠ΅Ρ€ event-driven прилоТСния Π½Π° основС Π²Π΅Π±Ρ…ΡƒΠΊΠΎΠ² Π² ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π½ΠΎΠΌ S3-Ρ…Ρ€Π°Π½ΠΈΠ»ΠΈΡ‰Π΅ Mail.ru Cloud Solutions

ID β€” Π½Π°Π·Π²Π°Π½ΠΈΠ΅ Π²Π΅Π±Ρ…ΡƒΠΊΠ°.

Event β€” ΠΊΠ°ΠΊΠΈΠ΅ события ΠΏΠ΅Ρ€Π΅Π΄Π°Π²Π°Ρ‚ΡŒ. ΠœΡ‹ Π·Π°Π΄Π°Π»ΠΈ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡Ρƒ всСх событий, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ происходят ΠΏΡ€ΠΈ Ρ€Π°Π±ΠΎΡ‚Π΅ с Ρ„Π°ΠΉΠ»Π°ΠΌΠΈ (Π΄ΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΠ΅ ΠΈ ΡƒΠ΄Π°Π»Π΅Π½ΠΈΠ΅).

URL β€” адрСс сСрвСра ΠΏΡ€ΠΈΠ΅ΠΌΠ° Π²Π΅Π±Ρ…ΡƒΠΊΠΎΠ².

Filter prefix/suffix β€” Ρ„ΠΈΠ»ΡŒΡ‚Ρ€, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ позволяСт Π³Π΅Π½Π΅Ρ€ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Π²Π΅Π±Ρ…ΡƒΠΊΠΈ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π½Π° ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Ρ‹, названия ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‚ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Π½Ρ‹ΠΌ ΠΏΡ€Π°Π²ΠΈΠ»Π°ΠΌ. НапримСр, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π²Π΅Π±Ρ…ΡƒΠΊ срабатывал Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Ρ„Π°ΠΉΠ»Ρ‹ с Ρ€Π°ΡΡˆΠΈΡ€Π΅Π½ΠΈΠ΅ΠΌ .png, Π² Filter suffix Π½Π°Π΄ΠΎ Π½Π°ΠΏΠΈΡΠ°Ρ‚ΡŒ Β«pngΒ».

Π’ Ρ‚Π΅ΠΊΡƒΡ‰ΠΈΠΉ ΠΌΠΎΠΌΠ΅Π½Ρ‚ ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°ΡŽΡ‚ΡΡ для обращСния ΠΊ сСрвСру ΠΏΡ€ΠΈΠ΅ΠΌΠ° Π²Π΅Π±Ρ…ΡƒΠΊΠΎΠ² Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΏΠΎΡ€Ρ‚Ρ‹ 80 ΠΈ 443.

НаТмСм Π”ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ hook ΠΈ ΡƒΠ²ΠΈΠ΄ΠΈΠΌ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅Π΅:

ΠŸΡ€ΠΈΠΌΠ΅Ρ€ event-driven прилоТСния Π½Π° основС Π²Π΅Π±Ρ…ΡƒΠΊΠΎΠ² Π² ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π½ΠΎΠΌ S3-Ρ…Ρ€Π°Π½ΠΈΠ»ΠΈΡ‰Π΅ Mail.ru Cloud Solutions
Hook Π΄ΠΎΠ±Π°Π²Π»Π΅Π½.

Π‘Π΅Ρ€Π²Π΅Ρ€ ΠΏΡ€ΠΈΠ΅ΠΌΠ° Π²Π΅Π±Ρ…ΡƒΠΊΠΎΠ² Π² Π»ΠΎΠ³Π°Ρ… ΠΏΠΎΠΊΠ°Π·Ρ‹Π²Π°Π΅Ρ‚ ΠΏΡ€ΠΎΡ…ΠΎΠΆΠ΄Π΅Π½ΠΈΠ΅ процСсса рСгистрации Ρ…ΡƒΠΊΠ°:

ubuntu@ubuntu-basic-1-2-10gb:~/s3-webhook$ sudo ./s3-webhook -port 80
2020/06/15 12:01:14 [POST] incoming HTTP request from 
95.163.216.92:42530
2020/06/15 12:01:14 Got timestamp: 2020-06-15T15:01:13+03:00 TopicArn: 
mcs5259999770|myfiles-ash|s3:ObjectCreated:*,s3:ObjectRemoved:* Token: 
E2itMqAMUVVZc51pUhFWSp13DoxezvRxkUh5P7LEuk1dEe9y URL: 
http://89.208.199.220/webhook
2020/06/15 12:01:14 Generate responce signature: 
3754ce36636f80dfd606c5254d64ecb2fd8d555c27962b70b4f759f32c76b66d

РСгистрация Π·Π°ΠΊΠΎΠ½Ρ‡Π΅Π½Π°. Π’ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅ΠΌ Ρ€Π°Π·Π΄Π΅Π»Π΅ Π±ΠΎΠ»Π΅Π΅ Π΄Π΅Ρ‚Π°Π»ΡŒΠ½ΠΎ рассмотрим Π°Π»Π³ΠΎΡ€ΠΈΡ‚ΠΌ Ρ€Π°Π±ΠΎΡ‚Ρ‹ сСрвСра ΠΏΡ€ΠΈΠ΅ΠΌΠ° Π²Π΅Π±Ρ…ΡƒΠΊΠΎΠ².

ОписаниС сСрвСра ΠΏΡ€ΠΈΠ΅ΠΌΠ° Π²Π΅Π±Ρ…ΡƒΠΊΠΎΠ²

Π’ нашСм ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π΅ сСрвСр написан Π½Π° Go. Π Π°Π·Π±Π΅Ρ€Π΅ΠΌ основныС ΠΏΡ€ΠΈΠ½Ρ†ΠΈΠΏΡ‹ Π΅Π³ΠΎ Ρ€Π°Π±ΠΎΡ‚Ρ‹.

package main

// Generate hmac_sha256_hex
func HmacSha256hex(message string, secret string) string {
}

// Generate hmac_sha256
func HmacSha256(message string, secret string) string {
}

// Send subscription confirmation
func SubscriptionConfirmation(w http.ResponseWriter, req *http.Request, body []byte) {
}

// Send subscription confirmation
func GotRecords(w http.ResponseWriter, req *http.Request, body []byte) {
}

// Liveness probe
func Ping(w http.ResponseWriter, req *http.Request) {
    // log request
    log.Printf("[%s] incoming HTTP Ping request from %sn", req.Method, req.RemoteAddr)
    fmt.Fprintf(w, "Pongn")
}

//Webhook
func Webhook(w http.ResponseWriter, req *http.Request) {
}

func main() {

    // get command line args
    bindPort := flag.Int("port", 80, "number between 1-65535")
    bindAddr := flag.String("address", "", "ip address in dot format")
    flag.StringVar(&actionScript, "script", "", "external script to execute")
    flag.Parse()

    http.HandleFunc("/ping", Ping)
    http.HandleFunc("/webhook", Webhook)

log.Fatal(http.ListenAndServe(*bindAddr+":"+strconv.Itoa(*bindPort), nil))
}

Рассмотрим основныС Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ:

  • Ping() β€” Ρ€ΠΎΡƒΡ‚, ΠΎΡ‚Π²Π΅Ρ‡Π°ΡŽΡ‰ΠΈΠΉ ΠΏΠΎ URL/ping, ΠΏΡ€ΠΎΡΡ‚Π΅ΠΉΡˆΠ°Ρ рСализация liveness probe.
  • Webhook() β€” основной Ρ€ΠΎΡƒΡ‚, ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ URL/Π²Π΅Π±Ρ…ΡƒΠΊΠ°:
    • ΠΏΠΎΠ΄Ρ‚Π²Π΅Ρ€ΠΆΠ΄Π°Π΅Ρ‚ Ρ€Π΅Π³ΠΈΡΡ‚Ρ€Π°Ρ†ΠΈΡŽ Π½Π° сСрвисС ΠΏΡƒΠ±Π»ΠΈΠΊΠ°Ρ†ΠΈΠΈ (ΠΏΠ΅Ρ€Π΅Ρ…ΠΎΠ΄ Π² Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ SubscriptionConfirmation),
    • ΠΎΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Π΅Ρ‚ приходящиС Π²Π΅Π±Ρ…ΡƒΠΊΠΈ (функция Gotrecords).
  • Π€ΡƒΠ½ΠΊΡ†ΠΈΠΈ HmacSha256 ΠΈ HmacSha256hex β€” Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ Π°Π»Π³ΠΎΡ€ΠΈΡ‚ΠΌΠΎΠ² ΡˆΠΈΡ„Ρ€ΠΎΠ²Π°Π½ΠΈΡ HMAC-SHA256 ΠΈ HMAC-SHA256 с Π²Ρ‹Π²ΠΎΠ΄ΠΎΠΌ Π² Π²ΠΈΠ΄Π΅ строки 16-Ρ€ΠΈΡ‡Π½Ρ‹Ρ… чисСл для подстчСта сигнатуры.
  • main β€” главная функция, ΠΎΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Π΅Ρ‚ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Ρ‹ ΠΊΠΎΠΌΠ°Π½Π΄Π½ΠΎΠΉ строки ΠΈ рСгистрируСт ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ URL.

ΠŸΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Ρ‹ ΠΊΠΎΠΌΠ°Π½Π΄Π½ΠΎΠΉ строки, ΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°Π΅ΠΌΡ‹Π΅ сСрвСром:

  • -port β€” ΠΏΠΎΡ€Ρ‚, Π½Π° ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌ сСрвСр Π±ΡƒΠ΄Π΅Ρ‚ ΡΠ»ΡƒΡˆΠ°Ρ‚ΡŒ.
  • -address β€” IP-адрСс, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ Π±ΡƒΠ΄Π΅Ρ‚ ΡΠ»ΡƒΡˆΠ°Ρ‚ΡŒ сСрвСр.
  • -script β€” внСшняя ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ°, которая вызываСтся Π½Π° ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ ΠΏΡ€ΠΈΡˆΠ΅Π΄ΡˆΠΈΠΉ Ρ…ΡƒΠΊ.

Рассмотрим ΠΏΠΎΠ΄Ρ€ΠΎΠ±Π½Π΅Π΅ Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ:

//Webhook
func Webhook(w http.ResponseWriter, req *http.Request) {

    // Read body
    body, err := ioutil.ReadAll(req.Body)
    defer req.Body.Close()
    if err != nil {
        http.Error(w, err.Error(), 500)
        return
    }

    // log request
    log.Printf("[%s] incoming HTTP request from %sn", req.Method, req.RemoteAddr)
    // check if we got subscription confirmation request
    if strings.Contains(string(body), 
""Type":"SubscriptionConfirmation"") {
        SubscriptionConfirmation(w, req, body)
    } else {
        GotRecords(w, req, body)
    }

}

Π­Ρ‚Π° функция опрСдСляСт, Ρ‡Ρ‚ΠΎ ΠΏΡ€ΠΈΡˆΠ»ΠΎ β€” запрос Π½Π° ΠΏΠΎΠ΄Ρ‚Π²Π΅Ρ€ΠΆΠ΄Π΅Π½ΠΈΠ΅ рСгистрации Π»ΠΈΠ±ΠΎ Π²Π΅Π±Ρ…ΡƒΠΊ. Как слСдуСт ΠΈΠ· Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°Ρ†ΠΈΠΈ, Π² случаС подтвСрТдСния рСгистрации ΠΏΡ€ΠΈΡ…ΠΎΠ΄ΠΈΡ‚ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π°Ρ структура Json Π² запросС Post:

POST http://test.com HTTP/1.1
x-amz-sns-messages-type: SubscriptionConfirmation
content-type: application/json

{
    "Timestamp":"2019-12-26T19:29:12+03:00",
    "Type":"SubscriptionConfirmation",
    "Message":"You have chosen to subscribe to the topic $topic. To confirm the subscription you need to response with calculated signature",
    "TopicArn":"mcs2883541269|bucketA|s3:ObjectCreated:Put",
    "SignatureVersion":1,
    "Token":Β«RPE5UuG94rGgBH6kHXN9FUPugFxj1hs2aUQc99btJp3E49tAΒ»
}

На этот запрос Π½ΡƒΠΆΠ½ΠΎ ΠΎΡ‚Π²Π΅Ρ‚ΠΈΡ‚ΡŒ:

content-type: application/json

{"signature":Β«ea3fce4bb15c6de4fec365d36bcebbc34ccddf54616d5ca12e1972f82b6d37afΒ»}

Π“Π΄Π΅ сигнатура вычисляСтся ΠΊΠ°ΠΊ:

signature = hmac_sha256(url, hmac_sha256(TopicArn, 
hmac_sha256(Timestamp, Token)))

Если ΠΆΠ΅ ΠΏΡ€ΠΈΡ…ΠΎΠ΄ΠΈΡ‚ Π²Π΅Π±Ρ…ΡƒΠΊ, Ρ‚ΠΎ структура Post-запроса выглядит Ρ‚Π°ΠΊ:

POST <url> HTTP/1.1
x-amz-sns-messages-type: SubscriptionConfirmation

{ "Records":
    [
        {
            "s3": {
                "object": {
                    "eTag":"aed563ecafb4bcc5654c597a421547b2",
                    "sequencer":1577453615,
                    "key":"some-file-to-bucket",
                    "size":100
                },
            "configurationId":"1",
            "bucket": {
                "name": "bucketA",
                "ownerIdentity": {
                    "principalId":"mcs2883541269"}
                },
                "s3SchemaVersion":"1.0"
            },
            "eventVersion":"1.0",
            "requestParameters":{
                "sourceIPAddress":"185.6.245.156"
            },
            "userIdentity": {
                "principalId":"2407013e-cbc1-415f-9102-16fb9bd6946b"
            },
            "eventName":"s3:ObjectCreated:Put",
            "awsRegion":"ru-msk",
            "eventSource":"aws:s3",
            "responseElements": {
                "x-amz-request-id":"VGJR5rtJ"
            }
        }
    ]
}

БоотвСтствСнно, Π² зависимости ΠΎΡ‚ запроса Π½ΡƒΠΆΠ½ΠΎ ΠΏΠΎΠ½ΡΡ‚ΡŒ, ΠΊΠ°ΠΊ ΠΎΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Ρ‚ΡŒ Π΄Π°Π½Π½Ρ‹Π΅. Π― Π²Ρ‹Π±Ρ€Π°Π» Π² качСствС ΠΈΠ½Π΄ΠΈΠΊΠ°Ρ‚ΠΎΡ€Π° запись "Type":"SubscriptionConfirmation", ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΎΠ½Π° присутствуСт Π² запросС Π½Π° ΠΏΠΎΠ΄Ρ‚Π²Π΅Ρ€ΠΆΠ΄Π΅Π½ΠΈΠ΅ подписки ΠΈ Π½Π΅ присутствуСт Π² Π²Π΅Π±Ρ…ΡƒΠΊΠ΅. Π˜ΡΡ…ΠΎΠ΄Ρ ΠΈΠ· наличия/отсутствия этой записи Π² POST-запросС, дальнСйшСС Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹ ΠΏΠ΅Ρ€Π΅Ρ…ΠΎΠ΄ΠΈΡ‚ Π»ΠΈΠ±ΠΎ Π² Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ SubscriptionConfirmation, Π»ΠΈΠ±ΠΎ Π² Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ GotRecords.

Π€ΡƒΠ½ΠΊΡ†ΠΈΡŽ SubscriptionConfirmation Π΄Π΅Ρ‚Π°Π»ΡŒΠ½ΠΎ Ρ€Π°ΡΡΠΌΠ°Ρ‚Ρ€ΠΈΠ²Π°Ρ‚ΡŒ Π½Π΅ Π±ΡƒΠ΄Π΅ΠΌ, ΠΎΠ½Π° Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Π½Π° ΠΏΠΎ ΠΏΡ€ΠΈΠ½Ρ†ΠΈΠΏΠ°ΠΌ, ΠΈΠ·Π»ΠΎΠΆΠ΅Π½Π½Ρ‹ΠΌ Π² Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°Ρ†ΠΈΠΈ. Π˜Π·ΡƒΡ‡ΠΈΡ‚ΡŒ исходный ΠΊΠΎΠ΄ этой Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ ΠΌΠΎΠΆΠ½ΠΎ Π² git-Ρ€Π΅ΠΏΠΎΠ·ΠΈΡ‚ΠΎΡ€ΠΈΠΈ ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π°.

Ѐункция GotRecords Ρ€Π°Π·Π±ΠΈΡ€Π°Π΅Ρ‚ приходящий запрос ΠΈ для ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π° Record Π²Ρ‹Π·Ρ‹Π²Π°Π΅Ρ‚ внСшний скрипт (имя ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ³ΠΎ Π±Ρ‹Π»ΠΎ ΠΏΠ΅Ρ€Π΅Π΄Π°Π½ΠΎ Π² ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Π΅ -script) с ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Π°ΠΌΠΈ:

  • имя Π±Π°ΠΊΠ΅Ρ‚Π°
  • ΠΊΠ»ΡŽΡ‡ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°
  • дСйствиС:
    • copy β€” Ссли Π² исходном запросС EventName = ObjectCreated | PutObject | PutObjectCopy
    • delete β€” Ссли Π² исходном запросС EventName = ObjectRemoved | DeleteObject

Π’Π°ΠΊΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ, Ссли ΠΏΡ€ΠΈΠ»Π΅Ρ‚Π΅Π» Ρ…ΡƒΠΊ c Post-запросом, ΠΊΠ°ΠΊ описано Π²Ρ‹ΡˆΠ΅, ΠΈ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ -script=script.sh Ρ‚ΠΎ скрипт Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹Π·Π²Π°Π½ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ:

script.sh  bucketA some-file-to-bucket copy

Π‘Π»Π΅Π΄ΡƒΠ΅Ρ‚ ΠΏΠΎΠ½ΠΈΠΌΠ°Ρ‚ΡŒ, Ρ‡Ρ‚ΠΎ Π΄Π°Π½Π½Ρ‹ΠΉ сСрвСр ΠΏΡ€ΠΈΠ΅ΠΌΠ° Π²Π΅Π±Ρ…ΡƒΠΊΠΎΠ² β€” это Π½Π΅ Π·Π°ΠΊΠΎΠ½Ρ‡Π΅Π½Π½ΠΎΠ΅ production-Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅, Π° ΡƒΠΏΡ€ΠΎΡ‰Π΅Π½Π½Ρ‹ΠΉ ΠΏΡ€ΠΈΠΌΠ΅Ρ€ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΠΉ Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ.

ΠŸΡ€ΠΈΠΌΠ΅Ρ€ Ρ€Π°Π±ΠΎΡ‚Ρ‹

Π‘Π΄Π΅Π»Π°Π΅ΠΌ ΡΠΈΠ½Ρ…Ρ€ΠΎΠ½ΠΈΠ·Π°Ρ†ΠΈΡŽ Ρ„Π°ΠΉΠ»ΠΎΠ² основного Π±Π°ΠΊΠ΅Ρ‚Π° Π² MCS Π² Ρ€Π΅Π·Π΅Ρ€Π²Π½Ρ‹ΠΉ Π±Π°ΠΊΠ΅Ρ‚ Π² AWS. Основной Π±Π°ΠΊΠ΅Ρ‚ называСтся myfiles-ash, Ρ€Π΅Π·Π΅Ρ€Π²Π½Ρ‹ΠΉ β€” myfiles-backup (конфигурация Π±Π°ΠΊΠ΅Ρ‚Π° Π² AWS Π²Ρ‹Ρ…ΠΎΠ΄ΠΈΡ‚ Π·Π° ΠΏΡ€Π΅Π΄Π΅Π»Ρ‹ Π΄Π°Π½Π½ΠΎΠΉ ΡΡ‚Π°Ρ‚ΡŒΠΈ). БоотвСтствСнно, ΠΊΠΎΠ³Π΄Π° Ρ„Π°ΠΉΠ» кладСтся Π² основной Π±Π°ΠΊΠ΅Ρ‚, Π΅Π³ΠΎ копия Π΄ΠΎΠ»ΠΆΠ½Π° ΠΏΠΎΡΠ²ΠΈΡ‚ΡŒΡΡ Π² Ρ€Π΅Π·Π΅Ρ€Π²Π½ΠΎΠΌ, ΠΊΠΎΠ³Π΄Π° удаляСтся ΠΈΠ· основного β€” ΡƒΠ΄Π°Π»ΡΡ‚ΡŒΡΡ Π² Ρ€Π΅Π·Π΅Ρ€Π²Π½ΠΎΠΌ.

Π Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ с Π±Π°ΠΊΠ΅Ρ‚Π°ΠΌΠΈ Π±ΡƒΠ΄Π΅ΠΌ ΡƒΡ‚ΠΈΠ»ΠΈΡ‚ΠΎΠΉ awscli, с ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΉ совмСстимо ΠΊΠ°ΠΊ ΠΎΠ±Π»Π°Ρ‡Π½ΠΎΠ΅ Ρ…Ρ€Π°Π½ΠΈΠ»ΠΈΡ‰Π΅ MCS, Ρ‚Π°ΠΊ ΠΈ ΠΎΠ±Π»Π°Ρ‡Π½ΠΎΠ΅ Ρ…Ρ€Π°Π½ΠΈΠ»ΠΈΡ‰Π΅ AWS.

ubuntu@ubuntu-basic-1-2-10gb:~$ sudo apt-get install awscli
Reading package lists... Done
Building dependency tree
Reading state information... Done
After this operation, 34.4 MB of additional disk space will be used.
Unpacking awscli (1.14.44-1ubuntu1) ...
Setting up awscli (1.14.44-1ubuntu1) ...

Π‘ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€ΠΈΡ€ΡƒΠ΅ΠΌ доступ ΠΊ API S3 MCS:

ubuntu@ubuntu-basic-1-2-10gb:~$ aws configure --profile mcs
AWS Access Key ID [None]: hdywEPtuuJTExxxxxxxxxxxxxx
AWS Secret Access Key [None]: hDz3SgxKwXoxxxxxxxxxxxxxxxxxx
Default region name [None]:
Default output format [None]:

Π‘ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€ΠΈΡ€ΡƒΠ΅ΠΌ доступ ΠΊ API S3 AWS:

ubuntu@ubuntu-basic-1-2-10gb:~$ aws configure --profile aws
AWS Access Key ID [None]: AKIAJXXXXXXXXXXXX
AWS Secret Access Key [None]: dfuerphOLQwu0CreP5Z8l5fuXXXXXXXXXXXXXXXX
Default region name [None]:
Default output format [None]:

ΠŸΡ€ΠΎΠ²Π΅Ρ€ΠΈΠΌ доступы:

К AWS:

ubuntu@ubuntu-basic-1-2-10gb:~$ aws s3 ls --profile aws
2020-07-06 08:44:11 myfiles-backup

Для MCS, ΠΏΡ€ΠΈ Ρ€Π°Π±ΠΎΡ‚Π΅ ΠΊΠΎΠΌΠ°Π½Π΄Ρ‹ Π½Π°Π΄ΠΎ Π΄ΠΎΠ±Π°Π²Π»ΡΡ‚ΡŒ —endpoint-url:

ubuntu@ubuntu-basic-1-2-10gb:~$ aws s3 ls --profile mcs --endpoint-url 
https://hb.bizmrg.com
2020-02-04 06:38:05 databasebackups-0cdaaa6402d4424e9676c75a720afa85
2020-05-27 10:08:33 myfiles-ash

Доступ ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½.

Π’Π΅ΠΏΠ΅Ρ€ΡŒ напишСм скрипт ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ приходящСго Ρ…ΡƒΠΊΠ°, Π½Π°Π·ΠΎΠ²Π΅ΠΌ Π΅Π³ΠΎ s3_backup_mcs_aws.sh

#!/bin/bash
# Require aws cli
# if file added β€” copy it to backup bucket
# if file removed β€” remove it from backup bucket
# Variables
ENDPOINT_MCS="https://hb.bizmrg.com"
AWSCLI_MCS=`which aws`" --endpoint-url ${ENDPOINT_MCS} --profile mcs s3"
AWSCLI_AWS=`which aws`" --profile aws s3"
BACKUP_BUCKET="myfiles-backup"

SOURCE_BUCKET=""
SOURCE_FILE=""
ACTION=""

SOURCE="s3://${SOURCE_BUCKET}/${SOURCE_FILE}"
TARGET="s3://${BACKUP_BUCKET}/${SOURCE_FILE}"
TEMP="/tmp/${SOURCE_BUCKET}/${SOURCE_FILE}"

case ${ACTION} in
    "copy")
    ${AWSCLI_MCS} cp "${SOURCE}" "${TEMP}"
    ${AWSCLI_AWS} cp "${TEMP}" "${TARGET}"
    rm ${TEMP}
    ;;

    "delete")
    ${AWSCLI_AWS} rm ${TARGET}
    ;;

    *)
    echo "Usage: 
#!/bin/bash
# Require aws cli
# if file added β€” copy it to backup bucket
# if file removed β€” remove it from backup bucket
# Variables
ENDPOINT_MCS="https://hb.bizmrg.com"
AWSCLI_MCS=`which aws`" --endpoint-url ${ENDPOINT_MCS} --profile mcs s3"
AWSCLI_AWS=`which aws`" --profile aws s3"
BACKUP_BUCKET="myfiles-backup"
SOURCE_BUCKET="${1}"
SOURCE_FILE="${2}"
ACTION="${3}"
SOURCE="s3://${SOURCE_BUCKET}/${SOURCE_FILE}"
TARGET="s3://${BACKUP_BUCKET}/${SOURCE_FILE}"
TEMP="/tmp/${SOURCE_BUCKET}/${SOURCE_FILE}"
case ${ACTION} in
"copy")
${AWSCLI_MCS} cp "${SOURCE}" "${TEMP}"
${AWSCLI_AWS} cp "${TEMP}" "${TARGET}"
rm ${TEMP}
;;
"delete")
${AWSCLI_AWS} rm ${TARGET}
;;
*)
echo "Usage: ${0} sourcebucket sourcefile copy/delete"
exit 1
;;
esac
sourcebucket sourcefile copy/delete" exit 1 ;; esac

ЗапускаСм сСрвСр:

ubuntu@ubuntu-basic-1-2-10gb:~/s3-webhook$ sudo ./s3-webhook -port 80 -
script scripts/s3_backup_mcs_aws.sh

ΠŸΡ€ΠΎΠ²Π΅Ρ€ΡΠ΅ΠΌ, ΠΊΠ°ΠΊ это сработаСт. Π§Π΅Ρ€Π΅Π· Π²Π΅Π±-интСрфСйс MCS Π΄ΠΎΠ±Π°Π²ΠΈΠΌ Ρ„Π°ΠΉΠ» test.txt Π² Π±Π°ΠΊΠ΅Ρ‚ myfiles-ash. Π’ Π»ΠΎΠ³Π°Ρ… Π² консоли Π²ΠΈΠ΄Π½ΠΎ, Ρ‡Ρ‚ΠΎ Π±Ρ‹Π» сдСлан запрос Π½Π° сСрвСр Π²Π΅Π±Ρ…ΡƒΠΊΠΎΠ²:

2020/07/06 09:43:08 [POST] incoming HTTP request from 
95.163.216.92:56612
download: s3://myfiles-ash/test.txt to ../../../tmp/myfiles-ash/test.txt
upload: ../../../tmp/myfiles-ash/test.txt to 
s3://myfiles-backup/test.txt

ΠŸΡ€ΠΎΠ²Π΅Ρ€ΠΈΠΌ содСрТимоС Π±Π°ΠΊΠ΅Ρ‚Π° myfiles-backup Π² AWS:

ubuntu@ubuntu-basic-1-2-10gb:~/s3-webhook$ aws s3 --profile aws ls 
myfiles-backup
2020-07-06 09:43:10       1104 test.txt

Π’Π΅ΠΏΠ΅Ρ€ΡŒ Ρ‡Π΅Ρ€Π΅Π· Π²Π΅Π±-интСрфСйс ΡƒΠ΄Π°Π»ΠΈΠΌ Ρ„Π°ΠΉΠ» ΠΈΠ· Π±Π°ΠΊΠ΅Ρ‚Π° myfiles-ash.

Π›ΠΎΠ³ΠΈ сСрвСра:

2020/07/06 09:44:46 [POST] incoming HTTP request from 
95.163.216.92:58224
delete: s3://myfiles-backup/test.txt

Π‘ΠΎΠ΄Π΅Ρ€ΠΆΠΈΠΌΠΎΠ΅ Π±Π°ΠΊΠ΅Ρ‚Π°:

ubuntu@ubuntu-basic-1-2-10gb:~/s3-webhook$ aws s3 --profile aws ls 
myfiles-backup
ubuntu@ubuntu-basic-1-2-10gb:~$

Π€Π°ΠΉΠ» ΡƒΠ΄Π°Π»Π΅Π½, Π·Π°Π΄Π°Ρ‡Π° Ρ€Π΅ΡˆΠ΅Π½Π°.

Π—Π°ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ ΠΈ ToDo

Π’Π΅ΡΡŒ ΠΊΠΎΠ΄, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌΡ‹ΠΉ Π² этой ΡΡ‚Π°Ρ‚ΡŒΠ΅, Π»Π΅ΠΆΠΈΡ‚ Π² ΠΌΠΎΠ΅ΠΌ Ρ€Π΅ΠΏΠΎΠ·ΠΈΡ‚ΠΎΡ€ΠΈΠΈ. Π’Π°ΠΌ ΠΆΠ΅ Π»Π΅ΠΆΠ°Ρ‚ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Ρ‹ скриптов ΠΈ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Ρ‹ подсчСта сигнатур для рСгистрации Π²Π΅Π±Ρ…ΡƒΠΊΠΎΠ².

Π”Π°Π½Π½Ρ‹ΠΉ ΠΊΠΎΠ΄ β€” Π½Π΅ Π±ΠΎΠ»Π΅Π΅ Ρ‡Π΅ΠΌ ΠΏΡ€ΠΈΠΌΠ΅Ρ€ Ρ‚ΠΎΠ³ΠΎ, ΠΊΠ°ΠΊ ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ S3-Π²Π΅Π±Ρ…ΡƒΠΊΠΈ Π² своСй Π΄Π΅ΡΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΠΈ. Как я сказал Π² Π½Π°Ρ‡Π°Π»Π΅, Ссли ΠΏΠ»Π°Π½ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ использованиС Ρ‚Π°ΠΊΠΎΠ³ΠΎ сСрвСра Π² ΠΏΡ€ΠΎΠ΄ΡƒΠΊΡ‚ΠΈΠ²Π΅, Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ ΠΊΠ°ΠΊ ΠΌΠΈΠ½ΠΈΠΌΡƒΠΌ ΠΏΠ΅Ρ€Π΅ΠΏΠΈΡΡ‹Π²Π°Ρ‚ΡŒ сСрвСр ΠΏΠΎΠ΄ Π°ΡΠΈΠ½Ρ…Ρ€ΠΎΠ½Π½ΡƒΡŽ Ρ€Π°Π±ΠΎΡ‚Ρƒ: приходящиС Π²Π΅Π±Ρ…ΡƒΠΊΠΈ Ρ€Π΅Π³ΠΈΡΡ‚Ρ€ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Π² ΠΎΡ‡Π΅Ρ€Π΅Π΄ΠΈ (RabbitMQ ΠΈΠ»ΠΈ NATS), Π° ΠΎΡ‚Ρ‚ΡƒΠ΄Π° ΠΈΡ… Ρ€Π°Π·Π±ΠΈΡ€Π°Ρ‚ΡŒ ΠΈ ΠΎΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Ρ‚ΡŒ worker-прилоТСниями. Π˜Π½Π°Ρ‡Π΅ ΠΏΡ€ΠΈ массированном ΠΏΡ€ΠΈΡ…ΠΎΠ΄Π΅ Π²Π΅Π±Ρ…ΡƒΠΊΠΎΠ² ΠΌΠΎΠΆΠ½ΠΎ ΡΡ‚ΠΎΠ»ΠΊΠ½ΡƒΡ‚ΡŒΡΡ с Π½Π΅Ρ…Π²Π°Ρ‚ΠΊΠΎΠΉ рСсурсов сСрвСра для выполнСния Π·Π°Π΄Π°Ρ‡. НаличиС ΠΆΠ΅ ΠΎΡ‡Π΅Ρ€Π΅Π΄Π΅ΠΉ позволяСт Ρ€Π°Π·Π½ΠΎΡΠΈΡ‚ΡŒ сСрвСр ΠΈ workers, Π° Ρ‚Π°ΠΊΠΆΠ΅ Ρ€Π΅ΡˆΠ°Ρ‚ΡŒ вопросы с ΠΏΠΎΠ²Ρ‚ΠΎΡ€ΠΎΠΌ Π·Π°Π΄Π°Ρ‡ Π² случаС сбоСв. Π’Π°ΠΊ ΠΆΠ΅ ΠΆΠ΅Π»Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎ ΠΌΠ΅Π½ΡΡ‚ΡŒ Π»ΠΎΠ³ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ Π½Π° Π±ΠΎΠ»Π΅Π΅ ΠΏΠΎΠ΄Ρ€ΠΎΠ±Π½ΠΎΠ΅ ΠΈ Π±ΠΎΠ»Π΅Π΅ стандартизованноС.

УспСхов!

Π•Ρ‰Π΅ ΠΏΠΎΡ‡ΠΈΡ‚Π°Ρ‚ΡŒ ΠΏΠΎ Ρ‚Π΅ΠΌΠ΅:

Π˜ΡΡ‚ΠΎΡ‡Π½ΠΈΠΊ: habr.com