BerandaComputers and TechnologyMasalah Makro dengan Layanan Mikro

Masalah Makro dengan Layanan Mikro

Hanya dalam 20 tahun, rekayasa perangkat lunak telah bergeser dari membuat monolit dengan database tunggal dan status terpusat ke layanan mikro di mana semuanya didistribusikan ke berbagai kontainer, server, pusat data, dan bahkan benua. Arsitektur terdistribusi telah memungkinkan pengembang untuk mengukur dan memenuhi kebutuhan dunia yang semakin terhubung. Mendistribusikan berbagai hal juga memperkenalkan dunia masalah yang sama sekali baru, yang banyak di antaranya sebelumnya diselesaikan dengan monolit.

Dalam artikel ini, saya akan membahas bagaimana kita mencapai titik ini dengan berjalan kaki singkat melalui sejarah aplikasi jaringan. Setelah itu, kita akan berbicara tentang model eksekusi stateful Temporal dan bagaimana mencoba untuk memecahkan masalah yang diperkenalkan oleh arsitektur berorientasi layanan (SOA). Dalam keterbukaan penuh, saya adalah Kepala Produk untuk Sementara, jadi saya mungkin bias, tapi saya pikir pendekatan ini adalah masa depan.

Pelajaran sejarah singkat

Dua puluh tahun lalu, pengembang hampir selalu membuat aplikasi monolitik. Modelnya sederhana, konsisten, dan mirip dengan pengalaman yang Anda dapatkan dalam pemrograman di lingkungan lokal.

Monolit pada dasarnya bergantung pada database tunggal, yang berarti semua negara bagian terpusat. Monolit dapat mengubah statusnya dalam satu transaksi, yang berarti ia menghasilkan hasil biner — berhasil atau tidak. Tidak ada ruang untuk ketidakkonsistenan. Oleh karena itu, monolit memberikan pengalaman yang luar biasa bagi pengembang karena artinya tidak ada kemungkinan transaksi yang gagal yang mengakibatkan status yang tidak konsisten. Pada gilirannya, ini berarti pengembang tidak perlu terus-menerus menulis kode untuk menebak keadaan.

Untuk waktu yang lama, monolit masuk akal. Tidak ada banyak pengguna yang terhubung, yang berarti persyaratan skala untuk software sangat minim. Bahkan raksasa perangkat lunak terbesar pun beroperasi pada skala yang tampaknya sangat kecil hari ini. Ada beberapa perusahaan seperti Amazon dan Google yang berjalan pada “skala”, tetapi mereka adalah pengecualian yang jarang terjadi, bukan aturannya.

Orang-orang menyukai perangkat lunak

Selama 20 tahun terakhir, permintaan perangkat lunak tidak akan berhenti berkembang. Saat ini, aplikasi diharapkan dapat melayani pasar global sejak hari pertama. Perusahaan seperti Twitter dan Facebook telah membuat taruhan meja selalu online 24/7. Perangkat lunak tidak hanya memberdayakan hal-hal di balik layar lagi, itu menjadi pengalaman pengguna akhir itu sendiri. Setiap perusahaan sekarang diharapkan memiliki produk perangkat lunak. Keandalan dan ketersediaan bukan lagi fitur, mereka adalah persyaratan.

Sayangnya, monolit mulai rusak saat skala dan ketersediaan menjadi persyaratan. Pengembang dan bisnis perlu menemukan cara untuk mengikuti pertumbuhan global yang cepat dan menuntut ekspektasi pengguna. Mereka mulai mencari arsitektur alternatif yang akan meringankan masalah skalabilitas yang mereka alami.

Jawaban yang mereka temukan adalah layanan mikro (yah, arsitektur berorientasi layanan). Layanan mikro pada awalnya tampak hebat karena memungkinkan aplikasi untuk dipecah menjadi unit yang relatif mandiri yang dapat diskalakan secara independen. Dan karena setiap layanan mikro mempertahankan statusnya sendiri, itu berarti aplikasi Anda tidak lagi terbatas pada apa yang cocok di satu mesin! Pengembang akhirnya dapat membangun aplikasi yang memenuhi tuntutan skala dunia yang semakin terhubung. Layanan mikro juga memberikan fleksibilitas bagi tim dan perusahaan karena mereka memberikan garis tanggung jawab dan pemisahan yang jelas untuk arsitektur organisasi.

