Terjemahan dan penyesuaian Java Microservices: A Practical Guide . Bahagian panduan sebelumnya:
Mari kita lihat masalah yang wujud dalam perkhidmatan mikro di Jawa, bermula dengan perkara abstrak dan berakhir dengan perpustakaan konkrit.
Bagaimana untuk menjadikan perkhidmatan mikro Java berdaya tahan?
Ingat bahawa apabila anda mencipta perkhidmatan mikro, anda pada asasnya memperdagangkan panggilan kaedah JVM untuk panggilan HTTP segerak atau pemesejan tak segerak. Walaupun panggilan kaedah kebanyakannya dijamin untuk diselesaikan (kecuali penutupan JVM yang tidak dijangka), panggilan rangkaian tidak boleh dipercayai secara lalai. Ia mungkin berfungsi, tetapi ia mungkin tidak berfungsi atas pelbagai sebab: rangkaian terlampau beban, peraturan tembok api baharu telah dilaksanakan, dan sebagainya. Untuk melihat cara ini membuat perubahan, mari lihat contoh BillingService.Corak Ketahanan HTTP/REST
Katakan pelanggan boleh membeli e-buku di tapak web syarikat anda. Untuk melakukan ini, anda baru sahaja melaksanakan perkhidmatan mikro pengebilan yang boleh menghubungi kedai dalam talian anda untuk menjana invois PDF sebenar. Buat masa ini, kami akan membuat panggilan ini secara serentak, melalui HTTP (walaupun lebih masuk akal untuk memanggil perkhidmatan ini secara tidak segerak, kerana penjanaan PDF tidak perlu serta-merta dari perspektif pengguna. Kami akan menggunakan contoh yang sama dalam seterusnya bahagian dan lihat perbezaannya).@Service
class BillingService {
@Autowired
private HttpClient client;
public void bill(User user, Plan plan) {
Invoice invoice = createInvoice(user, plan);
httpClient.send(invoiceRequest(user.getEmail(), invoice), responseHandler());
// ...
}
}
Untuk meringkaskan, berikut ialah tiga kemungkinan hasil panggilan HTTP ini.
- OK: panggilan dibuat, akaun berjaya dibuat.
- KELEWATAN: Panggilan telah diteruskan, tetapi ia mengambil masa terlalu lama untuk diselesaikan.
- RALAT. Panggilan gagal, anda mungkin telah menghantar permintaan yang tidak serasi, atau sistem mungkin tidak berfungsi.
Corak Ketahanan Pemesejan
Mari kita lihat lebih dekat pada komunikasi tak segerak. Program BillingService kami kini mungkin kelihatan seperti ini, dengan andaian kami menggunakan Spring dan RabbitMQ untuk pemesejan. Untuk membuat akaun, kami kini menghantar mesej kepada broker mesej RabbitMQ kami, di mana terdapat beberapa pekerja menunggu mesej baharu. Pekerja ini membuat invois PDF dan menghantarnya kepada pengguna yang sesuai.@Service
class BillingService {
@Autowired
private RabbitTemplate rabbitTemplate;
public void bill(User user, Plan plan) {
Invoice invoice = createInvoice(user, plan);
// преобразует счет, например, в json и использует его How тело messages
rabbitTemplate.convertAndSend(exchange, routingkey, invoice);
// ...
}
}
Ralat berpotensi kelihatan sedikit berbeza sekarang, kerana anda tidak lagi menerima jawapan OK atau ERROR serta-merta seperti yang anda lakukan dengan sambungan HTTP segerak. Sebaliknya, kami mungkin mempunyai tiga kemungkinan senario yang boleh menjadi salah, yang boleh menimbulkan soalan berikut:
- Adakah mesej saya dihantar dan digunakan oleh pekerja? Atau adakah ia hilang? (Pengguna tidak menerima invois).
- Adakah mesej saya hanya dihantar sekali? Atau dihantar lebih daripada sekali dan diproses sekali sahaja? (Pengguna akan menerima berbilang invois).
- Konfigurasi: Daripada "Adakah saya menggunakan kekunci/nama penghalaan yang betul untuk pertukaran" kepada "Adakah broker mesej saya dikonfigurasikan dan diselenggara dengan betul atau adakah baris gilirnya penuh?" (Pengguna tidak menerima invois).
- Jika anda menggunakan pelaksanaan JMS seperti ActiveMQ, anda boleh menukar kelajuan untuk jaminan komitmen dua fasa (XA).
- Jika anda menggunakan RabbitMQ, baca tutorial ini dahulu, dan kemudian fikirkan dengan teliti tentang pengesahan, toleransi kesalahan dan kebolehpercayaan mesej secara umum.
- Mungkin seseorang mahir dalam mengkonfigurasi pelayan Aktif atau RabbitMQ, terutamanya dalam kombinasi dengan pengelompokan dan Docker (sesiapa sahaja? ;))
Rangka kerja manakah yang akan menjadi penyelesaian terbaik untuk perkhidmatan mikro Java?
Di satu pihak, anda boleh memasang pilihan yang sangat popular seperti Spring Boot . Ia menjadikannya sangat mudah untuk mencipta fail .jar, dilengkapi dengan pelayan web terbina dalam seperti Tomcat atau Jetty, dan boleh dijalankan dengan cepat dan di mana-mana sahaja. Ideal untuk membina aplikasi perkhidmatan mikro. Baru-baru ini, beberapa rangka kerja perkhidmatan mikro khusus, Kubernetes atau GraalVM , muncul, sebahagiannya diilhamkan oleh pengaturcaraan reaktif. Berikut ialah beberapa lagi pesaing yang menarik: Quarkus , Micronaut , Vert.x , Helidon . Pada akhirnya, anda perlu memilih sendiri, tetapi kami boleh memberikan anda beberapa cadangan yang mungkin tidak sepenuhnya standard: Dengan pengecualian Spring Boot, semua rangka kerja perkhidmatan mikro biasanya dipasarkan dengan sangat pantas, dengan permulaan yang hampir serta-merta , penggunaan memori yang rendah, kebolehskalaan kepada infiniti. Bahan pemasaran biasanya menampilkan grafik yang mengagumkan yang mempamerkan platform bersebelahan dengan Spring Boot raksasa atau antara satu sama lain. Ini, secara teorinya, melepaskan kegelisahan pembangun yang menyokong projek warisan, yang kadangkala mengambil masa beberapa minit untuk dimuatkan. Atau pembangun yang bekerja di awan yang ingin memulakan/menghentikan seberapa banyak bekas mikro yang mereka perlukan dalam masa 50 ms. Masalahnya, bagaimanapun, ialah masa permulaan logam kosong (tiruan) ini dan masa penempatan semula hampir tidak menyumbang kepada kejayaan keseluruhan projek. Sekurang-kurangnya mereka mempengaruhi kurang daripada infrastruktur rangka kerja yang kukuh, dokumentasi yang kukuh, komuniti dan kemahiran pembangun yang kukuh. Jadi lebih baik untuk melihatnya dengan cara ini: Jika setakat ini:- Anda membiarkan ORM anda berleluasa, menghasilkan ratusan pertanyaan untuk aliran kerja mudah.
- Anda memerlukan gigabait yang tidak berkesudahan untuk menjalankan monolit sederhana kompleks anda.
- Anda mempunyai begitu banyak kod dan kerumitannya sangat tinggi (kami tidak bercakap tentang permulaan yang berpotensi perlahan seperti Hibernate sekarang) sehingga aplikasi anda mengambil masa beberapa minit untuk dimuatkan.
Perpustakaan manakah yang terbaik untuk panggilan Java REST segerak?
Dari segi teknikal peringkat rendah, anda mungkin akan mendapat salah satu daripada perpustakaan klien HTTP berikut: HttpClient asli Java (sejak Java 11), HttpClient Apache atau OkHttp . Ambil perhatian bahawa saya menyebut "mungkin" di sini kerana terdapat pilihan lain, daripada pelanggan JAX-RS lama yang baik kepada pelanggan WebSocket moden . Walau apa pun, trendnya adalah ke arah menjana klien HTTP, menjauhkan diri daripada bermain-main dengan panggilan HTTP sendiri. Untuk melakukan ini, anda perlu melihat projek OpenFeign dan dokumentasinya sebagai titik permulaan untuk bacaan selanjutnya.Apakah broker terbaik untuk pemesejan Java tak segerak?
Kemungkinan besar, anda akan menemui ActiveMQ (Classic atau Artemis) yang popular , RabbitMQ atau Kafka .- ActiveMQ dan RabbitMQ ialah broker mesej tradisional yang lengkap. Mereka melibatkan interaksi "broker pintar" dan "pengguna bodoh".
- Dari segi sejarah, ActiveMQ telah mendapat manfaat sebaris mudah (untuk ujian), yang boleh dikurangkan dengan tetapan RabbitMQ/Docker/TestContainer.
- Kafka tidak boleh dipanggil broker tradisional "pintar". Sebaliknya, ia adalah kedai mesej (fail log) yang agak "bodoh" yang memerlukan pengguna pintar untuk memproses.
Apakah perpustakaan yang boleh saya gunakan untuk menguji perkhidmatan mikro?
Ia bergantung pada timbunan anda. Jika anda mempunyai ekosistem Spring digunakan, adalah bijak untuk menggunakan alatan khusus rangka kerja . Jika JavaEE adalah seperti Arquillian . Mungkin berbaloi untuk melihat Docker dan pustaka Testcontainers yang sangat bagus , yang membantu khususnya untuk menyediakan pangkalan data Oracle dengan mudah dan cepat untuk pembangunan tempatan atau ujian integrasi. Untuk menguji olok-olok seluruh pelayan HTTP, lihat Wiremock . Untuk menguji pemesejan tak segerak, cuba laksanakan ActiveMQ atau RabbitMQ dan kemudian tulis ujian menggunakan Awaitility DSL . Selain itu, semua alatan biasa anda digunakan - Junit , TestNG untuk AssertJ dan Mockito . Sila ambil perhatian bahawa ini bukan senarai lengkap. Jika anda tidak menemui alat kegemaran anda di sini, sila siarkan di bahagian komen.Bagaimana untuk membolehkan pengelogan untuk semua perkhidmatan mikro Java?
Log masuk kes perkhidmatan mikro adalah topik yang menarik dan agak rumit. Daripada mempunyai satu fail log yang anda boleh manipulasi dengan arahan yang kurang atau grep, anda kini mempunyai n fail log, dan anda mahu mereka tidak terlalu berselerak. Ciri-ciri ekosistem pembalakan diterangkan dengan baik dalam artikel ini (dalam bahasa Inggeris). Pastikan anda membacanya dan perhatikan bahagian Pengelogan berpusat dari perspektif perkhidmatan mikro . Dalam amalan, anda akan menemui pendekatan yang berbeza: Pentadbir sistem menulis skrip tertentu yang mengumpul dan menggabungkan fail log daripada pelayan berbeza ke dalam satu fail log dan meletakkannya pada pelayan FTP untuk dimuat turun. Menjalankan kombinasi kucing/grep/unig/isih dalam sesi SSH selari. Inilah yang dilakukan oleh Amazon AWS, dan anda boleh memberitahu pengurus anda. Gunakan alat seperti Graylog atau ELK Stack (Elasticsearch, Logstash, Kibana)Bagaimanakah perkhidmatan mikro saya mencari antara satu sama lain?
Sehingga kini, kami menganggap bahawa perkhidmatan mikro kami tahu tentang satu sama lain dan mengetahui IPS yang sepadan. Mari kita bercakap tentang konfigurasi statik. Jadi, monolit perbankan kami [ip = 192.168.200.1] tahu bahawa ia perlu bercakap dengan pelayan risiko [ip = 192.168.200.2], yang dikodkan keras dalam fail sifat. Walau bagaimanapun, anda boleh menjadikan perkara lebih dinamik:- Gunakan pelayan konfigurasi berasaskan awan dari mana semua perkhidmatan mikro menarik konfigurasi mereka dan bukannya menggunakan fail application.properties pada perkhidmatan mikro mereka.
- Memandangkan tika perkhidmatan anda boleh menukar lokasinya secara dinamik, adalah wajar melihat perkhidmatan yang mengetahui tempat perkhidmatan anda berada, IP mereka dan cara menghalakannya.
- Sekarang segala-galanya dinamik, masalah baru timbul, seperti pemilihan pemimpin secara automatik: siapakah tuan yang mengerjakan tugas tertentu supaya tidak memprosesnya dua kali, misalnya? Siapa yang menggantikan pemimpin apabila dia gagal? Atas dasar apakah penggantian berlaku?
Bagaimana untuk mengatur kebenaran dan pengesahan menggunakan perkhidmatan mikro Java?
Topik ini juga layak untuk cerita yang berasingan. Sekali lagi, pilihan terdiri daripada pengesahan HTTPS asas berkod keras dengan rangka kerja keselamatan tersuai kepada menjalankan pemasangan Oauth2 dengan pelayan kebenarannya sendiri.Bagaimanakah saya boleh memastikan bahawa semua persekitaran saya kelihatan sama?
Perkara yang benar untuk penempatan tanpa perkhidmatan mikro juga benar untuk penggunaan dengan satu. Cuba gabungan Docker/Testcontainers dan Scripting/Ansible.Tiada soalan: secara ringkas tentang YAML
Mari kita menjauhkan diri dari perpustakaan dan isu-isu yang berkaitan untuk seketika dan lihat sebentar di Yaml. Format fail ini digunakan secara de facto sebagai format untuk "konfigurasi penulisan sebagai kod." Ia juga digunakan oleh alat mudah seperti Ansible dan gergasi seperti Kubernetes. Untuk mengalami kesakitan lekukan YAML, cuba tulis fail Ansible yang mudah dan lihat berapa banyak anda perlu mengedit fail sebelum ia berfungsi seperti yang diharapkan. Dan ini walaupun formatnya disokong oleh semua IDE utama! Selepas itu, kembali untuk menghabiskan membaca panduan ini.Yaml:
- is:
- so
- great
Bagaimana pula dengan transaksi yang diedarkan? Ujian prestasi? Topik lain?
Mungkin suatu hari nanti, dalam edisi manual yang akan datang. Buat masa ini, itu sahaja. Kekal bersama kami!Isu Konseptual dengan Microservices
Selain masalah khusus perkhidmatan mikro di Jawa, terdapat masalah lain, katakan, masalah yang muncul dalam mana-mana projek perkhidmatan mikro. Mereka berkaitan kebanyakannya dengan organisasi, pasukan dan pengurusan.Bahagian hadapan dan bahagian belakang tidak sepadan
Ketakpadanan Frontend dan Backend ialah masalah yang sangat biasa dalam banyak projek perkhidmatan mikro. Apakah maksudnya? Hanya itu dalam monolit lama yang baik, pembangun antara muka web mempunyai satu sumber khusus untuk mendapatkan data. Dalam projek perkhidmatan mikro, pembangun bahagian hadapan tiba-tiba mempunyai n sumber untuk mendapatkan data daripadanya. Bayangkan anda sedang mencipta beberapa jenis projek perkhidmatan mikro IoT (Internet of Things) di Jawa. Katakan anda menguruskan mesin geodetik dan relau industri di seluruh Eropah. Dan ketuhar ini menghantar anda kemas kini tetap dengan suhunya dan seumpamanya. Lambat laun anda mungkin mahu mencari ketuhar dalam UI pentadbir, mungkin menggunakan perkhidmatan mikro "carian relau". Bergantung pada sejauh mana ketat rakan sejawat belakang anda menggunakan reka bentuk dipacu domain atau undang-undang perkhidmatan mikro, perkhidmatan mikro "cari ketuhar" hanya boleh mengembalikan ID ketuhar dan bukan data lain seperti jenis, model atau lokasi. Untuk melakukan ini, pembangun bahagian hadapan perlu membuat satu atau n panggilan tambahan (bergantung pada pelaksanaan halaman) dalam perkhidmatan mikro "dapatkan data relau" dengan ID yang mereka terima daripada perkhidmatan mikro pertama. Dan walaupun ini hanyalah contoh mudah, walaupun diambil dari projek sebenar (!), malah ia menunjukkan masalah berikut: pasar raya telah menjadi sangat popular. Itu kerana dengan mereka anda tidak perlu pergi ke 10 tempat berbeza untuk membeli sayur-sayuran, air limau, piza beku dan kertas tandas. Sebaliknya, anda pergi ke satu tempat. Ia lebih mudah dan cepat. Perkara yang sama berlaku untuk pembangun bahagian hadapan dan perkhidmatan mikro.Jangkaan Pengurusan
Pengurusan berada di bawah tanggapan yang silap bahawa mereka kini perlu mengupah pembangun yang tidak terhingga untuk projek (menyeluruh), kerana pembangun kini boleh bekerja sepenuhnya secara bebas antara satu sama lain, masing-masing menggunakan perkhidmatan mikro mereka sendiri. Hanya sedikit kerja penyepaduan diperlukan pada penghujung (sejurus sebelum pelancaran). Malah, pendekatan ini sangat bermasalah. Dalam perenggan berikut kami akan cuba menerangkan sebabnya."Kepingan yang lebih kecil" tidak sama dengan "kepingan yang lebih baik"
Adalah satu kesilapan besar untuk menganggap bahawa kod yang dibahagikan kepada 20 bahagian semestinya mempunyai kualiti yang lebih tinggi daripada satu bahagian keseluruhan. Walaupun kami mengambil kualiti dari sudut teknikal semata-mata, perkhidmatan individu kami mungkin masih menjalankan 400 pertanyaan Hibernate untuk memilih pengguna daripada pangkalan data, merentasi lapisan kod yang tidak disokong. Sekali lagi, kami kembali kepada petikan Simon Brown: jika anda gagal membina monolit dengan betul, sukar untuk membina perkhidmatan mikro yang betul. Selalunya terlalu lewat untuk bercakap tentang toleransi kesalahan dalam projek perkhidmatan mikro. Sehingga kadangkala menakutkan untuk melihat cara perkhidmatan mikro berfungsi dalam projek sebenar. Sebabnya ialah pembangun Java tidak sentiasa bersedia untuk mengkaji toleransi kesalahan, rangkaian dan topik berkaitan lain pada tahap yang sepatutnya. "Kepingan" itu sendiri lebih kecil, tetapi "bahagian teknikal" lebih besar. Bayangkan pasukan perkhidmatan mikro anda diminta untuk menulis perkhidmatan mikro teknikal untuk log masuk ke sistem pangkalan data, seperti ini:@Controller
class LoginController {
// ...
@PostMapping("/login")
public boolean login(String username, String password) {
User user = userDao.findByUserName(username);
if (user == null) {
// обработка варианта с несуществующим пользователем
return false;
}
if (!user.getPassword().equals(hashed(password))) {
// обработка неверного пароля
return false;
}
// 'Ю-ху, залогинorсь!';
// установите cookies, делайте, что угодно
return true;
}
}
Kini pasukan anda mungkin memutuskan (dan mungkin juga meyakinkan ahli perniagaan) bahawa ini terlalu mudah dan membosankan, daripada menulis perkhidmatan log masuk, adalah lebih baik untuk menulis perkhidmatan mikro UserStateChanged yang benar-benar berguna tanpa sebarang implikasi perniagaan yang nyata dan ketara. Dan memandangkan sesetengah orang pada masa ini menganggap Java seperti dinosaur, mari tulis perkhidmatan mikro UserStateChanged kami dalam Erlang yang bergaya. Dan mari cuba gunakan pokok merah-hitam di suatu tempat, kerana Steve Yegge menulis bahawa anda perlu mengenalinya dari dalam untuk memohon kepada Google. Dari perspektif penyepaduan, penyelenggaraan dan reka bentuk keseluruhan, ini sama buruknya dengan menulis lapisan kod spageti dalam satu monolit. Contoh tiruan dan biasa? Ini adalah benar. Walau bagaimanapun, ini boleh berlaku dalam realiti.
Lebih sedikit kepingan - kurang pemahaman
Kemudian persoalan timbul secara semula jadi tentang memahami sistem secara keseluruhan, proses dan aliran kerjanya, tetapi pada masa yang sama anda, sebagai pembangun, hanya bertanggungjawab untuk mengusahakan perkhidmatan mikro terpencil anda [95: login-101: updateUserProfile]. Ia selaras dengan perenggan sebelumnya, tetapi bergantung pada organisasi anda, tahap kepercayaan dan komunikasi, ini boleh membawa kepada banyak kekeliruan, mengangkat bahu dan menyalahkan jika terdapat kerosakan yang tidak disengajakan dalam rantaian perkhidmatan mikro. Dan tidak ada sesiapa yang akan bertanggungjawab sepenuhnya atas apa yang berlaku. Dan ia bukan soal ketidakjujuran. Malah, sangat sukar untuk menyambung bahagian yang berbeza dan memahami tempatnya dalam gambaran keseluruhan projek.Komunikasi dan perkhidmatan
Tahap komunikasi dan perkhidmatan sangat bergantung pada saiz syarikat. Walau bagaimanapun, hubungan umum adalah jelas: semakin banyak, semakin bermasalah.- Siapa yang menjalankan perkhidmatan mikro #47?
- Adakah mereka hanya menggunakan versi perkhidmatan mikro yang baharu dan tidak serasi? Di manakah ini didokumenkan?
- Dengan siapa saya perlu bercakap untuk meminta ciri baharu?
- Siapa yang akan menyokong perkhidmatan mikro itu di Erlang, selepas satu-satunya yang tahu bahasa ini meninggalkan syarikat itu?
- Semua pasukan perkhidmatan mikro kami bekerja bukan sahaja dalam bahasa pengaturcaraan yang berbeza, tetapi juga dalam zon waktu yang berbeza! Bagaimanakah kita menyelaraskan semua ini dengan betul?
GO TO FULL VERSION