Karaf教程之Config Admin服務的使用

目錄

摘要
配置管理服務規範
如何使配置生效
引入簡單的可配置類
動手實踐。使用OSGi接口方式實現配置
例子運行
深入Karaf配置命令
使用Blueprint配置
部署配置文件
總結和展望未來
參考文獻

摘要

在Karaf教程的第一部分,我們學習瞭如何使用maven和blueprint提供和使用pojo服務,以及如何使用http服務發佈一個servlet。
在第二部分,我們關注OSGi bundles的配置。和servlet容器不同,對於配置OSGi包含了一個非常好的規範:來自OSGi企業規範的配置管理服務。在該教程中,將涉及分別通過OSGi和blueprint方式來使用配置管理服務,以及如何使配置文件和bundles自動化部署。

教程的代碼可以在github查閱,地址Here

配置管理服務規範

首先我們看下配置服務規範概覽。這裏使用到主要有以下兩個接口:

  • ConfigurationAdmin -允許檢索和改變配置。這個服務是配置管理服務實現提供的接口。

  • ManagedService -配置發生改變的時候,允許做出響應。你不得不實現這個接口,並且把它註冊爲一個服務來獲取通告。

所以基本上在配置管理服務中的配置是一個字典,這個字典包含了屬性和相應的值。字典被一個持久化標識符(persistent identifier (pid))標識.標識是一個簡單的字符串,且唯一的標識該配置。

如何使配置生效

可以通過使用ConfigurationAdmin.getConfiguration接口檢索一個配置,但不推薦這麼做。OSGi是動態的以至於可能發生這樣的情況,bundles在config admin服務或者config admin服務還沒有讀取配置之前啓動了。所以有時可能獲取到一個null配置。

因此推薦的方式是使用ManagedService服務來監聽更新。如果因爲沒有配置bundle不能啓動,則可在第一次更新消息被接收的時,通過創建一個可配置的pojo對象是一個不錯的主意。

引入簡單的可配置類

按照需求,可配置的類應該是pojo。雖然可以簡單地實現ManagedService接口並直接使用Dictionary,這需要依賴於OSGi和當前的Config Admin Service規範。因此改用一個具有title屬性的簡單bean類。另外添加了一個刷新方法,在配置項被更改之後應該被調用。

public class MyApp {

  String title;

  public void setTitle(String title) {
    this.title = title;
  }

  public void refresh() {
    System.out.println("Configuration updated (title=" + title + ")");
  }
}

我們的目的是配置tilte,當配置改變的時候要調用refresh方法。我們將使用OSGi方式和blueprint兩種方式實現。

動手實踐。使用OSGi接口方式實現配置

