استقرار و اجرای مهاجرتها
در این مرحله droplet ما با تمام نرمافزارها و حسابهای کاربری مورد نیاز تنظیم شده است، پس بیایید به استقرار و اجرای برنامه API خود بپردازیم.
در سطح بسیار بالا، فرآیند استقرار ما از سه عمل تشکیل شده است:
- کپی کردن فایل باینری برنامه و فایلهای مهاجرت SQL به droplet.
- اجرای مهاجرتها روی دیتابیس PostgreSQL در droplet.
- شروع اجرای فایل باینری برنامه به عنوان یک background service.
فعلاً فقط روی مراحل ۱ و ۲ تمرکز میکنیم و اجرای برنامه به عنوان یک background service را در فصل بعدی بررسی خواهیم کرد.
بیایید با ایجاد یک rule جدید make production/deploy/api در makefile خود شروع کنیم، که از آن برای اجرای خودکار این دو مرحله استفاده خواهیم کرد. به این صورت:
... # ==================================================================================== # # PRODUCTION # ==================================================================================== # production_host_ip = "161.35.71.158" ## production/connect: connect to the production server .PHONY: production/connect production/connect: ssh greenlight@${production_host_ip} ## production/deploy/api: deploy the api to production .PHONY: production/deploy/api production/deploy/api: rsync -P ./bin/linux_amd64/api greenlight@${production_host_ip}:~ rsync -rP --delete ./migrations greenlight@${production_host_ip}:~ ssh -t greenlight@${production_host_ip} 'migrate -path ~/migrations -database $$GREENLIGHT_DB_DSN up'
بیایید به سرعت بررسی کنیم این rule جدید چه کاری انجام میدهد.
اول، دستور rsync را اجرا میکند تا فایل باینری اجرایی ./bin/linux_amd64/api (نسخهای که به طور خاص برای Linux کامپایل شده) و پوشه ./migrations را به دایرکتوری خانه کاربر greenlight در droplet کپی کند.
سپس از دستور ssh با پرچم -t استفاده میکند تا این مهاجرتهای دیتابیس را در droplet به عنوان کاربر greenlight با دستور زیر اجرا کند:
'migrate -path ~/migrations -database $$GREENLIGHT_DB_DSN up'
از آنجا که کاراکتر $ در makefileها معنای خاصی دارد، ما آن را با اضافه کردن یک کاراکتر دالار اضافی مانند $$ escape میکنیم. این یعنی دستوری که واقعاً در droplet اجرا میشود 'migrate -path ~/migrations -database $GREENLIGHT_DB_DSN up' خواهد بود و در نتیجه مهاجرت با استفاده از متغیر محیطی droplet GREENLIGHT_DB_DSN اجرا میشود.
همچنین مهم است که توجه کنید ما این دستور را با کوتیشن تکی احاطه کردهایم. اگر از کوتیشن دوگانه استفاده میکردیم، یک interpreted string میبود و نیاز به استفاده از یک کاراکتر escape اضافی \ داشتیم به این صورت:
"migrate -path ~/migrations -database \$$GREENLIGHT_DB_DSN up"
خوب، بیایید آن را امتحان کنیم!
دستور make production/deploy/api را که تازه ایجاد کردیم اجرا کنید. باید ببینید که تمام فایلها با موفقیت کپی میشوند (این کار بسته به سرعت اتصال شما ممکن است یک یا دو دقیقه طول بکشد) و سپس مهاجرتها روی دیتابیس شما اعمال میشوند. به این صورت:
$ make production/deploy/api
rsync -rP --delete ./bin/linux_amd64/api greenlight@"161.35.71.158":~
api
7,618,560 100% 119.34kB/s 0:01:02 (xfr#1, to-chk=13/14)
rsync -rP --delete ./migrations greenlight@"161.35.71.158":~
sending incremental file list
migrations/
migrations/000001_create_movies_table.down.sql
28 100% 27.34kB/s 0:00:00 (xfr#2, to-chk=11/14)
migrations/000001_create_movies_table.up.sql
286 100% 279.30kB/s 0:00:00 (xfr#3, to-chk=10/14)
migrations/000002_add_movies_check_constraints.down.sql
198 100% 193.36kB/s 0:00:00 (xfr#4, to-chk=9/14)
migrations/000002_add_movies_check_constraints.up.sql
289 100% 282.23kB/s 0:00:00 (xfr#5, to-chk=8/14)
migrations/000003_add_movies_indexes.down.sql
78 100% 76.17kB/s 0:00:00 (xfr#6, to-chk=7/14)
migrations/000003_add_movies_indexes.up.sql
170 100% 166.02kB/s 0:00:00 (xfr#7, to-chk=6/14)
migrations/000004_create_users_table.down.sql
27 100% 26.37kB/s 0:00:00 (xfr#8, to-chk=5/14)
migrations/000004_create_users_table.up.sql
294 100% 287.11kB/s 0:00:00 (xfr#9, to-chk=4/14)
migrations/000005_create_tokens_table.down.sql
28 100% 27.34kB/s 0:00:00 (xfr#10, to-chk=3/14)
migrations/000005_create_tokens_table.up.sql
203 100% 99.12kB/s 0:00:00 (xfr#11, to-chk=2/14)
migrations/000006_add_permissions.down.sql
73 100% 35.64kB/s 0:00:00 (xfr#12, to-chk=1/14)
migrations/000006_add_permissions.up.sql
452 100% 220.70kB/s 0:00:00 (xfr#13, to-chk=0/14)
ssh -t greenlight@"161.35.71.158" 'migrate -path ~/migrations -database $GREENLIGHT_DB_DSN up'
1/u create_movies_table (11.782733ms)
2/u add_movies_check_constraints (23.109006ms)
3/u add_movies_indexes (30.61223ms)
4/u create_users_table (39.890662ms)
5/u create_tokens_table (48.659641ms)
6/u add_permissions (58.23243ms)
Connection to 161.35.71.158 closed.
بیایید به سرعت به droplet خود وصل شویم و مطمئن شویم که همه چیز به درستی کار کرده است.
$ make production/connect ssh greenlight@'161.35.71.158' Welcome to Ubuntu 20.04.2 LTS (GNU/Linux 5.4.0-65-generic x86_64) ... greenlight@greenlight-production:~$ ls -R .: api migrations ./migrations: 000001_create_movies_table.down.sql 000001_create_movies_table.up.sql 000002_add_movies_check_constraints.down.sql 000002_add_movies_check_constraints.up.sql 000003_add_movies_indexes.down.sql 000003_add_movies_indexes.up.sql 000004_create_users_table.down.sql 000004_create_users_table.up.sql 000005_create_tokens_table.down.sql 000005_create_tokens_table.up.sql 000006_add_permissions.down.sql 000006_add_permissions.up.sql
تا اینجا همه چیز خوب پیش رفته است. میتوانیم ببینیم که دایرکتوری خانه کاربر greenlight ما شامل فایل باینری اجرایی api و یک پوشه حاوی فایلهای مهاجرت است.
بیایید همچنین با استفاده از psql به دیتابیس وصل شویم و با استفاده از meta command \dt بررسی کنیم که جداول ایجاد شدهاند. خروجی شما باید مشابه این باشد:
greenlight@greenlight-production:~$ psql $GREENLIGHT_DB_DSN
psql (12.6 (Ubuntu 12.6-0ubuntu0.20.04.1))
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, bits: 256, compression: off)
Type "help" for help.
greenlight=> \dt
List of relations
Schema | Name | Type | Owner
--------+-------------------+-------+------------
public | movies | table | greenlight
public | permissions | table | greenlight
public | schema_migrations | table | greenlight
public | tokens | table | greenlight
public | users | table | greenlight
public | users_permissions | table | greenlight
(6 rows)
اجرای API
در حالی که به droplet متصل هستیم، بیایید فایل باینری اجرایی api را امتحان کنیم. نمیتوانیم روی پورت 80 گوش دهیم زیرا Caddy در حال حاضر از آن استفاده میکند، بنابراین به جای آن روی پورت بدون محدودیت 4000 گوش خواهیم داد.
اگر همراه ما بودهاید، پورت 4000 در droplet شما در حال حاضر باید توسط قوانین firewall مسدود شده باشد، بنابراین نیاز داریم آن را به طور موقت برای اجازه دادن به درخواستهای ورودی باز کنیم. این کار را به این صورت انجام دهید:
greenlight@greenlight-production:~$ sudo ufw allow 4000/tcp Rule added Rule added (v6)
و سپس API را با دستور زیر شروع کنید:
greenlight@greenlight-production:~$ ./api -port=4000 -db-dsn=$GREENLIGHT_DB_DSN -env=production time=2023-09-10T10:59:13.722+02:00 level=INFO msg="database connection pool established" time=2023-09-10T10:59:13.722+02:00 level=INFO msg="starting server" addr=:4000 env=development
در این مرحله باید بتوانید http://<your_droplet_ip>:4000/v1/healthcheck را در مرورگر خود باز کنید و پاسخ موفقی از healthcheck endpoint دریافت کنید، مشابه این:
در نهایت، به پنل SSH خود برگردید و Ctrl+C را فشار دهید تا اجرای API در droplet متوقف شود. باید ببینید که به طور صحیح خاموش میشود به این صورت:
greenlight@greenlight-production:~$ /home/greenlight/api -port=4000 -db-dsn=$GREENLIGHT_DB_DSN -env=production time=2023-09-10T10:59:13.722+02:00 level=INFO msg="database connection pool established" time=2023-09-10T10:59:13.722+02:00 level=INFO msg="starting server" addr=:4000 env=development ^Ctime=2023-09-10T10:59:14.722+02:00 level=INFO msg="shutting down server" signal=terminated time=2023-09-10T10:59:14.722+02:00 level=INFO msg="completing background tasks" addr=:4000 time=2023-09-10T10:59:18.722+02:00 level=INFO msg="stopped server" addr=:4000