Tidak ada yang namanya makan siang gratis

Meskipun layanan mikro memecahkan masalah skalabilitas dan ketersediaan yang secara fundamental memblokir pertumbuhan perangkat lunak, tidak semuanya berjalan baik. Pengembang mulai menyadari bahwa layanan mikro memiliki beberapa kekurangan yang serius.

Dengan monolith, biasanya ada satu instance database dan satu server aplikasi. Dan karena monolit tidak dapat dipecah, hanya ada dua opsi praktis untuk penskalaan. Opsi pertama adalah penskalaan vertikal yang berarti mengupgrade perangkat keras untuk meningkatkan throughput / kapasitas. Penskalaan vertikal dapat menjadi efisien tetapi mahal dan jelas bukan solusi permanen jika kebutuhan aplikasi Anda terus berkembang. Jika skala Anda cukup vertikal, Anda akhirnya akan kehabisan perangkat keras untuk meningkatkan. Opsi kedua adalah penskalaan horizontal, yang dalam kasus monolit berarti hanya membuat salinannya sendiri sehingga masing-masing melayani sekumpulan pengguna / permintaan tertentu, dll. Penskalaan horizontal menghasilkan penggunaan sumber daya yang kurang dan pada skala yang cukup tinggi, cukup jelas tidak kerja. Ini tidak terjadi pada layanan mikro, yang nilainya berasal dari kemampuan untuk memiliki beberapa “jenis” database, antrian, dan server lain yang diskalakan dan dioperasikan secara independen. Tetapi masalah pertama yang diperhatikan orang ketika mereka beralih ke layanan mikro adalah bahwa mereka tiba-tiba menjadi bertanggung jawab atas banyak jenis server dan database yang berbeda. Untuk waktu yang lama, aspek layanan mikro ini tidak ditangani dan pengembang serta operator dibiarkan menyelesaikannya sendiri. Memecahkan masalah manajemen infrastruktur yang menyertai layanan mikro itu sulit, yang membuat aplikasi tidak dapat diandalkan.

Permintaan adalah kendaraan utama perubahan. Karena adopsi layanan mikro meningkat pesat, pengembang menjadi semakin termotivasi untuk memecahkan masalah infrastruktur yang mendasarinya. Perlahan tapi pasti, solusi mulai bermunculan, dan teknologi seperti Docker, Kubernetes, dan AWS Lambda turun tangan untuk mengisi kekosongan. Masing-masing teknologi ini sangat mengurangi beban pengoperasian infrastruktur layanan mikro. Daripada harus menulis kode khusus yang menangani penampung dan sumber daya yang mengatur, pengembang dapat mengandalkan alat untuk melakukan pekerjaannya. Sekarang Di tahun 2020, kami akhirnya mencapai titik di mana ketersediaan infrastruktur kami tidak menyabot keandalan aplikasi kami. Kerja bagus!

Tentu saja, kami belum memasuki utopia perangkat lunak yang sangat stabil. Infrastruktur tidak lagi menjadi sumber aplikasi yang tidak dapat diandalkan; kode aplikasinya adalah.

Masalah lain dengan layanan mikro

Dengan monolit, pengembang menulis kode yang membuat perubahan berstatus biner. Sesuatu terjadi atau tidak. Dengan layanan mikro, keadaan dunia tersebar di berbagai server. Mengubah status aplikasi sekarang memerlukan pembaruan database yang berbeda secara bersamaan. Ini memperkenalkan kemungkinan bahwa satu DB akan berhasil diperbarui tetapi yang lain bisa turun, membuat Anda terjebak dalam keadaan tengah yang tidak konsisten. Tetapi karena layanan adalah satu-satunya jawaban untuk skalabilitas horizontal, pengembang tidak memiliki jalan lain untuk maju.