首先在本節展示通過使用OSGi接口如何使用config admin服務。然而這絕不可能是你以後要這麼實現。這僅僅是幫助你理解在鉤子下發生了什麼。
你可以在這個子目錄下configapp找到實現(https://github.com/cschneider/Karaf-Tutorial/tree/master/configadmin/configapp)
首先我們需要一個pom文件用於maven編譯。你最好從例子中configapp的pom開始看起。
如果你纔剛開始,你將不得不使用maven-bundle-plugin編譯你的工程爲一個OSGi bundle,且你需要添加兩個依賴:

<dependency>
  <groupId>org.osgi</groupId>
  <artifactId>org.osgi.compendium</artifactId>
  <version>4.2.0</version>
</dependency>
<dependency>
  <groupId>org.osgi</groupId>
  <artifactId>org.osgi.core</artifactId>
  <version>4.2.0</version>
</dependency>

第一個依賴是用於config admin服務相關接口,第二個依賴是用於創建Activator和包含基本的OSGi相關的接口。

現在我們將專注修訂MyApp類。下面的類達到了目的。我們實現了ManagedService接口用於和Config Admin服務交互。無論什麼時候配置發生變化,ConfigUpdater都被調用。
第一件事是檢查是否爲null,這個情況是可能發生的,當config被移除的時候。關於這個步驟我們可以停掉MyApp運行,但是爲了保持簡單我們僅僅是忽略了這些問題。下一步是創建一個MyApp實例。
正常情況,你將在Activator完成這個步驟,但是你將不得不考慮空配置的情況,這種情況不是我們期望的。最後一步是簡單地從config獲取一個值傳入setter方法並調用,且在設置完所有配置後調用refresh方法。

private final class ConfigUpdater implements ManagedService {

  public void updated(Dictionary config) throws ConfigurationException {
    if (config == null) {
      return;
    }

    if (app == null) {
      app = new MyApp();
    }

    app.setTitle((String)config.get("title"));
    app.refresh();
  }
}

當然這樣還沒有完成所有事情,最後一步是在Activator.start註冊ConfigUpdater。類似其他服務一樣我們簡單地使用了registerService。唯一特別的事情是你不得不設置屬性SERVICE_PID到你的配置pid,這樣Config Admin服務就知道你想要監聽的是什麼配置了。

Hashtable<String, Object> properties = new Hashtable<String, Object>();
properties.put(Constants.SERVICE_PID, CONFIG_PID);
serviceReg = context.registerService(ManagedService.class.getName(), new ConfigUpdater() , properties);

例子運行

  • 運行mvn install編譯工程.
  • 啓動一個新的Karaf實例
  • 從target目錄複製configapp.jar bundle到Karaf deploy目錄

現在我們注意到好像什麼事都沒發生。在Karaf控制檯調用list你應該能夠看到bundle實際上是已經啓動,但是卻沒有任何輸出,因爲沒有配置。我們仍然需要創建配置文件和設置tilte。
- 複製已經存在的文件/configadmin-features/src/main/resources/ConfigApp.cfg 到Karaf實例中的/etc目錄

這裏重要的部分是文件名必須是.cfg。這樣config admin服務能夠發現它。

現在fileinstall bundle將在etc目錄下偵測到新的文件。當以.cfg結尾的文件將被當作配置管理資源且根據文件名pid來創建或者更新對應的Config Admin服務配置。

所以現在你應該在Karaf控制檯能看到如下輸出。這顯示了配置的變化被檢測和轉發。如果你現在用編輯器修改文件內容和保存修改,修改將被通告。

Configuration updated (title=" + title + ")

深入Karaf配置命令

在Karaf控制檯輸入如下:

> config:list
Pid:            ConfigApp
BundleLocation: file:/C:/java/apache-karaf-2.2.3/deploy/configapp.jar
Properties:
   service.pid = ConfigApp
   felix.fileinstall.filename = file:/C:/java/apache-karaf-2.2.3/etc/ConfigApp.cfg
   title = my Title

在配置列表中你應該能夠找到配置ConfigApp。這個配置顯示配置文件從哪裏加載的,pid標識符和在文件中設置的所有屬性。

我們也可以修改配置:

> config:edit ConfigApp
> config:propset title "A better title"
> config:proplist
   service.pid = ConfigApp
   felix.fileinstall.filename = file:/C:/java/apache-karaf-2.2.3/etc/ConfigApp.cfg
   title = A better title
> config:update
Configuration updated (title=A better title)

我們發現修訂直接通告到bundle,如果你查看etc下配置文件,你可以發現修訂也被持久化到文件了。所以在重啓Karaf後修訂仍然生效。

使用Blueprint配置

繼我們用OSGi實現和Config Admin服務交互後,現在我們將看下使用Blueprint怎麼實現相同的功能。幸運地是這種方式十分的簡單,Blueprint做了大部分的事情。

簡單的定義一個cm:property-placeholder元素。類似文件中的屬性佔位符但是這個是和Config Admin服務起作用。我們需要提供config PID和更新策略。當我們選擇reload策略,這意味着一個修訂發生,blueprint的上下文環境會重新加載反映這個修訂。當config PID沒有找到或者屬性不存在,將設置爲默認屬性值。

和bean類集成通常是一個簡單的bean定義,這個bean是定義了title屬性和分配了一個佔位符。通過使用config admin服務解析這個佔位符。唯一特別是的事情是init-method。
這被用於在配置修訂後,我們機會去做相應的事情。例如上面的OSGi例子。

因爲blueprint我們不需要任何maven依賴,因此java代碼僅是一個Java bean時。通過把它放在OSGI-INF/blueprintblueprint目錄和blueprint extender被加載,環境很容易被激活。因爲在Karaf中blueprint總是被加載,所以我們不需要做其他事情。

<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
[http://www.osgi.org/xmlns/blueprint/v1.0.0] [http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd]
[http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0] [http://svn.apache.org/repos/asf/aries/trunk/blueprint/blueprint-cm/src/main/resources/org/apache/aries/blueprint/compendium/cm/blueprint-cm-1.1.0.xsd]
">
<cm:property-placeholder persistent-id="ConfigApp" update-strategy="reload" >
<cm:default-properties>
<cm:property name="title" value="Default Title"/>
</cm:default-properties>
</cm:property-placeholder>

<bean id="myApp" init-method="refresh">
<property name="title" value="$\{title\}"></property>
</bean>
</blueprint>

上面xml請刪除title附近的反斜槓。這個僅僅是了避免當wiki macro解析錯誤的影響。

部署配置文件

在我們已經成功地使用Config Admin服務後,進入產品環境唯一的事情就是部署bundle和一個默認配置。這個可以通過使用一個Karaf的feature文件來完成。我們根據需要的bunldes定義一個feature,和簡單添加一個configfile元素。這個使得Karaf部署指定文件到karaf安裝的etc目錄下。如果文件已經存在,它不會被覆蓋。

<feature name="tutorial-configadmin" version="${pom.version}">
<bundle>mvn:net.lr.tutorial.configadmin/configapp/${pom.version}</bundle>
<bundle>mvn:net.lr.tutorial.configadmin/configapp-blueprint/${pom.version}</bundle>
<configfile finalname="/etc/ConfigApp.cfg">mvn:net.lr.tutorial.configadmin/configadmin-features/${pom.version}/cfg</configfile>
</feature>

最後一個問題是怎麼部署配置到maven使得configfile能夠發現它。這個有點類似feature和build-helper-maven-plugin關係,詳情請看pom文件怎麼使用它。

總結和展望未來

在這個教程中,我們已經學習了Config Admin服務是怎麼工作的以及如何使用OSGi和blueprint。我們也明白瞭如何編譯及如何把文檔和我們的工程部署在一起。

然而這裏還是有一些非常有用的小細節沒有涉及到。第一個細節是configfile不總是和config admin服務一致。實事上Karaf沒有使用config admin服務去部署文件。我們所看到的是,已經存在的config元素不僅寫配置到config admin服務中,而且持久化了它。幸運的是我的同事Jean Baptiste已經在研究這方面相關的,請訪問Here

另外一個細節是對於企業環境,第一,需要定製化的config admin服務。例如需要在整網集中的地方設置配置和友好的UI界面。第二,是你不僅僅想要部署默認配置,而是部署對於系統管理確實需要的配置。所以針對安裝的bunldes和feature和必要配置的修訂,我認爲你應該定一個部署計劃。如果這個被正確的完成。將有利於部署和配置修訂的檢查,同時也有利於在某些配置錯誤的情況下去回滾修訂。我希望我們可以在下一個Talend ESB EE發行版本提供一些相關功能。

參考文獻

Using the Configuration Admin Service


myqrcode

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章