3 poin oleh GN⁺ 2023-12-08 | 1 komentar | Bagikan ke WhatsApp
  • FLAME membungkus sebagian kode aplikasi yang sudah ada menjadi fungsi lalu menjalankannya pada salinan aplikasi sementara, dengan tujuan mencapai elastic scaling yang terperinci tanpa memindahkan kode ke runtime terpisah
  • Pendekatan FaaS tradisional dapat membuat struktur yang makin kompleks bahkan untuk tugas seperti pembuatan thumbnail video, dengan HTTP, S3, SQS, API Gateway, encoder/decoder, dan orkestrasi workflow yang terus bertambah
  • Library flame untuk Elixir mendelegasikan eksekusi fungsi ke runner jarak jauh dengan FLAME.call, dan FLAME.FlyBackend dari Fly.io menyalakan Fly Machine baru dengan image Docker yang sama lalu menghubungkannya ke node induk dalam sekitar 3 detik
  • Dalam pengembangan dan pengujian, LocalBackend menjalankan kode pada runtime yang sama, sementara di produksi min, max, max_concurrency, dan idle_shutdown_after mengatur scale-to-zero serta pemeliharaan status hot dalam waktu singkat
  • Alih-alih menghilangkan job queue, FLAME memisahkan jaminan durabilitas dari eksekusi elastis, sehingga queue menangani dispatch, commit, dan retry, sedangkan pekerjaan intensif CPU diproses di dalam pemanggilan FLAME

Masalah yang ingin dipecahkan pola FLAME

  • Auto scaling elastis mengurangi beban pengelolaan server dan menjanjikan biaya berbasis penggunaan, tetapi penggunaan FaaS juga bisa menambah queue terpisah, storage, glue code, serta kompleksitas pengembangan, pengujian, dan CI
  • FLAME adalah singkatan dari Fleeting Lambda Application for Modular Execution, yaitu pendekatan yang memperlakukan seluruh aplikasi seperti lambda dan hanya menjalankan sebagian pekerjaan modul pada infrastruktur yang hidup sebentar
  • Tujuannya dirangkum menjadi tiga hal
    • mengurangi pengelolaan server dengan alur deployment yang sudah ada seperti fly deploy, git push heroku, kubectl
    • melakukan scaling granular on-demand hanya pada bagian tertentu dari kode aplikasi
    • tidak menulis ulang aplikasi atau memindahkan sebagian kode ke runtime proprietary

Memindahkan fungsi yang sudah ada dengan FLAME.call

  • Contohnya adalah fungsi generate_thumbnails dalam aplikasi Elixir yang mengubah video yang diunggah menjadi thumbnail menggunakan ffmpeg
  • Fungsi yang ada membuat direktori sementara, menjalankan ffmpeg, lalu menyimpan thumbnail yang dihasilkan ke storage yang durable dan mencatat URL-nya ke DB dengan Repo.insert_all
  • Karena transcoding video yang intensif CPU dapat menghentikan seluruh layanan di produksi, isi fungsi dibungkus dengan FLAME.call(MyApp.FFMpegRunner, fn -> ... end) alih-alih memindahkan seluruh kode ke FaaS atau microservice
  • FLAME.call menerima nama pool runner dan sebuah fungsi, lalu mencari atau menyalakan salinan baru dari seluruh aplikasi dan hanya menjalankan fungsi tersebut
    • Variabel seperti struct %Video{} dan interval yang ditangkap closure akan diteruskan secara otomatis
    • Runner FLAME terhubung ke node induk setelah menyala, menerima fungsi yang akan dijalankan, lalu mengembalikan hasilnya ke pemanggil
    • Bergantung pada konfigurasi, runner dapat menunggu pekerjaan tambahan lalu dimatikan saat idle, atau langsung berhenti
  • Karena seluruh aplikasi berjalan termasuk koneksi DB, Repo.insert_all tetap bisa digunakan seperti pada kode aslinya