Masalah mendasar dengan status distribusi di seluruh layanan adalah bahwa setiap panggilan ke layanan eksternal adalah ketersediaan dadu. Pengembang tentu saja dapat memilih untuk mengabaikan masalah dalam kode mereka dan menganggap setiap ketergantungan eksternal yang mereka panggil akan selalu berhasil. Namun jika diabaikan, itu berarti salah satu dari dependensi down-stream tersebut dapat menghentikan aplikasi tanpa peringatan. Akibatnya, pengembang terpaksa mengadaptasi kode era monolit mereka yang ada untuk menambahkan cek yang menebak apakah operasi gagal di tengah transaksi. Pada kode di bawah ini, pengembang harus terus-menerus mengambil status terakhir yang direkam dari ad-hoc myDB untuk menghindari kemungkinan kondisi balapan. Sayangnya, meski dengan penerapan ini masih ada kondisi balapan. Jika status akun berubah tanpa juga memperbarui myDB , masih ada ruang untuk ketidakkonsistenan.

  public void transferWithoutTemporal (String fromId , String toId, String referenceId, double amount) {   boolean withdrawalDonePreviously=myDB.getWithdrawState (referenceId);   if (! withdrawDonePreviously) {       account.withdraw (fromAccountId, referenceId, jumlah); myDB.setWithdrawn (referenceId);   }   boolean depositDonePreviously=myDB.getDepositState (referenceId);   if (! depositDonePreviously) {       account.deposit (toAccountId, referenceId, jumlah); myDB.setDeposited (referenceId);   } }  

Sayangnya, tidak mungkin untuk menulis kode bebas bug, dan umumnya, semakin kompleks kodenya, semakin tinggi kemungkinan untuk bug. Seperti yang Anda duga, kode yang berhubungan dengan “tengah” tidak hanya rumit tetapi juga berbelit-belit. Beberapa keandalan lebih baik daripada tidak sama sekali, jadi pengembang dipaksa untuk menulis kode yang secara inheren bermasalah ini untuk mempertahankan pengalaman pengguna akhir. Hal ini menghabiskan waktu dan energi pengembang serta menghabiskan banyak uang bagi pemberi kerja. Meskipun layanan mikro sangat bagus untuk penskalaan, layanan mikro memiliki harga yang menguntungkan dan produktivitas bagi pengembang dan keandalan untuk aplikasi.

Jutaan pengembang membuang-buang waktu setiap hari untuk menemukan kembali salah satu roda yang paling diciptakan kembali, kode boilerplate keandalan. Pendekatan saat ini untuk bekerja dengan layanan mikro tidak mencerminkan persyaratan keandalan dan skalabilitas aplikasi modern.

Sementara

Jadi, sekarang tibalah bagian di mana kami menawarkan solusi kami kepada Anda. Untuk lebih jelasnya, ini tidak didukung oleh Stack Overflow. Dan kami belum mengatakan itu sempurna. Kami ingin berbagi ide dan mendengarkan pemikiran Anda. Tempat apa yang lebih baik untuk mendapatkan umpan balik tentang peningkatan kode selain Stack?

Hingga hari ini, tidak ada solusi yang memungkinkan pengembang menggunakan layanan mikro tanpa mengalami masalah yang saya jelaskan di atas. Anda dapat menguji dan mensimulasikan status kegagalan, menulis kode untuk mengantisipasi kerusakan, tetapi masalah ini akan tetap terjadi. Kami percaya Temporal memecahkan masalah ini. Temporal adalah open-source (MIT, no shenanigans), stateful, microservice orchestration runtime.

Temporal memiliki dua komponen utama: lapisan backend berstatus yang didukung oleh database pilihan Anda dan kerangka kerja sisi klien dalam salah satu bahasa yang didukung. Aplikasi dibuat menggunakan kerangka kerja sisi klien dan kode lama biasa yang secara otomatis mempertahankan perubahan status ke backend saat kode Anda berjalan. Anda bebas menggunakan dependensi, library, dan build chain yang sama dengan yang akan Anda andalkan saat membuat aplikasi lain. Untuk memperjelas, backend itu sendiri sangat terdistribusi jadi ini bukan situasi J2EE 2.0. Faktanya, sifat backend yang terdistribusi inilah yang memungkinkan penskalaan horizontal hampir tak terbatas. Temporal bertujuan untuk memberikan konsistensi, kesederhanaan, dan keandalan untuk lapisan aplikasi seperti yang dilakukan Docker Kubernetes dan tanpa server untuk infrastruktur.

