Php tanpa server

Menjelang peluncuran kursus Pengembang PHP Backend, kami memiliki pelajaran terbuka tradisional . Kali ini kami berkenalan dengan konsep Serverless, berbicara tentang penerapannya di AWS, membahas prinsip-prinsip operasi, perakitan dan peluncuran, dan juga membangun PHP-bot PHP sederhana berdasarkan AWS Lambda.


Dosen - Alexander Pryakhin , CTO Rusia Westwing.





Sebuah perjalanan singkat ke dalam sejarah



Bagaimana kita bisa sampai pada kehidupan sehingga komputasi tanpa server muncul? Tentu saja, mereka muncul tidak hanya seperti itu, tetapi menjadi kelanjutan logis dari teknologi virtualisasi yang ada.



Apa yang biasanya kita virtualisasikan? Misalnya, sebuah prosesor. Anda juga dapat melakukan virtualisasi memori dengan menyorot area memori tertentu dan membuatnya dapat diakses oleh beberapa pengguna dan tidak dapat diakses oleh orang lain. Anda dapat melakukan virtualisasi jaringan VPN. Dan sebagainya.



Virtualisasi itu baik karena kami lebih baik memanfaatkan sumber daya dan meningkatkan produktivitas. Tetapi ada juga kelemahannya, misalnya, pada suatu waktu ada masalah kompatibilitas. Namun, praktis tidak ada arsitektur yang tidak sesuai dengan mesin virtual modern.


Kekurangan berikutnya adalah kita menambahkan lapisan abstraksi tambahan, menambahkan hypervisor, menambahkan mesin virtual dengan sendirinya, dan, tentu saja, kita bisa kehilangan sedikit kecepatan. Agak rumit dan penggunaan server.



Jika kami membawa mesin virtual standar, itu akan terlihat seperti ini:



Pertama, kami memiliki server besi, dan kedua, sistem operasi yang akan memutar hypervisor kami. Dan di atas semua ini, mesin virtual kami berputar, di mana ada OS tamu, perpustakaan, dan aplikasi. Jika Anda berpikir secara logis, maka kami melihat beberapa overhead di hadapan OS tamu, karena sebenarnya kami menghabiskan sumber daya tambahan.


Bagaimana saya bisa menyelesaikan masalah overhead? Menolak mesin virtual dan meletakkan sistem manajemen kontainer di atas sistem operasi utama. Tentu saja, sistem yang paling populer sekarang adalah Docker Engine. Kemudian pustaka di dalam wadah akan menggunakan kernel host dari sistem operasi.



Dengan cara ini, kami menghapus overhead, tetapi Docker juga tidak ideal, dan memiliki masalah sendiri dan fitur kerja yang tidak semua orang suka.


Hal utama yang harus dipahami adalah Docker dan mesin virtual adalah pendekatan yang berbeda, dan tidak perlu menyamakan mereka. Docker bukan mikrovirtual yang dapat digunakan sebagai mesin virtual, karena wadahnya untuk itu dan wadahnya. Namun wadah tersebut memungkinkan kami untuk memberikan fleksibilitas dan pendekatan yang sama sekali berbeda untuk pengiriman berkelanjutan, ketika kami mengirimkan barang-barang ke produksi dan memahami bahwa mereka sudah diuji dan berfungsi.


Teknologi cloud


Dengan semakin berkembangnya virtualisasi, teknologi cloud juga mulai berkembang. Ini adalah solusi yang baik, tetapi perlu disebutkan segera bahwa awan bukan peluru perak dan bukan obat mujarab untuk semua penyakit. Di sini orang tidak bisa tidak mengingat satu kutipan terkenal:


"Ketika saya mendengar seseorang menggembar-gemborkan cloud sebagai peluru ajaib untuk semua masalah komputasi, saya diam-diam mengganti" cloud "dengan" badut "dan melanjutkan dengan senyum seperti zen."
Amy kaya

