Lớp Lifecycle

Một phần của tài liệu Áp dụng OSGi trong việc xây dựng hệ thống dựa thành phần (Trang 32)

Ở phần trước ta đã nói về lớp module và giới thiệu bundle, một bundle là một thuật ngữ trong OSGi cho một module. Một bundle là một file JAR và mở rộng thêm module meta-data. Ta sử dụng các bundle để định nghĩa tính module cả về mặt logic (tính đóng gói và các phần phụ thuộc) và vật lý (đơn vị có thể triển khai độc lập) của một ứng dụng.

Trong phần này ta sẽ nói về việc làm sao để cài đặt các bundle vào một OSGi framework. Và làm sao để quản lý vòng đời của các bundle.

Quản lý vòng đời

Lớp Lifecycle của OSGi cung cấp một API quản lý và định nghĩa vòng đời cho các bundle khi chạy trong OSGi framework. Lớp Lifecycle phục vụ cho hai mục đích khác nhau:

-Từ bên ngoài đối với ứng dụng của ta, thì lớp Lifecycle định nghĩa các lệnh thực thi vòng đời của bundle. Những lệnh này cho phép ta quản lý và phát triển ứng dụng bằng cách thay đổi động các thành phần của các bundle trong một framework đang chạy. - Từ bên trong đối với ứng dụng của ta, lớp Lifecycle định nghĩa làm thế nào các bundle của ta có thể truy cập tới ngữ cảnh thực thi của nó (execution context), nó cung cấp cho bundle cách tương tác với OSGi framework và các công cụ thuận tiện ở thời gian chạy.

Vòng đời của bundle

Không giống như file JAR thông thường, OSGi bundle có một vòng đời. Chúng có thể được khởi động (start) và dừng (stop) theo nhu cầu, tương ứng các Classloader và các lớp của chúng xuất hiện và biến mất khỏi hệ thống.

OSGi framework hỗ trợ các tao tác quản lý toàn bộ vòng đời của các bundle, bao gồm install, resolve, start, stop, update và uninstall. Ví dụ so sánh Class Path của Java thông thường so với việc quản lý vòng đời của các bundle trong OSGi như ở hình 2.12 [7].

Một điểm khác biệt lớn nữa so với Java Class Path thông thường là tính động. OSGi framework hỗ trợ toàn bộ vòng đời của bundle ở thời điểm chạy. Điều này giống như là thay đổi những gì sẽ ở trong Class Path một cách động. Ta không cần phải khởi động lại server hay framework. Hình 2.13 [7] mô tả toàn bộ các trạng thái của bundle trong vòng đời của nó.

Hình 2.13: Vòng đời của bundle trong OSGi

Các chính sách active

Một bundle có một số điểu khiển khi nó chuyển giữa các trạng thái. Sau khi một bundle đã khởi động (start). Nó có thể chuyển ngay lập tức từ STARTING sang trạng thái ACTIVE (eager activation), hoặc nó có thể đợi một hoặc nhiều lớp được nạp (lazy activation). Chính sách mặc định là eager activation; lazy activation có thể được sử dụng bằng cách thêm vào manifest sau:

Bundle-ActivationPolicy: lazy -Bundle activator

Trước khi chuyển tới trạng thái ACTIVE, một bundle sẽ có một cơ hội để thực hiện một số khởi tạo. Nếu một bundle khai báo một activator, activator của nó sẽ được thông báo bất cứ khi nào bundle được khởi động hoặc dừng. Lớp activator được khai báo trong bundle manifest như sau:

Mặc dù chúng được sử dụng rộng rãi và xử lý trong nhân của OSGi, nhưng bundle activator không phải là mẫu thường được dùng trong OSGi enterprise. Chúng ta có thể sử dụng Blueprint (một mô hình thành phần hỗ trợ khai báo và sử dụng các dịch vụ trong OSGi) để làm mọi thứ ta có thể với activator, nhưng mạnh mẽ và linh động hơn.

Một số lệnh ta thường dùng khi trong khi triển khai ứng dụng tương ứng với một số trạng thái của bundle được mô tả trong hình 2.14 [1].

Hình 2.14: Các lệnh OSGi tương ứng với các thao tác khi triển khai ứng dụng