Temporal menyediakan sejumlah mekanisme yang sangat andal untuk mengatur layanan mikro, tetapi yang paling penting adalah pelestarian status. Pelestarian negara adalah fitur Temporal yang menggunakan sumber acara untuk secara otomatis mempertahankan perubahan status apa pun dalam aplikasi yang sedang berjalan. Artinya, jika komputer yang menjalankan fungsi Alur kerja Temporal Anda mogok, kode tersebut akan dilanjutkan secara otomatis di komputer lain seperti kerusakan tidak pernah terjadi. Ini bahkan mencakup variabel lokal, utas, dan status khusus aplikasi lainnya. Cara terbaik untuk memahami cara kerja fitur ini adalah dengan analogi. Sebagai pengembang saat ini, Anda kemungkinan besar mengandalkan kontrol versi (Git) untuk melacak perubahan yang Anda buat pada kode Anda. Hal tentang Git, adalah bahwa ia tidak mengambil snapshot status komprehensif aplikasi Anda setelah setiap perubahan yang Anda buat. Git bekerja dengan hanya menyimpan hal-hal yang telah berubah dan kemudian memutar ulang perubahan tersebut dari awal untuk mencapai keadaan yang diinginkan. Temporal adalah semacam (lagi analogi kasar) seperti Git untuk riwayat stateful aplikasi yang sedang berjalan. Setiap kali kode Anda mengubah status aplikasi, Temporal secara otomatis menyimpan perubahan itu (bukan hasilnya) dengan cara yang toleran terhadap kesalahan. Ini berarti Temporal tidak hanya memulihkan aplikasi yang rusak, tetapi juga mengembalikannya, mencabangnya, dan banyak lagi. Hasilnya adalah developer tidak perlu lagi membangun aplikasi dengan asumsi server yang mendasarinya bisa gagal.

Sebagai pengembang, fitur ini seperti beralih dari menyimpan (ctrl-s) dokumen secara manual setelah setiap huruf yang Anda ketik ke penyimpanan otomatis di cloud dengan Google Dokumen. Bukan hanya karena Anda tidak lagi menyimpan secara manual, tidak ada lagi satu mesin yang terkait dengan dokumen itu. Pelestarian negara berarti pengembang menulis jauh lebih sedikit kode boilerplate yang membosankan yang pada awalnya diperkenalkan oleh layanan mikro. Ini juga berarti bahwa infrastruktur ad-hoc – seperti antrian mandiri, cache, dan database – tidak lagi diperlukan. Ini mengurangi beban operasi dan biaya tambahan untuk menambahkan fitur baru. Itu juga membuat orientasi karyawan baru jauh lebih mudah karena mereka tidak lagi perlu meningkatkan kode manajemen negara yang berantakan dan khusus domain.

Pengawetan status juga hadir dalam bentuk lain: “pengatur waktu yang tahan lama”. Timer tahan lama adalah mekanisme toleransi kesalahan yang dimanfaatkan pengembang melalui Workflow.sleep . Secara umum Workflow.sleep berfungsi persis seperti bahasa asli perintah tidur . Tetapi dengan Workflow.sleep Anda bisa tidur dengan aman untuk periode waktu apa pun, tidak peduli berapa lama. Ada banyak pengguna Temporal dengan alur kerja yang tidur selama berminggu-minggu atau bahkan bertahun-tahun. Untuk mencapai hal ini, layanan Temporal mempertahankan pengatur waktu yang tahan lama di datastore yang mendasarinya dan melacak saat kode yang sesuai perlu dilanjutkan. Sekali lagi, bahkan jika server yang mendasari crash (atau Anda baru saja mematikannya), kode akan dilanjutkan pada mesin yang tersedia saat pengatur waktu dimaksudkan untuk diaktifkan. Alur kerja tidur tidak menghabiskan sumber daya sehingga Anda dapat memiliki jutaan alur kerja tidur dengan overhead yang dapat diabaikan. Ini semua mungkin tampak sangat abstrak jadi berikut adalah contoh cara kerja kode Temporal:

  kelas publik SubscriptionWorkflowImpl mengimplementasikan SubscriptionWorkflow {   aktivitas SubscriptionActivities pribadi terakhir=      Workflow.newActivityStub (SubscriptionActivities.class);   public void mengeksekusi (String customerId) {     activities.onboardToFreeTrial (customerId);     coba {       Workflow.sleep (Duration.ofDays (180));       activities.upgradeFromTrialToPaid (customerId);       sementara (benar) {         Workflow.sleep (Duration.ofDays (30));         activities.chargeMonthlyFee (customerId);       }     } menangkap (CancellationException e) {       activities.processSubscriptionCancellation (customerId);     }   } }  

