Kami menerapkan OSGI di platform Karaf

OSGI tidak sulit


Saya telah bertemu berkali-kali bahwa OSGI sulit. Dan terlebih lagi, dia sendiri pernah memiliki pendapat seperti itu. Tahun 2009, tepatnya. Pada saat itu, kami mengumpulkan proyek menggunakan Maven Tycho, dan menyebarkannya ke Equinox. Dan itu benar-benar lebih sulit daripada mengembangkan dan merakit proyek untuk JavaEE (pada saat itu versi EJB 3 baru saja muncul, yang kami beralih ke). Equinox jauh lebih nyaman daripada Weblogic, misalnya, dan manfaat OSGI tidak jelas bagi saya saat itu.

Tapi kemudian, setelah bertahun-tahun, saya harus memulai proyek di pekerjaan baru, yang disusun berdasarkan Apache Camel dan Apache Karaf. Ini bukan ide saya, saya sudah lama mengenal Camel, dan memutuskan untuk membaca tentang Karaf, bahkan tanpa tawaran. Saya membacanya suatu malam, dan menyadari - ini dia, sederhana dan siap pakai, solusi yang hampir sama untuk beberapa masalah khas JavaEE, mirip dengan yang pernah saya lakukan pada lutut saya menggunakan Weblogic WLST, Jython, dan Maven Aether.

Jadi, katakanlah Anda memutuskan untuk mencoba OSGI di platform Karaf. Di mana kita mulai?

Jika Anda menginginkan pemahaman yang lebih dalam


Anda tentu saja dapat memulai dengan membaca dokumentasi. Dan itu mungkin dengan HabrΓ© - ada artikel yang sangat bagus di sini, katakanlah dulu sekali. Tetapi secara umum, karaf menerima begitu sedikit perhatian. Ada beberapa ulasan lagi ini atau ini . Lebih baik untuk tidak menyebutkan karaf ini. Seperti yang mereka katakan, jangan baca koran Soviet malam ini ... karena mereka akan memberi tahu Anda di sana bahwa karaf adalah kerangka kerja OSGI - jadi Anda tidak percaya. Kerangka OSGI adalah Apache Felix atau Eclipse Equinox, atas dasar yang hanya bekerja karaf. Anda dapat memilih salah satu dari mereka.

Perlu dicatat bahwa ketika Jboss Fuse, atau Apache ServiceMix disebutkan, itu harus dibaca sebagai "Karaf, dengan komponen yang sudah diinstal", yaitu. sebenarnya - hal yang sama, hanya dikumpulkan oleh vendor. Saya tidak akan menyarankan memulai dengan ini dalam praktik, tetapi sangat mungkin untuk membaca artikel ulasan tentang ServiceMix, misalnya.

Untuk memulainya, saya akan mencoba menentukan secara singkat di sini apa OSGI itu dan untuk apa OSGI itu digunakan.

Secara umum, OSGI adalah alat untuk membuat aplikasi Java dari modul. Analog yang dekat dapat dianggap, misalnya, JavaEE, dan sampai batas tertentu wadah OSGI dapat mengeksekusi modul JavaEE (katakanlah, aplikasi web dalam bentuk Perang), dan di sisi lain, banyak wadah JavaEE mengandung OSGI di dalam sebagai cara menerapkan modularitas "untuk diri mereka sendiri ". Artinya, JavaEE dan OSGI adalah hal-hal yang mirip dengan kompatibilitas, dan berhasil saling melengkapi.

Bagian penting dari setiap sistem modular adalah definisi dari modul itu sendiri. Dalam kasus OSGI, modul ini disebut bundel, dan itu adalah arsip jar yang terkenal untuk semua pengembang dengan beberapa tambahan (yaitu, sangat mirip di sini, misalnya, untuk perang atau telinga). Dengan analogi dengan JavaEE, bundel dapat mengekspor dan mengimpor layanan, yang pada dasarnya adalah metode kelas (yaitu, layanan adalah antarmuka, atau semua metode umum kelas).

Metadata bundel tidak asing bagi semua META-INF / MANIFEST.MF. Header manifes OSGI tidak bersinggungan dengan header untuk JRE, masing-masing, di luar bundel wadah OSGI adalah toples biasa. Penting bahwa di antara metadata ada:

Bundle-SymbolicName: com.example.myosgi Bundle-Version: 1.0.0 

Ini adalah "koordinat" bundel, dan fakta bahwa kita dapat memiliki dua atau lebih yang diinstal secara bersamaan dan versi kerja dari bundel yang sama dalam satu wadah adalah penting.

Mirip dengan JavaEE, bundel memiliki siklus hidup yang terlihat seperti ini: gambar Selain layanan, bundel juga dapat mengimpor dan mengekspor paket (paket, dalam arti biasa untuk java). Paket yang diekspor didefinisikan di dalam bundel, dan dibuat tersedia untuk komponen lain ketika bundel diinstal pada sistem. Yang diimpor didefinisikan di suatu tempat dari luar, harus diekspor oleh seseorang, dan diberikan kepada bundel oleh wadah sebelum dapat mulai bekerja.

Paket impor dapat dinyatakan opsional, serta layanan impor. Dan cukup signifikan bahwa impor dan ekspor mengandung indikasi versi (atau rentang versi).

Perbedaan dari JavaEE


Yah, bagus juga mereka sama - kami mengerti. Dan bagaimana perbedaannya?

Menurut pendapat saya, perbedaan utama adalah bahwa OSGI memberi kita lebih banyak fleksibilitas. Setelah bundel dalam keadaan MULAI, kemungkinan hanya dibatasi oleh imajinasi Anda. Katakanlah Anda dapat dengan mudah membuat utas (ya, ya, saya tahu tentang ManagedExecutorService), kumpulan koneksi ke basis data, dll. Sebuah wadah tidak mengambil kendali atas semua sumber daya sampai tingkat yang sama seperti JavaEE.

Anda dapat mengekspor layanan baru dalam proses. Coba katakan di JavaEE secara dinamis buat servlet baru? Dan di sini sangat mungkin, apalagi, wadah servle karaf yang dibuat atas dasar dermaga akan segera terdeteksi oleh servlet yang Anda buat dan akan tersedia untuk klien di URL tertentu.

Meskipun ini sedikit penyederhanaan, tetapi jika aplikasi JavaEE dalam bentuk klasiknya terutama terdiri dari komponen:

  • pasif, menunggu panggilan dari klien
  • didefinisikan secara statis, yaitu, pada saat penyebaran aplikasi.

Di sisi lain, aplikasi berbasis OSGI dapat berisi:

  • komponen terjadwal aktif dan pasif, melakukan jajak pendapat, baik, mendengarkan soket, dll.
  • layanan dapat didefinisikan dan dipublikasikan secara dinamis
  • Anda dapat berlangganan acara kerangka kerja, misalnya, mendengarkan pendaftaran layanan, bundel, dll., Menerima tautan ke bundel dan layanan lain, dan melakukan lebih banyak lagi.

Ya, pada JavaEE, banyak dari ini juga sebagian mungkin (misalnya, melalui JNDI), tetapi dalam kasus OSGI, dalam praktiknya menjadi lebih mudah. Meskipun mungkin ada beberapa risiko lagi di sini.

Perbedaan antara karaf dan OSGI murni


Selain kerangka karaf, ada banyak hal berguna. Pada dasarnya, karaf adalah alat untuk mengelola kerangka kerja OSGI dengan nyaman - memasang bundel (termasuk grup) di sana, mengonfigurasinya, memantau, menjelaskan model peran dan memastikan keamanan, dan sejenisnya.

Dan mari kita berlatih?