Cài đặt và phân giải bundle

Cài đặt (installation) là quá trình các bundle mới được thêm vào một OSGi framework ở thời điểm chạy. Điều này có thể được làm trong một số cách xác định của framework, nhưng có một cách thường được sử dụng, đó là cơ chế độc lập với framework cho phép cài đặt một bundle từ bất kỳ đầu cục bộ (local) hay một vị trí từ xa (remote location).

BundleContext có thể được sử dụng để cài đặt một bundle sử dụng URL trỏ tới một file bundle ở đâu đó, như sau:

Sau khi cài đặt vào một framework, một OSGi bundle có trạng thái là INSTALLED. Một INSTALLED bundle không có một Classloader và cũng không thể cung cấp mã nguồn hay package cho bundle nào khác. Framework sẽ đảm bảo tất cả các phần phụ thuộc của một bundle được thỏa mãn trước khi nó có thể được sử dụng (đó là, không có lớp nào có thể được nạp từ nó). Framework sẽ không cho phép một bundle chuyển sang trạng thái RESPLVED trừ phi tất cả các phần phụ thuộc của nó được thỏa mãn.

org.osgi.framework.BundleContext.installBundle(String location)

Khi tất cả các phần phụ thuộc của bundle là có sẵn trong OSGi framework (có các exported package cho tất cả các import của nó), thì framework resolver sẽ cố gắng phân giải bundle. Quá trình này tạo sợi dây nối (wire) giữa các package import và export, tuân theo các ràng buộc về phiên bản được khai báo trong meta-data. Một RESOLVED bundle có một Classloader, và các lớp cũng như tài nguyên của nó có thể được nạp từ kể từ khi bundle được phân giải. Quá trình phân giải đảm bảo các phần phụ thuộc có sẵn ở thời điểm chạy và ngăn chặn rủi ro thường gặp phải là ngoại lệ NoClassDefFoundError.

Starting và stopping bundle

Sau khi một bundle đã vào trạng thái RESOLVED, thì nó có thể được coi như đủ điều kiện là STARTED. Khi đó các lớp của nó có thể được nạp từ một bundle ngay sau khi nó đã được phân giải, ta có thể cảm thấy bối rối vì không biết quá trình starting nghĩa là gì. Quá trình này là một số thứ xảy ra khi khởi động bundle, giống như gọi BundleActivator nếu có, và chuyển sang trạng thái ACTIVE.

Sự thay đổi quan trọng nhất trong quá trình starting một bundle là một active BundleContext được tạo cho một bundle khi nó khởi động. BundleContext có thể được sử dụng bởi bundle để tương tác với framework, tác động lên vòng đời của các bundle khác, và một điều quan trọng nhất đó là truy cập OSGi Service Registry.

Quá trình stopping một bundle ngược lại với quá trình starting. Framework chuyển trạng thái các bundle về lại RESOLVED, nó gọi phương thức stop trong BundleActivator của bundle, và nó đảm bảo bất kỳ dịch vụ nào đã được đăng ký bởi bundle sẽ được gỡ đi từ Service Registry.

Uninstalling và updating bundle

Khi một bundle không cần trong một môi trường chạy nữa nó có thể được uninstalled. Ngược lại những gì ta có thể mong đợi, uninstalling một bundle không gỡ nó từ môi trường chạy. Uninstalled các bundle là chúng được đánh dấu để không đủ tư cách cung cấp các package khi framework resolver cố gắng phân giải các bundle mới, nhưng chúng tiếp tục cung cấp các package tới các bundle đang tồn tại.

Một bundle đã uninstall vẫn còn cung cấp các package cho các bundle khác không thể bị gỡ bỏ ngay lập tức, làm như vậy sẽ lấy đi các package mà các bundle đang chạy đang sử dụng và gây ra hỗn loạn. Các bundle đã uninstall chỉ có thể bị từ chối bởi framework khi không có các bundle đã resolve khác được nối với chúng. Về cơ bản, sau khi một bundle được gỡ bỏ, framework được refresh sử dụng

PackageAdmin.refreshPackages() hay

bundle.adapt(FrameworkWiring.class).refreshBundles(). Làm như vậy để framework phân giải lại bất kỳ bundle nào đang sử dụng các package từ bundle đã bị gỡ bỏ. Nó

cho phép framework dọn dẹp các bundle đã gỡ bỏ khi không còn bundle nào sử dụng các package của nó. Một bundle đã gỡ bỏ không thể được gỡ đi bởi vì nó vẫn cung cấp các package cho các bundle khác đôi khi được biết như một zombie bundle.

Việc cập nhật (update) một bundle là không thể trong Java chuẩn. Quá trình cập nhật giống như một thao tác đơn nhất (automic) thực hiện gỡ bỏ và cài đặt lại cho phép nội dung của bundle được thay đổi.Nếu một bundle A1 được cập nhật thành bundle A2, và nó cung cấp các package cho một bundle khác B, thì phiên bản cũ A1 không thể được gỡ đi mà không làm hỏng B. Trường hợp này sẽ không dừng việc update vì lỗi, mà có nghĩa là ta sẽ kết thúc với cả hai A1 và A2 bundle cùng có sẵn ở một thời điểm. B sẽ tiếp tục sử dụng A1 (cho đến khi nó được refresh), nhưng tương lai sẽ phân giải và nối tới A2. Tương tự với uninstallation, việc refresh framework sau khi cập nhật cho phép framework dọn dẹp các phiên bản cũ của bundle.

Quản lý các phụ thuộc trong một hệ thống động

Các bundle có thể được stop bất cứ lúc nào. Chuyện gì sẽ xảy ra với các bundle phụ thuộc vào các bundle đã stop? Khi một bundle bị dừng, nó vẫn còn có ClassLoader, do đó các exported package vẫn còn có sẵn với các bundle khác đã nối với nó. Có một thứ thay đổi đó là bundle đã bị dừng không có BundleContext nữa. Điều này có nghĩa là tất cả các dịch vụ mà bundle đã đăng ký khi nó khởi động là bị gỡ bỏ bởi framework (giả sử bundle không tự dọn dẹp). Rõ ràng, các bundle phụ thuộc vào những dịch vụ này không thể sử dụng chúng được nữa, nhưng nếu bundle đã bị dừng và khởi động trở lại, thì mọi thứ luôn luôn được trả về trạng thái ban đầu của nó.

Quá trình gỡ bỏ một bundle là thao tác hủy nhiều thứ hơn quá trình dừng. Một bundle đã bị gỡ bỏ không thể cung cấp các package cho bất kỳ quá trình phân giải nào, và nó cũng không thể cung cấp bất kỳ dịch vụ nào. Framework tự động gỡ bỏ các bundle đã gỡ bỏ, nhưng đôi khi nó không thể làm điều này. Nếu gỡ bỏ bundle đang cung cấp các package cho các bundle khác trước khi các bundle này bị gỡ bỏ, thì những kết nối sẽ giữ Classloader của bundle đã bị gỡ bỏ sống. Điều này thường được gọi là zombie bundle; bundle không còn sống nữa, và không có cách nào đưa chúng trở lại, nhưng chúng vẫn ở quanh đó. Hệ thống có thể hóa giải điều này bằng việc khởi động lại framework, bằng cách gọi refreshPackages thông qua PackageAdmin service, hoặc bằng cách gọi refreshBundles qua FrameworkWiring service.

Bất kỳ bundle nào phụ thuộc vào bundle đã bị gỡ bỏ sẽ được dừng và phân giải lại. Điều này có nghĩa là chúng chuyển tất cả về trạng thái INSTALLED.

Quá trình dừng và gỡ bỏ không chỉ là những hành động có thể thực hiện trên các bundle độc lập. Các OSGi bundle có thể được cập nhật động, và một thao tác cập nhật có thể gỡ bỏ các exported package trước đó hoặc giới thiệu các yêu cầu package mới. Như với gỡ bỏ bundle các package đã bị gỡ bỏ vẫn còn có sẵn cho các bundle

đang tồn tại sử dụng (từ phiên bản update trước của bundle) cho đến khi framework được khởi động lại hoặc refresh.

Một phần của tài liệu Áp dụng OSGi trong việc xây dựng hệ thống dựa thành phần (Trang 32)

Tải bản đầy đủ (PDF)

(81 trang)