Di luar pelestarian negara, Temporal menawarkan serangkaian mekanisme untuk membangun aplikasi yang andal. Fungsi aktivitas dipanggil dari dalam alur kerja, tetapi kode yang berjalan di dalam aktivitas tidak stateful. Meskipun tidak stateful, Aktivitas dilengkapi dengan percobaan ulang otomatis, batas waktu, dan detak jantung. Aktivitas sangat berguna untuk mengenkapsulasi kode yang berpotensi gagal. Misalnya, aplikasi Anda bergantung pada API bank yang sering kali tidak tersedia. Dengan aplikasi tradisional, Anda perlu menggabungkan kode apa pun yang memanggil API bank dengan banyak pernyataan coba / tangkap, logika coba lagi, dan batas waktu. Tetapi jika Anda memanggil API bank dalam suatu aktivitas, semua hal ini disediakan di luar kotak, yang berarti jika panggilan gagal, aktivitas tersebut akan dicoba ulang secara otomatis. Percobaan ulang memang bagus, tetapi terkadang layanan yang tidak dapat diandalkan adalah layanan yang Anda miliki dan Anda lebih suka menghindari DDoSing. Karena alasan ini, panggilan aktivitas juga mendukung waktu tunggu, yang didukung oleh pengatur waktu yang tahan lama. Artinya, Anda dapat memiliki aktivitas menunggu berjam-jam, berhari-hari, atau berminggu-minggu di antara percobaan ulang. Ini sangat bagus terutama untuk kode yang Anda butuhkan untuk berhasil tetapi tidak peduli tentang seberapa cepat itu terjadi.

Teks : Video ini menjelaskan model pemrograman Temporal dalam 2 menit

Aspek lain yang kuat dari Temporal adalah visibilitas yang diberikannya ke dalam aplikasi yang sedang berjalan. API visibilitas menyediakan antarmuka seperti SQL untuk membuat kueri metadata dari alur kerja apa pun (berjalan atau sebaliknya). Dimungkinkan juga untuk menentukan dan memperbarui nilai metadata khusus langsung dari dalam alur kerja. API visibilitas sangat bagus untuk operator dan pengembang Temporal, terutama saat melakukan debug selama pengembangan. Visibilitas bahkan mendukung penerapan tindakan batch ke hasil kueri. Misalnya, Anda dapat mengirim sinyal penghentian ke semua alur kerja yang cocok dengan kueri Anda tentang waktu pembuatan> kemarin . Temporal juga mendukung fitur pengambilan sinkron yang memungkinkan pengembang untuk mengambil nilai variabel alur kerja lokal dalam menjalankan instance. Ini seperti jika debugger di IDE Anda berfungsi pada aplikasi produksi.

  kelas statis publik GreetingWorkflowImpl mengimplementasikan GreetingWorkflow {      salam string pribadi;      @Mengesampingkan     public void createGreeting (nama string) {       salam="Halo" + nama + "!";       Workflow.sleep (Duration.ofSeconds (2));       salam="Sampai jumpa" + nama + "!";     }      @Mengesampingkan     public String queryGreeting () {       salam balasan;     }   }  

Kesimpulan

Layanan mikro memang bagus, tetapi harga yang dibayar oleh pengembang dan bisnis dalam produktivitas dan keandalan untuk menggunakannya tidak. Temporal bertujuan untuk mengatasi masalah ini dengan menyediakan lingkungan yang membayar layanan mikro untuk pengembang. Pelestarian status, percobaan ulang otomatis panggilan yang gagal, dan visibilitas di luar kotak hanyalah beberapa hal penting yang disediakan Temporal untuk membuat layanan mikro berkembang menjadi wajar.

Tag: ,

Read More

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments