Daftar Isi
Latihan
The terakhir kali kami berakhir pada yang ditempatkan halaman Web boneka statis, yang dikembangkan menggunakan Flutter untuk web. Halaman ini menampilkan kemajuan pengembangan layanan kami, tetapi data pada tanggal dimulainya pengembangan dan rilis harus di-hardcode dalam aplikasi. Jadi, kami kehilangan kemampuan untuk mengubah informasi di halaman. Saatnya mengembangkan aplikasi server data. Diagram semua aplikasi layanan ada di artikel "Layanan dalam Bahasa Dart: Pendahuluan, Infrastruktur Backend" .
Pada artikel ini, kami akan menulis aplikasi menggunakan framework Aqueduct, mengevaluasi kinerja dan konsumsi sumber dayanya dalam mode yang berbeda, menulis toolkit untuk mengompilasi ke dalam aplikasi asli untuk Windows dan Linux, menangani migrasi skema database untuk kelas aplikasi domain, dan bahkan mempublikasikan citra buruh pelabuhan alat kami ke register DockerHub publik.
Kegunaan
Memasang Saluran Air
Mari kita mulai dengan menginstal dart-sdk, kit pengembangan Dart. Anda dapat menginstalnya menggunakan pengelola paket sistem operasi Anda seperti yang disarankan di sini . Namun, dalam kasus Windows, tidak ada pengelola paket yang diinstal di sistem Anda secara default. Jadi hanya:
- Unduh arsip dan keluarkan ke drive C:
- , , , . . ยซ ยป

- Path . dart , , C:\dart-sdk\bin
- , dart pub ( dart)
dart --version
pub -v
- , ,
- aqueduct CLI (command line interface)
pub global activate aqueduct
aqueduct

Secara teoritis dimungkinkan untuk menginstal server database PostgreSQL secara lokal juga . Namun, Docker memungkinkan kita untuk menghindari kebutuhan ini dan membuat lingkungan pengembangan mirip dengan runtime di server.
Pembuatan aplikasi
Jadi, mari buka folder server kita di VsCode
code c:/docs/dart_server
Bagi mereka yang belum melihat artikel pertama dan kedua , kode sumber dapat di-clone dari repositori guthub :
git clone https://github.com/AndX2/dart_server.gitMari buat template aplikasi:
aqueduct create data_app
Mari berkenalan dengan konten template proyek:
- README.md - catatan yang menjelaskan cara bekerja dengan proyek saluran air, menjalankan tes, membuat dokumentasi API, dll. File dukungan.
- pubspec.yaml โ pub. , , , .
- config.yaml config.src.yaml โ . .
- analysis_options.yaml โ ( ). .
- .travis.yml โ (continuous Integration). .
- pubspec.lock .packages โ pub. โ , , โ ().
- .dart_tool/package_config.json โ , aqueduct CLI. .
- bin/main.dart โ (, ). ( ).
- lib/channel.dart โ ApplicationChannel โ . Aqueduct CPU RAM. ( Dart isolate) () .

- lib/data_app.dart โ . (library) dart_app
- test/ โ . -, . Postman.
Konfigurasi
Tugas pertama yang harus diselesaikan adalah menyiapkan aplikasi saat startup. Aqueduct memiliki mekanisme built-in untuk mengekstrak parameter dari file konfigurasi, tetapi mekanisme ini sangat tidak nyaman saat dijalankan di container Docker. Kami akan bertindak berbeda:
- Mari teruskan daftar variabel ke sistem operasi container.
- Saat meluncurkan aplikasi di dalam penampung, kami membaca variabel lingkungan sistem operasi dan menggunakannya untuk konfigurasi awal.
- Mari buat rute untuk melihat semua variabel lingkungan dari aplikasi yang berjalan melalui jaringan (ini akan berguna saat melihat status aplikasi dari panel admin).
Di folder / lib , buat beberapa folder dan repositori pertama untuk mengakses variabel lingkungan:
EnvironmentRepository di konstruktor membaca variabel lingkungan dari sistem operasi dalam bentuk kamus Map <String, String> dan menyimpannya di variabel privat _env . Mari tambahkan metode untuk mendapatkan semua parameter dalam bentuk kamus: lib / service / EnvironmentService - komponen logis untuk mengakses data EnvironmentRepository:
Injeksi ketergantungan
Di sini Anda perlu berhenti dan menangani dependensi komponen:
- pengontrol jaringan akan membutuhkan turunan dari layanan variabel,
- layanan harus unik untuk seluruh aplikasi,
- untuk membuat layanan, Anda harus terlebih dahulu membuat instance dari repositori variabel.
Kami akan menyelesaikan masalah ini menggunakan pustaka GetIt . Hubungkan paket yang diperlukan ke pubspec.yaml :
Buat instance container injector lib / di / di_container.dart dan tulis metode dengan pendaftaran repositori dan layanan: Panggil metode inisialisasi container DI dalam metode persiapan aplikasi:
Lapisan jaringan
lib / controller / ActuatorController - komponen jaringan http. Ini berisi metode untuk mengakses data layanan aplikasi: Mari kita deklarasikan penangan rute untuk pengontrol di lib / controller / Routes :
Awal pertama
Untuk menjalankan Anda membutuhkan:
- mengemas aplikasi menjadi image Docker,
- menambahkan wadah ke skrip tulis-buruh pelabuhan,
- konfigurasikan NGINX ke permintaan proxy.
Buat Dockerfile di folder aplikasi . Ini adalah skrip untuk membuat dan menjalankan image untuk Docker: Tambahkan container aplikasi ke skrip docker-compose.yaml : Buat file data_app.env dengan variabel konfigurasi untuk aplikasi: Tambahkan lokasi baru ke NGINX debug config conf.dev.d / default.conf : Jalankan debug skrip dengan bendera pra-bangun:
docker-compose -f docker-compose.yaml -f docker-compose.dev.yaml up --build
Skrip berhasil dijalankan, tetapi ada beberapa poin yang mengkhawatirkan:
- gambar panah resmi dari google diarsipkan 290MB . Saat dibuka, akan memakan lebih banyak ruang - 754MB. Lihat daftar gambar dan ukurannya:
docker images - Waktu kompilasi build dan JIT adalah 100+ detik. Terlalu banyak untuk menjalankan aplikasi yang sedang diobral
- Konsumsi memori di dasbor docker 300 MB segera setelah peluncuran
- Dalam uji stres (jaringan GET / api / aktuator / permintaan saja) konsumsi memori berada dalam kisaran 350-390 MB untuk aplikasi yang berjalan dalam satu isolat
Agaknya, sumber daya VPS anggaran kami tidak cukup untuk menjalankan aplikasi intensif sumber daya seperti itu. Mari kita periksa:
- Buat folder di server untuk versi baru aplikasi dan salin konten proyek
ssh root@dartservice.ru "mkdir -p /opt/srv_2" && scp -r ./* root@91.230.60.120:/opt/srv_2/ - Sekarang Anda perlu mentransfer ke folder ini proyek halaman web dari / opt / srv_1 / public / dan seluruh konten folder / opt / srv_1 / sertbot / (ini berisi sertifikat SSL untuk NGINX dan Mari mengenkripsi bot log), dan salin kunci dari / opt / srv_1 / dhparam /
- Luncurkan monitor sumber daya server di konsol terpisah
htop
- Mari jalankan script docker-compose di folder / opt / srv_2 /
docker-compose up --build -d - Beginilah tampilan rakitan aplikasi sebelum peluncuran:
- Dan sebagainya - dalam pekerjaan:
Dari 1GB RAM yang tersedia, aplikasi kita menggunakan 1,5GB "menempati" file halaman yang hilang. Ya, aplikasi telah dimulai, tetapi kami tidak berbicara tentang kapasitas muat apa pun. - Mari hentikan skrip:
docker-compose down
AOT
Kami memiliki tiga tugas untuk diselesaikan:
- kurangi konsumsi RAM dengan aplikasi dart,
- kurangi waktu startup,
- mengurangi ukuran container buruh pelabuhan dari aplikasi.
Solusinya adalah mengabaikan panah pada waktu proses. Sejak versi 2.6, aplikasi dart mendukung kompilasi menjadi kode eksekusi asli . Saluran air mendukung kompilasi mulai dari versi 4.0.0-b1.
Mari kita mulai dengan menghapus CLI saluran air secara lokal:
pub global deactivate aqueduct
Instal versi baru:
pub global activate aqueduct 4.0.0-b1
Mari kita tingkatkan ketergantungan di pubspec.yaml: Mari kita membangun
aplikasi asli:
aqueduct build
Hasilnya akan menjadi satu file data_app.aot assembly berukuran sekitar 6MB . Anda dapat segera meluncurkan aplikasi ini dengan parameter, misalnya:
data_app.aot --port 8080 --isolates 2
Konsumsi memori segera setelah peluncuran kurang dari 10 MB.
Mari kita lihat di bawah beban. Parameter uji: permintaan jaringan GET / aktuator, 100 utas dengan kecepatan maksimum yang tersedia, 10 menit. Hasil:
Total: kecepatan rata-rata - 13 ribu permintaan per detik untuk isi respons JSON 1,4kV, waktu respons rata-rata - 7 md, konsumsi memori (untuk dua instance) 42 MB. Tidak ada kesalahan.
Saat kami mengulang pengujian dengan enam aplikasi, kecepatan rata-rata tentu saja naik menjadi 19k / s, tetapi utilisasi prosesor mencapai 45% saat konsumsi memori 64 MB.
Ini adalah hasil yang luar biasa.
Kemasan wadah
Di sini kita akan menghadapi satu kesulitan lagi: kita hanya dapat mengkompilasi aplikasi dart menjadi aplikasi asli untuk OS saat ini. Dalam kasus saya, ini adalah Windows10 x64. Dalam wadah buruh pelabuhan, saya tentu saja lebih memilih salah satu distribusi Linux - misalnya Ubuntu 20.10.
Solusinya di sini akan menjadi docker-stand perantara, digunakan hanya untuk membangun aplikasi asli untuk Ubuntu. Mari kita tulis / dart2native / Dockerfile : Sekarang mari kita membangunnya menjadi gambar buruh pelabuhan bernama aqueduct_builder: 4.0.0-b1 , menimpa versi lama, jika ada:
docker build --pull --rm -f "dart2native\Dockerfile" -t aqueduct_builder:4.0.0-b1 "dart2native"
Mari kita periksa:
docker images
Mari menulis skrip build untuk aplikasi native docker-compose.dev.build.yaml : Jalankan skrip build:
docker-compose -f docker-compose.dev.build.yaml up
File data_app.aot yang dikompilasi untuk Ubuntu sudah membutuhkan 9 MB. Saat memulai, gunakan 19 MB RAM (untuk dua contoh). Mari kita lakukan pengujian beban lokal dalam kondisi yang sama, tetapi dalam wadah dengan proxy NGINX (GET, 100 utas):
Rata-rata, 5,3 ribu permintaan per detik. Pada saat yang sama, konsumsi RAM tidak melebihi 55 MB. Ukuran gambar telah menurun dibandingkan dengan dart dan saluran air yang dipasang dari 840 MB menjadi 74 MB pada disk.
Mari kita tulis skrip baru docker-compose.aot.yaml untuk meluncurkan aplikasi. Untuk melakukan ini, kami akan mengganti blok deskripsi data_app dengan menginstal gambar dasar "kosong" Ubuntu: 20.10. Mari pasang file assembly dan ubah perintah peluncuran:
Mari kita selesaikan satu masalah layanan lagi: pada kenyataannya, gambar pembuatan buruh pelabuhan dengan panah dan saluran air terpasang adalah alat yang cukup dapat digunakan kembali. Masuk akal untuk mengunggahnya ke register publik dan menghubungkannya sebagai gambar siap pakai yang dapat diunduh. Ini membutuhkan:
- mendaftar dengan register publik seperti DockerHub ,
- masuk secara lokal dengan login yang sama
docker login - ganti nama gambar yang diunggah sesuai dengan skema login / judul: tag
docker image tag a365ac7f5bbb andx2/aqueduct:4.0.0-b1 - bongkar gambar ke register
docker push andx2/aqueduct:4.0.0-b1
https://hub.docker.com/repository/docker/andx2/aqueduct/general
Sekarang kita dapat memodifikasi skrip build kita untuk menggunakan gambar publik
Koneksi database
Aqueduct sudah memiliki ORM built-in untuk bekerja dengan database PostgreSQL. Untuk menggunakannya, Anda membutuhkan:
- Buat objek domain yang mendeskripsikan record dalam database.
- . : , , . Aqueduct , , ManagedObject ( ), , . .
- . , , .
- , aqueduct, , seed() โ - .
- aqueduct CLI.
Mari kita mulai dengan menghubungkan container docker baru ke database PostgreSQL dalam skrip docker-compose.aot.yaml. Gambar siap berdasarkan Linux Alpine (versi "kompak" dari Linux untuk aplikasi tertanam): Di sini Anda perlu memperhatikan file variabel lingkungan data_db.env . Faktanya adalah bahwa gambar telah dikonfigurasi sebelumnya untuk menggunakan variabel ini sebagai nama pengguna, host, port, dan kata sandi akses. Mari tambahkan variabel ini ke file: Nilai diberikan secara bersyarat. Kami juga akan me-mount folder host ./data_db/ ke dalam wadah untuk menyimpan data database. Selanjutnya, di aplikasi data_app, tambahkan kelas / service / DbHelper untuk terhubung ke database menggunakan variabel lingkungan:
Mari buat objek domain yang dikelola ORM untuk mendapatkan pengaturan aplikasi klien: Tambahkan repositori dan layanan untuk menambahkan pengaturan dan dapatkan versi saat ini: Pengontrol jaringan: Daftarkan komponen baru di wadah DI: Tambahkan pengontrol baru dan titik akhir ke router: Sekarang kita membuat file migrasi database. Mari kita jalankan:
aqueduct db generateHasilnya adalah pembuatan file migrasi di folder proyek:
Sekarang Anda perlu menyelesaikan masalah layanan: migrasi harus diterapkan dari sistem dengan saluran air (dan dart) yang dipasang ke database yang berjalan dalam penampung, dan ini harus dilakukan selama pengembangan lokal dan di server. Untuk kasus ini, kami akan menggunakan gambar yang dibuat dan diterbitkan sebelumnya untuk perakitan AOT. Mari kita tulis skrip migrasi database docker-compose yang sesuai:
Detail yang menarik adalah string koneksi database. Saat menjalankan skrip, Anda dapat meneruskan file dengan variabel lingkungan sebagai argumen, lalu menggunakan variabel berikut untuk substitusi di skrip:
docker-compose -f docker-compose.migrations.yaml --env-file=./data_app.env --compatibility up --abort-on-container-exit
Mari perhatikan juga bendera peluncuran:
- --compatibility - kompatibilitas dengan versi docker-compose dari skrip 2.x. Ini akan memungkinkan opsi penerapan digunakan untuk membatasi penggunaan sumber daya oleh penampung, yang diabaikan di versi 3.x. Kami telah membatasi konsumsi RAM hingga 200MB dan penggunaan CPU hingga 50%
- --abort-on-container-exit - Bendera ini menyetel mode eksekusi skrip sehingga ketika salah satu wadah skrip berhenti, semua yang lain akan dihentikan. Oleh karena itu, ketika perintah untuk memigrasi skema database dijalankan dan container dengan aqueduct berhenti, docker-compose juga akan menghentikan container database.
Publikasi
Untuk mempersiapkan penerbitan aplikasi, Anda harus:
- data_app.env data_db.env. , POSTGRES_PASSWORD=postgres_password
- docker-compose.aot.yaml docker-compose.yaml.
- /api/actuator. .
Salin folder aplikasi ./data_app/ ke server . Poin penting di sini adalah sakelar -p (salin sambil mempertahankan atribut file) dalam perintah salin. Izinkan saya mengingatkan Anda bahwa saat membangun aplikasi asli, kami menetapkan hak eksekusi ke file data_app.aot :
scp -rp ./data_app root@dartservice.ru:/opt/srv_1
Mari kita juga menyalin:
- Konfigurasi NGINX telah diubah ./conf.d/default.conf
- Skrip startup dan migrasi docker-compose.yaml , docker-compose.migrations.yaml
- File dengan variabel lingkungan data_app.env dan data_db.env
Tambahkan folder / opt / srv_1 / data_db di server . Ini adalah volume sistem file host yang akan dipasang di wadah database. Semua data PostgreSQL akan disimpan di sini.
mkdir /opt/srv_2/data_db
Mari jalankan skrip untuk memigrasi skema database:
docker-compose -f docker-compose.migrations.yaml --env-file=./data_app.env up --abort-on-container-exit
Mari jalankan skrip aplikasi:
docker-compose up -d
-> Kode sumber github
Alih-alih kesimpulan
Kerangka untuk aplikasi backend sudah siap. Pada artikel berikutnya, berdasarkan itu, kami akan menulis aplikasi baru untuk memberi otorisasi kepada pengguna layanan. Untuk melakukan ini, kami akan menggunakan spesifikasi oAuth2 dan berintegrasi dengan VK dan Github.