Namun, untuk perusahaan menengah yang ingin menerima tingkat layanan tertentu dan toleransi kesalahan tanpa suntikan keuangan yang besar, cloud adalah pilihan yang cukup. Dan bagi banyak perusahaan, menjaga pusat data mereka dengan SLA yang sama akan jauh lebih mahal daripada dilayani di cloud. Selain itu, kita dapat menggunakan cloud untuk kebutuhan kita, karena mereka menyediakan beberapa hal hanya dalam beberapa klik mouse, yang sangat nyaman. Misalnya, kemampuan mengangkat mesin atau jaringan virtual dalam beberapa klik.
Ya, ada batasan, misalnya, Undang-Undang Federal ke 152 yang melarang penyimpanan data pribadi di luar negeri, sehingga Amazon yang sama tidak akan cocok untuk kita selama audit. Jangan lupa tentang Vendor-lock. Banyak solusi cloud yang tidak saling porting, meskipun penyimpanan yang kompatibel dengan S3 yang sama didukung oleh sebagian besar penyedia.


Awan memberi kami kesempatan untuk menerima berbagai tingkat layanan tanpa pengetahuan yang terfokus secara sempit. Semakin sedikit pengetahuan yang Anda butuhkan, semakin banyak kami akan membayar. Pada gambar di bawah ini, Anda dapat melihat piramida, di mana, dari bawah ke atas, penurunan persyaratan pengetahuan teknis saat menggunakan cloud ditampilkan:



Serverless dan FaaS (Berfungsi Sebagai Layanan)


Serverless adalah cara yang cukup muda untuk menjalankan skrip di awan, misalnya, seperti AWS (dalam hal AWS, server diimplementasikan dalam Lambda). Pendekatan * aaS yang tercantum pada piramida di atas sudah akrab: IaaS (EC2, VDS), PaaS (Shared Hosting), SaaS (Office 365, Tilda). Jadi, Serverless adalah implementasi dari pendekatan FaaS. Dan pendekatan ini terdiri dalam menyediakan platform siap pakai bagi pengguna untuk pengembangan, peluncuran, dan pengelolaan fungsionalitas tertentu tanpa perlu persiapan dan konfigurasi sendiri.


Bayangkan bahwa Anda memiliki mesin yang bergerak dalam pemrosesan dokumen malam hari, melakukan tugas dari jam 00:00 hingga jam 6:00, dan selama sisa jam itu diam. Pertanyaannya adalah: mengapa harus membayar di siang hari? Dan mengapa tidak menggunakan sumber daya gratis untuk hal lain? Keinginan untuk optimisasi dan keinginan untuk menghabiskan uang hanya untuk apa yang benar-benar Anda gunakan, dan menyebabkan munculnya FaaS.


Serverless adalah sumber daya untuk mengeksekusi kode dan tidak lebih. Ini tidak berarti bahwa tidak ada server di belakang skrip kami - itu, tetapi kami, pada kenyataannya, tidak memiliki sumber daya yang dialokasikan secara khusus di mana Lambda kami akan diluncurkan. Ketika kami menjalankan skrip kami, infrastruktur mikro segera dibuka di bawahnya, dan ini bukan masalah Anda pada prinsipnya - Anda hanya berpikir bahwa kode Anda dieksekusi, dan Anda tidak perlu memikirkan hal lain.
Tentu saja ini membutuhkan pendekatan tertentu untuk pengembangan kode Anda. Misalnya, Anda tidak dapat menyimpan apa pun di lingkungan ini, Anda harus mengeluarkan semuanya. Jika ini adalah data, maka diperlukan database eksternal, jika ini adalah log, maka layanan log eksternal, jika itu adalah file, maka penyimpanan file eksternal. Untungnya, penyedia Serverless mana pun menyediakan kemampuan untuk terhubung ke sistem eksternal.


Anda hanya memiliki kode, Anda bekerja dalam paradigma Stateless, Anda tidak memiliki status. Untuk dunia PHP yang sama, ini berarti, misalnya, Anda dapat melupakan mekanisme sesi standar. Pada prinsipnya, Anda bahkan dapat membangun Serverless Anda, dan baru-baru ini di Habrรฉ ada artikel tentang hal ini .


Gagasan utama Serverless adalah bahwa infrastruktur tidak memerlukan dukungan dari tim. Semuanya jatuh di pundak platform, di mana Anda, pada kenyataannya, membayar uang. Dari minus - Anda tidak mengontrol lingkungan eksekusi dan tidak tahu di mana apa yang dilakukan.


Jadi Serverless:


  • tidak berarti tidak adanya server secara fisik;
  • bukan pembunuh virtualoks dan Docker;
  • tidak hype di sini dan sekarang.
    Serverless harus didorong secara sadar dan sengaja. Misalnya, jika Anda perlu dengan cepat menguji hipotesis tanpa melibatkan setengah tim. Jadi Anda mendapatkan Function As A Service. Fungsi akan merespons beberapa peristiwa, dan karena ada reaksi terhadap peristiwa, peristiwa ini harus dipanggil oleh sesuatu - untuk ini, ada banyak pemicu dalam AWS yang sama.

Fitur FaaS:


  • infrastruktur tidak memerlukan konfigurasi;
  • Model acara โ€œout of the boxโ€;
  • Tanpa kewarganegaraan;
  • penskalaan sangat mudah dan dilakukan secara otomatis sesuai dengan kebutuhan pengguna.

AWS Lambda


Implementasi FaaS pertama dan tersedia untuk umum adalah AWS Lambda. Jika ini adalah tesis, maka ia memiliki fitur-fitur berikut:
- tersedia sejak 2014;
- Mendukung di luar kotak Java, Node.js, Python, Go, dan runtimes khusus;
- kami membayar untuk:
jumlah panggilan;
memimpin waktu.
AWS Lambda: mengapa dibutuhkan:
Pembuangan Anda hanya membayar untuk saat layanan berjalan.
Kecepatan. Lambda sendiri naik dan bekerja sangat cepat.
Fungsional Lambda memiliki banyak fitur untuk diintegrasikan dengan layanan AWS.
Performa. Menempatkan lambda cukup sulit. Secara paralel, ini dapat dilakukan tergantung pada wilayah dari maksimum 1000 hingga 3000 salinan. Dan jika diinginkan, batas ini dapat ditingkatkan dengan menulis dukungan.


Kami memiliki tubuh lambda, editor online, VPC sebagai kotak perhitungan virtual, pencatatan, kode itu sendiri, variabel lingkungan dan pemicu yang menyebabkan lambda (omong-omong, membuat versi berfungsi dengan sangat baik). Anatomi Lambda yang sangat baik diuraikan dalam artikel ini .


Kode disimpan baik di dalam tubuh (jika ini adalah bahasa yang didukung di luar kotak) atau dalam lapisan. Kami memiliki pemicu yang memanggil lambda, lambda membaca lingkungan sementara, menariknya sendiri dan menjalankan kode kami:



Jika kami memiliki runtime khusus, kami harus meletakkan kode dalam sebuah layer. Jika Anda bekerja dengan Docker, maka layer Docker sangat mirip dengan layer di lambda - semacam repositori semu di mana penjilidan kami yang diperlukan berada. Di sana kita memiliki file lingkungan yang dapat dieksekusi (jika kita berbicara tentang PHP, Anda harus meletakkan biner PHP yang dikompilasi terlebih dahulu), file bootstrap lambda (terletak secara default) dan skrip yang dipanggil langsung yang akan dieksekusi.



Dengan pengiriman, semuanya tidak begitu cerah:



Artinya, kami ditawari untuk mengambil file dengan kode, mengunggahnya ke arsip zip, mengunggahnya ke layer dan menjalankan kode kami. Sangat keren bahwa ini ditawarkan dalam dokumentasi resmi Amazon.



Tentu saja, ini tidak sesuai dengan kenyataan modern, dan bau dua per seribu di udara. Untungnya, orang-orang baik mencoba dan membuat beberapa kerangka kerja, jadi kami akan menggunakan kerangka Serverless yang dikembangkan di Node.js dan memungkinkan kami untuk mengelola aplikasi berdasarkan AWS Lambda. Selain itu, ketika kita berbicara tentang penyebaran dan pengembangan, tentu saja, saya tidak benar-benar ingin menggunakan secara manual, tetapi ada keinginan untuk melakukan sesuatu yang fleksibel dan otomatis.


Jadi, kita perlu:
- AWS CLI - antarmuka baris perintah untuk bekerja dengan layanan AWS;
- kerangka Serverless yang telah disebutkan di atas (versi pengembangan gratis, dan fungsinya cukup untuk mata);
- Perpustakaan Bref, yang diperlukan untuk menulis kode. Pustaka ini diinstal menggunakan komposer, sehingga kode tersebut akan kompatibel dengan kerangka kerja apa pun. Solusi yang bagus, terutama mengingat AWS Lambda tidak mendukung pemanggilan skrip PHP di luar kotak.



Sesuaikan lingkungan dan AWS Anda


AWS CLI


Mari kita mulai dengan membuat akun dan menginstal AWS CLI. Shell konsol AWS didasarkan pada Python 2.7+ atau 3.4+. Karena AWS merekomendasikan versi 3 Python, kami tidak akan berdebat.
Contoh di bawah ini untuk Ubuntu.


sudo apt-get -y install python3-pip 

Kemudian instal langsung AWS CLI:


 pip3 install awscli --upgrade --user 

Periksa instalasi:


 aws --version 

Sekarang Anda harus menghubungkan AWS CLI ke akun Anda. Anda dapat menggunakan nama pengguna dan kata sandi Anda yang sudah ada, tetapi akan lebih baik jika Anda membuat pengguna terpisah melalui AWS IAM, dengan mendefinisikannya hanya hak akses yang diperlukan. Memanggil konfigurasi tidak akan menyebabkan masalah:


 aws configure 

Selanjutnya, Anda akan memerlukan AWS Secret dan AWS Access Key. Mereka dapat diperoleh di ASW IAM di tab "Keamanan kredensial" (terletak di halaman pengguna yang diinginkan). Tombol "Buat kunci akses" akan membantu menghasilkan kunci akses. Simpan bersama mereka.



Untuk mendaftarkan bot baru di Telegram, gunakan @BotFather dan perintah / newbot. Akibatnya, token yang diperlukan untuk menghubungkan ke bot Anda akan dikembalikan kepada Anda. Kunci juga.



Kerangka tanpa server


Untuk menginstal Serverless Framework, Anda perlu akun di https://serverless.com/ .
Setelah menyelesaikan pendaftaran, kami akan melanjutkan ke instalasi di workstation kami. Node.js 6 dan di atas akan diperlukan.


 sudo apt-get -y install nodejs 

Untuk memastikan peluncuran yang benar di lingkungan kami, kami mengikuti langkah-langkah yang disarankan:


 mkdir ~/.npm-global export PATH=~/.npm-global/bin:$PATH source ~/.profile npm config set prefix '~/.npm-global' 

Juga tambahkan:


 ~/.npm-global/bin:$PATH 

ke file / etc / environment.
Sekarang masukkan Serverless:


 npm install -g serverless 

Aws


Nah, saatnya untuk beralih ke antarmuka AWS dan menambahkan nama domain. Kami membuat zona AWS Route 53, catatan DNS, dan sertifikat SSL untuknya.
Selain itu, Anda memerlukan ELB, yang kami buat di layanan EC2 -> Load Balancers. Ngomong-ngomong, saat membuat ELB, Anda harus melewati semua langkah wizard, yang menunjukkan sertifikat yang dibuat.


Sedangkan untuk penyeimbang, Anda bisa membuatnya melalui AWS CLI menggunakan perintah berikut:


 aws elb create-load-balancer --load-balancer-name my-load-balancer --listeners "Protocol=HTTP,LoadBalancerPort=80,InstanceProtocol=HTTP,InstancePort=80" "Protocol=HTTPS,LoadBalancerPort=443,InstanceProtocol=HTTP,InstancePort=80,SSLCertificateId=arn:aws:iam::123456789012:server-certificate/my-server-cert" --subnets subnet-15aaab61 --security-groups sg-a61988c3 

Sebuah penyeimbang akan dibutuhkan setelah penyebaran pertama. Dalam hal ini, Anda perlu mengirim permintaan ke domain kami untuk itu. Untuk mengimplementasikan ini, dalam pengaturan catatan DNS (bidang "Alias โ€‹โ€‹target"), mulai masukkan nama ELB yang dibuat. Akibatnya, Anda akan melihat daftar drop-down, sehingga tetap memilih entri yang diinginkan dan menyimpannya.



Sekarang buka kode.


Menulis kode


Kami akan menggunakan Bref untuk menulis kode. Seperti disebutkan sebelumnya, pustaka ini diinstal menggunakan komposer, sehingga kode tersebut akan kompatibel dengan kerangka kerja apa pun. Omong-omong, para pengembang telah menggambarkan proses menggunakan Bref dengan Laravel dan Symfony . Tetapi disarankan bagi kita untuk mengerjakan PHP "telanjang" - ini akan membantu untuk lebih memahami esensinya.
Kami mulai dengan dependensi:


 { "require": { "php": ">=7.2", "bref/bref": "^0.5.9", "telegram-bot/api": "*" }, "autoload": { "psr-4": { "App\": "src/" } } } 

Kami akan menulis dalam PHP 7.2 dan lebih tinggi, dan untuk bekerja dengan Telegram, shell untuk API ini cocok untuk kami - https://github.com/TelegramBot/Api . Adapun kode itu sendiri, itu akan ditempatkan di direktori src.


Jadi, lingkungan serverless sedang melalui dialog konsol. Diperlukan aplikasi HTTP, dan dari sudut pandang Lambda, ini berarti panggilan skrip akan dieksekusi dengan cara yang sama seperti Nginx. Interpretasi akan dilakukan oleh PHP-FPM. Secara umum, ini lebih mirip panggilan skrip konsol standar. Ini adalah poin penting, karena tanpa mempertimbangkan fitur ini, kami tidak akan dapat memanggil skrip melalui HTTP.
Kami melakukan:


 vendor/bin/bref init 

Dalam dialog, pilih item "aplikasi HTTP" dan jangan lupa untuk menentukan wilayah, karena aplikasi harus bekerja di wilayah yang sama di mana penyeimbang bekerja.
Setelah inisialisasi, 2 file baru akan muncul:
index.php - file yang dipanggil;
serverless.yml - file konfigurasi penyebaran.
Folder .serverless perlu segera ditambahkan ke .gitignore (folder tersebut akan muncul setelah upaya pertama yang digunakan).


Setelah kami memiliki aplikasi web, kami akan memasukkan index.php ke folder publik, segera beralih ke serverless.yml. Berikut ini tampilannya dalam implementasi kami:


 #  lambda- service: app #    provider: name: aws #   ! region: eu-central-1 #    runtime: provided # ,  bref  1024.         memoryLimit: 256 #   stage: dev #    environment: BOT_TOKEN: ${ssm:/app/bot-token} #  bref plugins: - ./vendor/bref/bref #  Lambda- functions: #       php-api-dev # service-function-stage api: handler: public/index.php description: '' # in seconds (API Gateway has a timeout of 29 seconds) timeout: 28 layers: - ${bref:layer.php-73-fpm} #     API Gateway events: - http: 'ANY /' - http: 'ANY /{proxy+}' #    environment: MY_VARIABLE: ${ssm:/app/my_variable} 

Sekarang mari kita menganalisis garis yang tidak jelas. Kami sebagian besar membutuhkan variabel lingkungan. Kami tidak ingin koneksi database hardcode, API eksternal, dll. Jika kami terhubung ke Telegram, kami akan memiliki token kami sendiri, yang diterima dari BotFather. Dan tidak disarankan untuk menyimpan token ini di serverless.yml, jadi lebih baik untuk mengirimnya ke penyimpanan ssm AWS:


 aws ssm put-parameter --region eu-central-1 --name '/app/my_variable' --type String --value '___BOTFATHER' 

Omong-omong, kami merujuknya dalam konfigurasi.
Variabel-variabel ini tersedia sebagai variabel lingkungan, dan Anda dapat mengaksesnya dalam PHP menggunakan fungsi getenv. Jika kita berbicara tentang contoh kita, maka mari kita simpan token bot dalam lingkup global untuk kesederhanaan. Kami juga dapat mentransfer token ke ruang lingkup fungsi tunggal, dan panggilan itu sendiri tidak akan berubah dari ini.


Mari kita lanjutkan. Sekarang mari kita membuat kelas BotApp sederhana - itu akan bertanggung jawab untuk menghasilkan respons untuk bot dan akan menanggapi perintah. Pengembang Telegram merekomendasikan penambahan dukungan untuk perintah / help dan / start untuk semua bot. Mari kita tambahkan perintah lain untuk bersenang-senang. Kelas itu sendiri cukup sederhana dan memungkinkan untuk mengimplementasikan Front controller di index.php tanpa memuat file panggilan itu sendiri. Untuk mendapatkan logika yang lebih kompleks, arsitektur harus dikembangkan dan rumit.


 <?php namespace App; use TelegramBot\Api\Client; use Telegram\Bot\Objects\Update; class BotApp { function run(): void{ $token = getenv('BOT_TOKEN'); $bot = new Client($token); //   start $bot->command('start', function ($message) use ($bot) { $answer = ' !'; $bot->sendMessage($message->getChat()->getId(), $answer); }); //    $bot->command('help', function ($message) use ($bot) { $answer = ': /help -  '; $bot->sendMessage($message->getChat()->getId(), $answer); }); //   $bot->command('hello', function ($message) use ($bot) { $answer = '-,  - ,   Serverless '; $bot->sendMessage($message->getChat()->getId(), $answer); }); $bot->run(); } } 

Dan di sini adalah daftar index.php:


 <?php require_once('../vendor/autoload.php'); use App\BotApp; try{ $botApp = new BotApp(); $botApp->run(); } catch (Exception $e){ echo $e->getMessage(); print_r($e->getTrace(), 1); } 

Ini mungkin tampak aneh, tetapi semuanya siap bagi kita untuk berangkat ke Produksi. Mari kita lakukan ini dengan menjalankan perintah di folder serverless.yml:


 sls deploy 

Dalam mode normal, serverless akan mengemas file dalam arsip zip, membuat S3-bucket tempat untuk meletakkannya, kemudian membuat atau memperbarui Aplikasi AWS yang dilampirkan ke Lambda, dan menempatkan kode dan runtime di lapisan yang terpisah.


Selama peluncuran pertama, Gateway API akan dibuat (kami membiarkannya agar lebih mudah untuk menguji panggilan, tetapi kemudian disarankan untuk menghapusnya). Anda juga perlu mengonfigurasi panggilan Lambda melalui ELB, yang kami pilih "Tambahkan pemicu" di jendela kontrol fungsi dan pilih "Application Load Balancer" di daftar turun bawah. Anda perlu menentukan ELB yang dibuat sebelumnya, mengatur koneksi melalui HTTPS, membiarkan Host kosong, dan di Path menentukan jalur yang akan dipanggil Lambda (misalnya, / lambda / mytgbot). Akibatnya, Lambda Anda akan tersedia di URL dengan jalur yang ditentukan.


Sekarang Anda dapat mendaftarkan bagian respons bot di Telegram sehingga kurir mengerti ke mana harus mendapatkan pesan. Untuk melakukan ini, panggil URL berikut di browser, tetapi jangan lupa untuk mengganti parameter Anda sendiri ke dalamnya:


 https://api.telegram.org/bot_/setWebhook?url=https://my-elb-host.com/lambda/mytgbot 

Akibatnya, API akan mengembalikan "OK", setelah itu bot akan tersedia.



Menguji bot di lokal


Bot dapat diuji sebelum penyebaran. Faktanya adalah bahwa Serverless Framework mendukung peluncuran di lokal menggunakan wadah Docker untuk ini. Perintah panggilan:


 sls invoke local --docker -f myFunction 

Jangan lupa bahwa kami menggunakan variabel lingkungan, jadi selama panggilan mereka juga harus diatur dalam format:


 sls invoke local --docker -f myFunction --env VAR1=val1 

Log


Secara default, output panggilan akan masuk ke CloudWatch - tersedia di panel Pemantauan fungsi Lambda yang sesuai. Di sini Anda dapat membaca jejak panggilan jika terjadi dump di sisi PHP. Selain itu, Anda dapat menghubungkan layanan pemantauan lanjutan, tetapi mereka akan dikenakan biaya beberapa sen tambahan setiap bulan.


Total


Sebagai hasilnya, kami mendapat solusi yang cukup cepat, fleksibel, terukur, dan juga relatif murah. Ya, Lambda tidak selalu menang dibandingkan dengan VM dan wadah standar, tetapi ada situasi ketika aplikasi Serverless membantu untuk "menembak" dengan cepat dan efisien. Dan contoh bot yang dibuat hanya menunjukkan ini.
Materi yang berguna tentang topik:


Source: https://habr.com/ru/post/id477370/


All Articles