Kalau begitu, mari kita mulai segera dengan instalasi. Tidak banyak yang bisa ditulis di sini - buka karaf.apache.org, unduh paket distribusi, buka paketnya. Versi karaf berbeda dalam mendukung spesifikasi OSGI yang berbeda (4, 5 atau 6), dan versi Java. Saya tidak merekomendasikan keluarga 2.x, tetapi di sini ada 3 (jika Anda memiliki Java 8, seperti milik saya), dan 4 dapat digunakan, meskipun hari ini hanya keluarga 4.x yang berkembang (versi 4.2.2 saat ini, mendukung OSGI 6 dan Java hingga 10).

Karaf bekerja dengan baik di Windows dan Linux, semua yang Anda butuhkan untuk membuat layanan dan autorun tersedia. Dukungan untuk MacOS dan banyak jenis Unix lainnya juga dinyatakan.

Anda biasanya dapat memulai karaf segera jika Anda menggunakan Internet. Jika tidak, maka biasanya layak memperbaiki file konfigurasi, yang menunjukkan di mana Anda memiliki repositori maven. Biasanya itu akan menjadi Nexus perusahaan, atau katakan Artifactory, siapa pun suka apa. Konfigurasi karaf terletak di folder distribusi dll. Nama-nama file konfigurasi tidak terlalu jelas, tetapi dalam hal ini Anda memerlukan file org.ops4j.pax.url.mvn.cfg. Format file ini adalah properti java.

Anda dapat menentukan repositori di file konfigurasi itu sendiri, mendaftar daftar URL di pengaturan, atau hanya menunjukkan di mana pengaturan Anda.xml berada. Di sana, karaf akan mengambil lokasi proxy Anda, yang biasanya perlu diketahui di intranet.

Kafar membutuhkan beberapa port, ini adalah HTTP, HTTPS (jika web dikonfigurasi, secara default tidak), SSH, RMI, JMX. Jika mereka sibuk dengan Anda, atau Anda ingin menjalankan beberapa salinan pada host yang sama, Anda harus mengubahnya juga. Ada sekitar lima port ini.

Port seperti jmx dan rmi - di sini: org.apache.karaf.management.cfg, ssh - org.apache.karaf.shell.cfg, untuk mengubah port http / https, Anda perlu membuat (kemungkinan besar tidak) file / etc / file org.ops4j.pax.web.cfg, dan tulis nilai org.osgi.service.http.port = port yang Anda butuhkan di dalamnya.

Maka Anda pasti bisa memulainya, dan sebagai aturan, semuanya akan mulai. Untuk penggunaan industri, jelas, Anda harus membuat perubahan pada file bin / setenv, atau bin / setenv.bat, misalnya, untuk mengalokasikan jumlah memori yang diperlukan, tetapi pertama-tama, untuk melihat, itu tidak perlu.

Anda dapat memulai Karaf segera dengan konsol, perintah karaf, atau Anda dapat menjalankannya di latar belakang dengan perintah mulai server, dan kemudian terhubung ke sana melalui SSH. Ini adalah SSH yang sepenuhnya standar, dengan dukungan untuk SCP, dan SFTP. Anda dapat menjalankan perintah, dan menyalin file bolak-balik. Dimungkinkan untuk terhubung dengan klien mana pun, misalnya, alat favorit saya adalah Far NetBox. Login tersedia dengan login dan kata sandi, serta dengan kunci. Di jeroan ayam itik jsch, dengan semua yang tersirat.

Saya sarankan memiliki jendela konsol tambahan segera untuk melihat log yang terletak di data / log / karaf.log (dan file lain biasanya ada di sana, meskipun ini dapat disesuaikan). Log berguna bagi Anda, dari pesan singkat di konsol, tidak semuanya jelas.

Saya akan menyarankan menginstal web segera, dan konsol web hawtio. Dua hal ini akan membuat Anda lebih mudah untuk menavigasi apa yang terjadi dalam wadah dan mengarahkan proses dari sana ke tingkat yang luas (sebagai bonus, Anda akan mendapatkan jolokia dan kemampuan untuk memantau melalui http). Instalasi hawtio dilakukan oleh dua perintah dari konsol karaf ( seperti dijelaskan di sini ), dan sayangnya, hari ini versi karaf 3.x tidak lagi didukung (Anda harus mencari versi hawtio yang lebih lama).

Di luar kotak, https tidak akan langsung, untuk ini Anda perlu melakukan beberapa upaya seperti menghasilkan sertifikat, dll. Implementasinya didasarkan pada dermaga, jadi semua upaya ini sebagian besar dilakukan dengan cara yang sama.

Oke, sudah mulai, selanjutnya apa?




Sebenarnya apa yang kamu harapkan? Saya bilang itu ssh. Tab berfungsi, jika itu.

Sudah waktunya untuk menginstal beberapa aplikasi. Aplikasi untuk OSGI adalah bundel, atau terdiri dari beberapa bundel. Karaf dapat menggunakan aplikasi dalam beberapa format:

  • Bundel toples, dengan atau tanpa manifes OSGI
  • xml mengandung Spring DM atau Blueprint
  • xml berisi fitur yang disebut, yang merupakan kumpulan bundel, fitur lain, dan sumber daya (file konfigurasi)
  • Arsip .kar yang berisi beberapa fitur dan repositori maven dengan dependensi
  • Aplikasi JavaEE (dalam beberapa kondisi tambahan), misalnya .war

Ada beberapa cara untuk melakukan ini:

  • menempatkan aplikasi dalam folder deploy
  • instal dari konsol dengan perintah install
  • instal fitur dengan perintah dari fitur: install console
  • kar: instal

Ya, secara umum, ini sangat mirip dengan apa yang bisa dilakukan oleh wadah JavaEE biasa, tetapi agak lebih nyaman (saya akan mengatakan itu jauh lebih nyaman).

Guci sederhana


Opsi termudah adalah memasang toples biasa. Jika Anda memilikinya di repositori maven, maka perintahnya cukup untuk menginstal:

 install mvn:groupId/artifactId/version 

Pada saat yang sama, Karaf menyadari bahwa ia memiliki kendi biasa di depannya, dan memprosesnya, membuat bungkus bundel dengan cepat, yang disebut bungkus, menghasilkan manifes default, dengan paket impor dan ekspor.

Rasa memasang hanya sebuah toples biasanya tidak banyak, karena bundel ini akan pasif - hanya mengekspor kelas yang akan tersedia untuk bundel lain.

Metode ini digunakan untuk menginstal komponen seperti Apache Commons Lang, misalnya:

 install mvn:org.apache.commons.lang3/commons-lang/3.8.1 

Tapi itu tidak berhasil :) Berikut adalah koordinat yang benar:

 install mvn:org.apache.commons/commons-lang3/3.8.1 

Mari kita lihat apa yang terjadi: list -u akan menunjukkan kepada kita bundel dan sumbernya:

 karaf@root()> list -u START LEVEL 100 , List Threshold: 50 ID | State | Lvl | Version | Name | Update location ------------------------------------------------------------------------------------------------- 87 | Installed | 80 | 3.8.1 | Apache Commons Lang | mvn:org.apache.commons/commons-lang3/3.8.1 88 | Installed | 80 | 3.6.0 | Apache Commons Lang | mvn:org.apache.commons/commons-lang3/3.6 

Seperti yang Anda lihat, sangat mungkin untuk menginstal dua versi dari satu komponen. Perbarui lokasi - ini adalah tempat kami memperoleh bundel, dan di mana ia dapat diperbarui jika perlu.

Konteks guci dan pegas


Jika ada Konteks Musim Semi di dalam botol Anda, segalanya menjadi lebih menarik. Karaf Deployer secara otomatis mencari konteks xml di folder META-INF / spring, dan membuatnya jika semua bundel eksternal yang diperlukan oleh bundel telah berhasil ditemukan.

Dengan demikian, semua layanan yang ada di dalam konteks sudah akan mulai. Jika Anda memiliki Musim Semi Unta di sana, misalnya, rute Unta akan mulai juga. Ini berarti bahwa kami mengatakan layanan REST, atau layanan yang mendengarkan pada port TCP, Anda sudah dapat memulai. Tentu saja, meluncurkan beberapa layanan mendengarkan pada satu port tidak akan berhasil seperti itu.

Hanya pegas konteks XML


Jika Anda memiliki, misalnya, definisi JDBC DataSources di dalam Spring Context, maka Anda dapat menginstalnya secara terpisah di Karaf. Yaitu ambil file xml yang hanya berisi DataSource dalam bentuk <bean>, atau set komponen lainnya, Anda bisa meletakkannya di folder deploy. Konteks akan diluncurkan dengan cara standar. Satu-satunya masalah adalah bahwa Sumber Data yang dibuat dengan cara ini tidak akan terlihat oleh bundel lain. Mereka perlu diekspor ke OSGI sebagai layanan. Tentang ini - sesaat kemudian.

Musim semi dm


Apa perbedaan antara Spring DM (versi yang mendukung OSGI) dan Spring klasik? Jadi dalam kasus klasik, semua biji dalam konteks dibuat pada tahap inisialisasi konteks. Yang baru tidak bisa muncul, yang lama tidak akan kemana-mana. Dalam kasus OSGI, bundel baru dapat diinstal dan bundel lama dihapus. Lingkungan menjadi lebih dinamis, Anda perlu merespons.

Metode respons disebut layanan. Suatu layanan biasanya merupakan antarmuka tertentu, dengan metode sendiri, yang diterbitkan oleh beberapa bundel. Layanan memiliki metadata yang memungkinkannya untuk dicari dan dibedakan dari layanan lain yang mengimplementasikan antarmuka serupa (jelas, dari DataSource lain). Metadata adalah sekumpulan properti nilai kunci sederhana.

Karena layanan dapat muncul dan menghilang, mereka yang membutuhkannya dapat berlangganan layanan saat startup atau mendengarkan acara untuk mengetahui tentang penampilan atau menghilangnya mereka. Pada tingkat Spring DM, dalam XML, ini diimplementasikan sebagai dua elemen, layanan dan referensi, yang tujuan dasarnya cukup sederhana: menerbitkan kacang yang ada dari konteksnya sebagai layanan, dan berlangganan ke layanan eksternal dengan menerbitkannya ke konteks musim semi saat ini.

Dengan demikian, ketika menginisialisasi bundel seperti itu, wadah akan menemukan layanan eksternal yang dibutuhkannya, dan menerbitkan bundel yang diimplementasikan di dalamnya, membuatnya dapat diakses dari luar. Bundel dimulai hanya setelah tautan layanan diselesaikan.

Bahkan, semuanya sedikit lebih rumit, karena bundel dapat menggunakan daftar layanan serupa, dan berlangganan segera ke daftar. Yaitu suatu layanan, secara umum, memiliki properti seperti kardinalitas, yang mengambil nilai 0..N. Dalam hal ini, langganan, di mana 0..1 ditunjukkan, menggambarkan layanan opsional, dan dalam hal ini bundel mulai berhasil bahkan jika tidak ada layanan seperti itu dalam sistem (dan alih-alih tautan ke sana, ia akan mendapatkan sebuah rintisan).

Saya perhatikan bahwa layanan hanyalah antarmuka apa saja (atau Anda dapat menerbitkan kelas saja), sehingga Anda dapat menerbitkan java.util.Map dengan data sebagai layanan.

Antara lain, layanan memungkinkan Anda menentukan metadata, dan referensi memungkinkan Anda untuk mencari layanan dengan metadata ini.

Cetak Biru


Blueprint adalah inkarnasi Spring DM yang lebih baru, yang sedikit lebih sederhana. Yaitu, jika di Spring Anda memiliki elemen XML khusus, maka mereka tidak ada di sini, karena tidak perlu. Kadang-kadang ini masih menyebabkan ketidaknyamanan, tetapi terus terang - jarang. Jika Anda tidak memigrasi proyek dari Spring, Anda dapat segera mulai dengan Cetak Biru.

Intinya di sini adalah sama - itu XML, yang menggambarkan komponen dari mana konteks bundel dirakit. Bagi mereka yang mengenal Spring, tidak ada yang asing sama sekali.

Berikut adalah contoh cara menggambarkan DataSource dan mengekspornya sebagai layanan:

 <?xml version="1.0" encoding="UTF-8"?> <blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"> <bean id="dataSource" class="oracle.jdbc.pool.OracleDataSource"> <property name="URL" value="URL"/> <property name="user" value="USER"/> <property name="password" value="PASSWORD"/> </bean> <service interface="javax.sql.DataSource" ref="dataSource" id="ds"> <service-properties> <entry key="osgi.jndi.service.name" value="jdbc/ds"/> </service-properties> </service> </blueprint> 

Yah, kami menyebarkan file ini ke folder penempatan, dan melihat hasil dari perintah daftar. Mereka melihat bahwa bundel itu tidak mulai - dalam status Indtalled. Kami mencoba memulai, dan kami mendapatkan pesan kesalahan.

Sekarang dalam daftar bundel dalam status Gagal. Ada apa? Jelas, ia juga membutuhkan dependensi, dalam hal ini, Jar dengan kelas Oracle JDBC, atau lebih tepatnya, paket oracle.jdbc.pool.
Kami menemukan tabung yang diperlukan di repositori, atau unduh dari situs Oracle, dan instal, seperti yang dijelaskan sebelumnya. Sumber Data kami telah dimulai.

Bagaimana cara menggunakan semua ini? Tautan layanan disebut dalam referensi Cetak Biru (di suatu tempat, dalam konteks bundel lain):

 <reference id="dataSource" interface="javax.sql.DataSource"/> 

Kemudian, kacang ini menjadi, seperti biasa, ketergantungan untuk kacang lainnya (dalam contoh unta-sql):

 <bean id="sql" class="org.apache.camel.component.sql.SqlComponent"> <property name="dataSource" ref="dataSource"/> </bean> 

Jar dan Aktivator


Cara kanonik untuk menginisialisasi bundel adalah dengan menggunakan kelas yang mengimplementasikan antarmuka Activator. Ini adalah antarmuka siklus hidup khas yang berisi metode mulai dan berhenti yang melewati konteks . Di dalamnya, bundel biasanya memulai utasnya, jika perlu, mulai mendengarkan port, berlangganan layanan eksternal menggunakan OSGI API, dan sebagainya. Ini mungkin cara yang paling kompleks, paling mendasar, dan paling fleksibel. Selama tiga tahun saya tidak pernah membutuhkannya.

Pengaturan dan konfigurasi


Jelaslah bahwa konfigurasi DataSource seperti itu, seperti yang diperlihatkan dalam contoh, hanya beberapa orang yang perlu. Login, kata sandi, dan banyak lagi, semuanya dikodekan dalam XML. Perlu untuk mengambil parameter ini.

 <property name="url" value="${oracle.ds.url}"/> <property name="user" value="${oracle.ds.user}"/> <property name="password" value="${oracle.ds.password}"/> 

Solusinya cukup sederhana, dan mirip dengan yang digunakan dalam Spring klasik: pada titik tertentu dalam konteks siklus hidup, nilai properti diganti dari berbagai sumber.

Pada ini kita akan mengakhiri bagian pertama. Jika ada minat pada topik ini, maka untuk dilanjutkan. Kami akan mempertimbangkan cara merakit aplikasi dari bundel, mengkonfigurasi, memantau, dan secara otomatis menggunakan sistem pada platform ini.

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


All Articles