Kompleksitas FaaS dan perbedaan FLAME

  • FaaS menyediakan komponen untuk menyelesaikan masalah, tetapi FLAME lebih mendekati pendekatan untuk mengurangi lapisan komunikasi terpisah itu sendiri
  • Dalam contoh thumbnail video, bahkan jika dimulai dari AWS Lambda Function URL yang sederhana, kompleksitas segera muncul
    • Jika thumbnail ingin di-stream kembali ke aplikasi melalui HTTP, encoder dan decoder kustom harus ditulis di kedua sisi
    • Jika transcoding video atau upload melebihi 15 menit, hard timeout Lambda memaksa video dipecah menjadi chunk dan memakai lebih banyak Lambda
    • Diperlukan orkestrasi workflow dan layanan tambahan seperti SQS dan S3
  • Implementasi berbasis FaaS biasanya menimbulkan titik biaya berikut
    • memicu Lambda melalui HTTP endpoint, S3, atau API Gateway
    • menulis Lambda khusus untuk transcoding video
    • menyimpan hasil thumbnail ke SQS
    • menulis SQS consumer di sisi aplikasi
    • menyimpan ke DB dan menyiapkan cara mengirim event ke subscriber aktif yang terhubung ke instance lain
  • FLAME memungkinkan penggunaan langsung kode internal aplikasi, DB yang ada, PubSub, dan fitur platform yang sudah ada, sehingga mengurangi layanan tambahan dan storage untuk pengambilan hasil

Backend Fly.io dan eksekusi lokal

  • flame library untuk Elixir adalah implementasi pola FLAME, dan secara default menyediakan LocalBackend serta FlyBackend
  • FLAME.FlyBackend menyalakan salinan aplikasi pada Machine baru di infrastruktur Fly.io dan dapat terhubung ke node induk dalam sekitar 3 detik untuk menerima pekerjaan
  • Karena Fly.io menjalankan aplikasi sebagai image Docker yang sudah dipaketkan, API Fly diminta untuk menyalakan Machine baru dengan image yang sama seperti aplikasi saat ini
  • Di infrastruktur Fly.io, runner FLAME dapat dimulai di region yang sama dengan induknya untuk mengurangi latensi antara induk dan runner
  • FLAME.FlyBackend memiliki kurang dari 200 LOC termasuk dokumentasi, dan satu-satunya dependensi library adalah HTTP client req
  • Dalam pengembangan dan pengujian, LocalBackend menjalankan kode tersebut pada runtime yang ada di laptop atau server CI

Pengiriman file dan penyederhanaan pengembangan/pengujian

  • FLAME dapat menggunakan kembali business logic, konfigurasi DB, PubSub, dan fitur platform tanpa menulis kode di luar aplikasi
  • Di Elixir, berkat kemampuan distribusi pada Erlang VM, stream file dari node induk dapat dikirim ke aplikasi FLAME jarak jauh
    • Node induk membuka stream file dari path video
    • Anak FLAME membuka stream file sementara dan menyalin stream dari induk
    • Setelah itu ffmpeg membuat thumbnail dengan file sementara di runner jarak jauh sebagai input
  • Dengan pendekatan ini, file dapat dikirim ke server FLAME tanpa harus menyiapkan antarmuka S3 atau HTTP secara terpisah
  • Deployment layanan terpisah, pengelolaan endpoint, pengambilan hasil melalui S3/SQS, serta konfigurasi dependensi untuk pengembangan, pengujian, dan CI pun berkurang

FLAME di luar Elixir

  • Elixir cocok untuk model FLAME karena menyediakan supervisi proses dan distributed messaging, tetapi bahasa lain dengan primitive konkurensi yang masuk akal juga dapat memakai pola ini
  • Contoh proof of concept JavaScript menjalankan fungsi aplikasi pada Fly Machine di mesin lain: fly-run-this-function-on-another-machine
  • Alur umum pemanggilan FLAME berbasis JavaScript adalah memindahkan bagian eksekusi modul ke file baru lalu menjalankannya di pool runner
  • Jika argumennya dapat diserialisasi sebagai JSON, alurnya mirip dengan contoh Elixir: kode aplikasi dijalankan pada instance yang hidup sebentar
  • Library FLAME yang lengkap perlu menangani hal-hal berikut
    • logika elastic pool scale-up dan scale-down
    • pengelolaan pool dengan mempertimbangkan hot startup dan cold startup
    • pemantauan runner jarak jauh untuk mencegah orphaned resource
    • cara menjaga deployment tetap mutakhir

Hubungan dengan queue pekerjaan latar belakang

  • FLAME juga dapat bekerja di dalam background job processor, tetapi ada bagian peran yang tumpang tindih dengan job queue
  • Job queue biasanya digunakan saat jaminan durabilitas diperlukan, dan queue dapat disesuaikan agar memproses lebih banyak pekerjaan ketika beban berubah
  • Pekerjaan yang durable dan eksekusi elastis adalah perhatian yang berbeda
    • Jika queue dipakai hanya untuk offload eksekusi, perlu glue code untuk memasukkan data ke pekerjaan dan mengembalikan hasil ke pemanggil atau perangkat pengguna
    • Jika keberhasilan pembuatan thumbnail setelah upload video harus dijamin, queue dapat menangani mekanisme dispatch, commit, dan retry
    • Transcoding yang sebenarnya dapat dijalankan melalui pemanggilan FLAME di dalam job agar durabilitas dan eksekusi yang dapat diskalakan dipisahkan
  • Pekerjaan seperti pratinjau video sebelum disimpan atau menjalankan model ML ketika pengguna sudah meninggalkan aplikasi mungkin tidak cocok dengan struktur yang menulis pekerjaan ke storage durable

Pool runner untuk elastic scaling

  • Implementasi FLAME di Elixir mendefinisikan pool elastis untuk runner sehingga mendukung scale-to-zero sekaligus pembatasan konkurensi
  • Contoh konfigurasi menambahkan FLAME.Pool ke start/2 aplikasi
    • min: 0 untuk mengizinkan scale-to-zero
    • max: 10 untuk menyalakan maksimal 10 runner
    • max_concurrency: 5 untuk mendukung 5 pekerjaan ffmpeg per runner
    • idle_shutdown_after: 30_000 untuk mematikan saat idle jika tidak ada pemanggilan selama 30 detik
  • Berdasarkan ada tidaknya induk FLAME, server web Phoenix dijalankan secara kondisional
    • Tidak perlu menjalankan web server pada runner FLAME yang tidak menangani traffic web
    • MyApp.Repo seperti DB tetap dibiarkan karena perlu digunakan di dalam runner FLAME
  • Dengan min: 1, setidaknya satu runner ffmpeg dapat dipertahankan dalam keadaan hot sejak aplikasi dimulai

Penempatan proses stateful

  • Bagian stateful dari aplikasi Elixir dibangun di sekitar primitive proses ringan yang memiliki mailbox pesan
  • FLAME.call dan FLAME.cast cocok untuk kode yang relatif stateless, sedangkan FLAME.place_child memulai spesifikasi proses yang sudah ada pada runner FLAME alih-alih secara lokal
  • FLAME.place_child dapat digunakan di tempat yang memakai antarmuka seperti Task.Supervisor.start_child atau DynamicSupervisor.start_child
  • Dalam contoh pembuatan thumbnail saat upload LiveView, chunk upload dikirim ke proses ThumbnailGenerator, dan proses itu berkomunikasi dengan ffmpeg
    • Saat menemukan delimiter PNG di stdout ffmpeg, proses itu mengirim pesan gambar ke proses LiveView
    • LiveView menerima pesan itu di handle_info lalu menambahkan gambar baru ke UI
  • Jika pemanggilan DynamicSupervisor.start_child(@sup, spec) yang ada diganti menjadi FLAME.place_child(Thumbs.FFMpegRunner, spec), proses ThumbnailGenerator akan berjalan pada runner FLAME
  • Karena proses dapat saling berkirim pesan tanpa memedulikan lokasi, ketika proses berakhir akibat upload selesai atau tab browser ditutup, server FLAME mendeteksi penghentian itu dan akan idle down saat tidak ada pekerjaan lain

Pemantauan jarak jauh dan penanganan kegagalan

  • Infrastruktur yang hidup sebentar memerlukan failsafe untuk mencegah orphaned resource
  • Ketika induk menyalakan runner, runner harus dapat melakukan idle down sendiri saat tidak ada pekerjaan, dan harus melakukan failsafe shutdown jika tidak lagi bisa berkomunikasi dengan node induk
  • Saat induk diganti oleh deployment baru, runner juga harus dihentikan untuk menjamin cluster menjalankan kode yang sama
  • Pemanggil aktif yang menunggu hasil dari runner harus mempertimbangkan kemungkinan runner berhenti karena alasan apa pun
  • Primitive yang disediakan Erlang VM membuat implementasi ini lebih sederhana
    • monitoring dan supervision proses lokal maupun jarak jauh
    • node monitoring untuk mendeteksi node naik dan turun
    • alur shutdown yang mengontrol urutan start/stop aplikasi agar runner aktif punya waktu menyelesaikan pekerjaan saat deployment baru
  • Detail implementasi internal akan dibahas di tulisan terpisah, dan saat ini source flame dapat ditinjau

Status saat ini dan langkah berikutnya

  • Library FLAME untuk Elixir masih berada pada tahap awal, tetapi sudah bisa dicoba sekarang
  • Ke depan direncanakan teknik pertumbuhan pool yang lebih canggih dan analisis mendalam tentang cara implementasi Elixir
  • Diskusi tentang implementasi pola FLAME di bahasa lain juga dimungkinkan

1 komentar

 
GN⁺ 2023-12-08
Opini Hacker News
  • Setelah mengalami sendiri rasa sakit dan kompleksitas aplikasi dengan lebih dari 100 fungsi Lambda selama 4 tahun terakhir, menurut saya tulisan ini tepat menyoroti kelemahan arsitektur serverless FaaS
    Saat baru mulai, kelemahan seperti ini tidak terlalu terlihat. Justru kalau pemakaiannya rendah, keuntungannya jelas: nyaris gratis dan hampir tanpa pemeliharaan
    Baru belakangan, ketika alur kerja Lambda saling kusut dan makin kaku karena saling ketergantungan, Anda akan menyesal dan berpikir seharusnya saja memakai monolith lalu mengelolanya sendiri dengan biaya beberapa ratus dolar lebih mahal. Sekarang, tempat seperti fly.io mungkin malah bisa lebih murah
    Saya penasaran apa yang terjadi kalau tidak memakai Elixir

    • Saya terus melihat pola bahwa developer yang bersemangat bisa membuat hampir proses atau arsitektur apa pun tetap berjalan selama sekitar 18 bulan, dan sekarang itu terasa hampir seperti rangkuman atau hukum
      Saat keadaan mulai memburuk, biasanya juga sudah waktunya mencari pekerjaan baru. Terutama kalau sekitar setahun setelah bergabung Anda mulai menyesali proses yang Anda perkenalkan sendiri. Saya sudah melihat ini berkali-kali pada atasan buruk, ‘unit test’ yang berantakan, Scrum, dan sebagainya
      Namun saya tidak tahu apakah orang-orang benar-benar mengenali penyebab ketidaknyamanan yang mereka rasakan di tempat kerja, atau hanya menerimanya secara samar sebagai “sudah waktunya pergi”. Ketika saya mencoba memberi nama pada hal yang tidak nyaman itu, saya mendapat banyak penolakan, dan setelah membaca Good to Great, beban emosional saya soal itu jauh berkurang. Tidak ada yang ingin berkata, “Oh, ini akibat dari tindakan saya sendiri”
      Orang-orang yang secara nyata menciptakan sistem ala Rube Goldberg yang saya pelihara adalah yang paling dulu pergi. Kapten kapal itu bertanya kepada rekan kerja apakah sebaiknya kami meng-open-source-kan engine kami, dan rekan itu menjawab bahwa tidak ada yang ingin memakai sistem yang menciptakan ulang roda yang sudah ada dan lebih baik. Orang itu mengundurkan diri dalam 3–4 bulan
    • Kami sedang membuat sesuatu yang seharusnya bisa memecahkan masalah ini di bahasa apa pun. Saat ini ada TypeScript SDK, dan Java juga sedang dikerjakan
      Jika Anda bisa menulis kode berorientasi layanan biasa yang memungkinkan Lambda saling memanggil, Anda tidak perlu memecah aplikasi menjadi ratusan potongan yang berjalan singkat. Namun itu tidak mungkin kalau Anda harus membayar juga untuk waktu menunggu. Jika Lambda bisa menjeda eksekusi saat menunggu I/O, masalahnya terselesaikan. Jadi menurut saya durable execution bisa menjadi jawabannya
      Selama beberapa minggu terakhir saya menulis artikel untuk menunjukkan hal ini: https://restate.dev/blog/suspendable-functions-make-lambda-t...
    • Salah satu bagian artikel juga membahas FLAME di luar Elixir. Ringkasnya, ini adalah pola yang umumnya bisa diterapkan pada bahasa yang punya model konkurensi yang masuk akal
      Kemudahan pakai yang didapat gratis di Elixir, seperti fungsi yang variabel hasil capture-nya bisa diserialisasi, mungkin sulit didapat semuanya. Namun di bahasa seperti JavaScript, saya rasa sekitar 90% bisa dicapai dengan memindahkan bagian eksekusi modul ke file baru, alih-alih membungkusnya dalam closure
      Orang yang mengimplementasikan pustaka FLAME juga harus menulis bagian pooling, monitoring, dan komunikasi jarak jauh. Elixir mendapatkan banyak hal gratis untuk messaging terdistribusi dan monitoring. Fitur terkait penempatan proses juga pada dasarnya hanya berlaku untuk Elixir
    • Bahkan hanya dengan 12 Lambda saja sudah sulit ditahan. Aplikasi aslinya dibuat oleh seseorang yang tidak terlalu mempertimbangkan pemeliharaan atau deployment, dan kodenya copy-paste di mana-mana
      Pada akhirnya kami pindah ke monolith Lambda gemuk, yaitu satu Lambda yang menangani beberapa endpoint
    • Kalau Anda tidak terlalu peduli pada cold start atau bisa mengelolanya, Anda juga bisa membuat monolith di Lambda
      Dengan kata lain, Anda bisa tetap memakai monolith sambil meminimalkan biaya AWS. Ini bukan masalah harus memilih salah satu
      Sekarang saya memakai asp.net, dan bahkan aplikasi yang cukup besar yang dideploy sebagai ready-to-run, termasuk model EF yang dioptimalkan, bisa mulai relatif cepat
  • Saya penulisnya. Senang akhirnya bisa memublikasikannya, dan saya akan menjawab kalau ada pertanyaan. Saya berharap beberapa orang cukup terdorong untuk mengimplementasikan pola FLAME di JavaScript, Go, dan bahasa lain

    • Kelihatannya bagus. Saya berharap Microsoft memperhatikannya. Azure Functions terlalu rumit dalam pengaturan keamanan dan deployment, serta punya asumsi aneh tentang kode seperti apa yang ingin dijalankan
    • Implementasi paling alami sepertinya akan berbentuk seperti vert.x di JVM
      Di sana sudah ada mekanisme untuk menangani scaling reaktif, Future, dan eksekusi asinkron melalui coroutine di atas event bus, serta mendukung serialisasi dan distribusi data di seluruh klaster. Ada juga klien event bus untuk beberapa bahasa populer, jadi mungkin aplikasi bisa dibuat dengan mencampur beberapa bahasa
    • Sebaiknya sedikit mengurangi hiperbolanya
      Kalau masalah disajikan seperti “…takdir yang lebih buruk daripada kematian”, lalu solusinya digambarkan begitu mudah dan tanpa rasa sakit sampai orang yang tidak meninggalkan pendekatan lain terlihat bodoh, tulisan seperti ini mudah dianggap sebagai tulisan sales murni. Itu gaya penjual obat mujarab
      Di awal tulisan, masalahnya sendiri sudah ditunjukkan dengan baik, jadi kalau ada perbandingan objektif yang jauh lebih tidak emosional, mungkin orang-orang yang penasaran dengan pendekatan yang lebih baik akan lebih tidak merasa ditolak
      Isi substansial tulisannya menarik, tetapi cara penyampaiannya membuat saya enggan. Semoga ini diterima sebagai umpan balik konstruktif
    • Artikel dan videonya bagus, dan konsepnya juga sangat menarik. Saya menantikan implementasi JavaScript, meski tampaknya tidak mudah
      Dan saya jadi merasa sedikit bersalah karena sudah mengambil ffmpeg.fly.dev lebih dulu
    • Saya penasaran, secara mendasar apa bedanya ini dengan cara Sidekiq menginstansiasi codebase Rails untuk menjalankan pekerjaan latar belakang
  • Bagian “bayangkan cukup membungkus bagian mana pun dari kode aplikasi yang ada dengan sebuah fungsi, lalu otomatis diskalakan, dan blok kode itu berjalan di salinan sementara aplikasi” menarik
    Kedengarannya seperti membuat apa yang dilakukan fork untuk serverless. Kerja yang luar biasa

  • Beberapa tahun lalu saya pernah memakai layanan yang pada dasarnya melakukan hal seperti ini. PiCloud sayangnya diakuisisi/ditelan oleh Dropbox, tetapi sebelumnya ia punya model persis seperti ini: pekerjaan disebar secara transparan ke worker. Caranya adalah membundel kode lalu menjalankannya di worker
    Contohnya ada di sini. Bisa dilihat bahwa modelnya persis sama: https://github.com/picloud/basic-examples/blob/master/exampl...
    Saya belum pernah memakai Elixir, tetapi pernah memakai Erlang beberapa dekade lalu, dan BEAM tampaknya secara fundamental tidak banyak berubah. Karena ini bagian inti dari desainnya, sepertinya jauh lebih cocok untuk pekerjaan seperti ini. Meski begitu, tetap tidak sepenuhnya gratis; saat menunggu, proses utama bisa saja mati, bukan?

  • Saya setuju dengan keseluruhan argumennya. Di https://www.windmill.dev kami mengambil pendekatan berbeda: unit abstraksinya kami lihat di level source code, bukan level kontainer
    Kami mem-parse fungsi main dan import untuk mengekstrak argumen serta dependensi, lalu menjalankan kode apa adanya di runtime yang diinginkan (TypeScript, Python, Go, Bash). Trik utamanya adalah mengelola cache secara efisien agar worker selalu tetap hangat, terlepas dari import
    Cara ini tidak terintegrasi ke codebase sedalam FLAME, tetapi pengguna sasarannya berbeda. Pengguna kami membuat workflow kompleks, cron job, atau skrip sekali pakai dengan UI yang dibuat otomatis, dari nol
    Di FLAME, tampaknya seluruh konteks di-snapshot lalu dipulihkan kembali di VM target. Pendekatan lain adalah memperkenalkan sintaks untuk menentukan konteks mana yang diperlukan dan mana yang tidak, sehingga hanya memuat yang minimum. Saat ini kami sedang mengeksplorasinya agar Windmill bisa lebih terintegrasi dengan codebase yang ada dan tidak bergantung pada panggilan HTTP

    • Yang sebenarnya terjadi di FLAME tidak persis begitu. FLAME hanya memanggil fungsi di node jarak jauh menggunakan fitur clustering bawaan BEAM
      Dalam proses itu, pengiriman hanya konteks yang diperlukan ditangani secara implisit. Artikel juga menjelaskannya seperti ini: “FLAME.call menerima nama pool runner dan sebuah fungsi. Lalu ia mencari atau mem-boot salinan baru dari seluruh aplikasi, dan menjalankan fungsi tersebut di sana. Variabel yang ditangkap fungsi sebagai closure, misalnya struct %Video{} dan interval, otomatis ikut dikirim”
    • Ada satu w tambahan. Untuk yang mencarinya, URL-nya ada di sini: https://www.windmill.dev/
      Saya suka tujuan proyeknya. Saya sungguh berharap Windmill menjadi alternatif open-source Retool/Airtable yang lebih baik
  • Saya suka bagian bahwa “di FLAME, runner untuk pengembangan dan pengujian cukup berjalan di backend lokal.” Serverless dengan pengalaman pengembangan lokal yang layak, bagus juga

    • Benar. Salah satu alasan saya tidak suka serverless adalah karena pengalaman pengembangan lokal jauh lebih buruk dibanding menjalankan monolith
  • Kalau “lalu ia mencari atau mem-boot salinan baru dari seluruh aplikasi dan fungsi itu dijalankan di sana”, apakah setiap Flame.call memulai ulang seluruh proses aplikasi dan menyalin masuk konteks eksekusi?
    Dari sisi skalabilitas ini solusi yang sangat sederhana, tetapi rasanya ada kekurangannya juga
    Jika waktu startup aplikasi bertambah 10 ms, berarti 10 ms ditambahkan ke setiap titik Flame.call dalam aplikasi, dan mungkin memori juga begitu
    Sepertinya kekhawatiran seperti ini perlu dipertimbangkan saat memakai sistem ini

    • FLAME.Pool di bagian akhir artikel membahas hal ini. Runner dipool, tetap dipertahankan dalam kondisi hangat selama waktu yang bisa dikonfigurasi, lalu diturunkan saat idle
      Dalam kondisi berbeban, pool sudah hangat sehingga hampir tidak membayar biaya cold start. Berikutnya, teknik pertumbuhan pool yang lebih canggih juga sedang ditambahkan ke library Elixir, sehingga situasi bertemu runner yang penuh lalu harus cold start baru juga bisa dihindari
      Pada runner yang hangat, overhead-nya hanya latensi antara parent dan child. Karena harus berada di data center yang sama, mestinya 1 ms atau kurang
  • Bagus sekali. Ini terasa seperti versi khusus Elixir yang sangat ringan dari apa yang kami buat di https://www.inngest.com/
    Keduanya mirip dalam hal membungkus kode yang ada dengan sesuatu agar bisa dipakai sebagai fungsi serverless, dan pada dasarnya bisa dipanggil sebagai RPC jarak jauh
    Kode seperti ini sering dieksekusi sebagai rangkaian langkah imperatif. Setiap langkah bisa dijalankan secara serial atau paralel sebagai Lambda tambahan. Namun ada state implisit yang tertangkap dalam variabel di antara langkah-langkah tersebut. Karena itu, fungsi tersebut menjadi workflow. Dalam model Inngest, state ini ditangkap dan disuntikkan kembali ke fungsi agar memiliki durabilitas
    Dari sisi durabilitas, proses seperti ini harus berbasis queue. Hal bagus dari model ini adalah queue itu murah. Jika queue dibuat semurah satu baris kode, semuanya jadi mudah. Developer mana pun bisa menulis kode yang andal tanpa mengkhawatirkan infrastruktur
    Monitoring dan observability juga penting. Dead letter queue benar-benar menyebalkan, dan kita harus bisa mengelola serta menjalankan ulang fungsi atau langkah yang gagal
    Ada juga perbedaan antara FLAME dan Inngest. Inngest berbasis queue, event-driven, dan bisa disediakan lewat HTTP dari bahasa apa pun. Karena Inngest menyimpan state secara eksternal, jika Anda menulis workflow dalam Elixir lalu menulis ulang dalam TypeScript dan melakukan redeploy, fungsi yang sedang berjalan bisa dimigrasikan secara live lintas bahasa backend, mirip CRIU
    Dengan pendekatan event-driven, flow control juga bisa dilakukan. Debounce, batching, throttling, hingga fan-out bisa ditangani di runtime atau bahasa apa pun. Misalnya, satu aplikasi Elixir di atas Fly bisa mengirim event untuk menjalankan fungsi di TypeScript + Lambda
    Saya menantikan ke mana FLAME akan berkembang. Saya melihat ada sebagian tujuan yang mirip

    • Inngest terlihat seperti layanan yang keren. Artikel juga membahas pemroses pekerjaan, durabilitas, dan retry
      Di Elixir, ketika membutuhkan durabilitas, retry, dan workflow, biasanya kami memakai Oban, dan di sini pun akan tetap begitu. Job Oban akan memanggil FLAME agar menangani eksekusi yang elastis
  • Ini salah satu alasan saya sangat tidak suka penulisan kapitalisasi judul ala Amerika yang dipaksakan HN. Serverless terlihat seperti berarti memikirkan ulang perusahaan serverless.com dengan huruf S kapital, bukan memikirkan ulang prinsip serverless dengan huruf s kecil
    Sebagai tambahan, saya berharap ada seseorang yang memikirkan ulang Serverless

    • Sepertinya kapitalisasi bukan dipaksakan HN, melainkan ditentukan oleh orang yang mengunggah tulisan
      Saya tidak tahu apakah Anda sudah melihat https://sst.dev/, tetapi sepertinya mereka melakukan persis hal itu. Misalnya, ada Live Lambda Development, sehingga pengembangan lokal menjadi sangat mudah dengan memangkas banyak feedback loop tanpa perlu mengunggah kode ke cloud dan menunggu deployment
  • Idenya cukup keren dan API-nya juga bagus
    Untuk bagian “pekerjaan CPU-bound seperti transcoding video dapat dengan cepat menghentikan seluruh layanan di produksi”, bukankah cukup melakukan autoscaling berbasis CPU saja?

    • Saya mencoba membahas pemikiran ini di bagian awal tulisan. Masalah dengan pendekatan seperti itu adalah ia melakukan scaling pada tingkat operasional yang salah
      Untuk menangani pekerjaan tertentu yang panas, Anda akhirnya menskalakan seluruh aplikasi termasuk web server. Yang kita inginkan, dan alasan kita mencari FaaS, adalah scaling elastis yang granular. Ide di sini adalah memungkinkan scaling granular semacam itu untuk kode aplikasi yang sudah ada, alih-alih terus menekan tombol scale pada web server atau worker dan berharap semuanya berjalan baik
    • Bisa ya, bisa juga tidak. Sisa workload mungkin tidak membutuhkan banyak CPU. Bisa jadi hanya satu atau dua workload yang membutuhkan performa seperti ini, dan Anda ingin memastikan pekerjaan itu tidak tersisih oleh hal lain
      Atau mungkin juga membutuhkan GPU
      Layanan inti mungkin cukup dengan 1–2 server, tetapi untuk pekerjaan yang terjadi kira-kira sekali sehari, saat diperlukan Anda mungkin harus melakukan scaling ke puluhan, ratusan, atau ribuan server