【问题标题】:How to provision OSGi services per client如何为每个客户端配置 OSGi 服务
【发布时间】:2011-02-07 22:56:44
【问题描述】:

我们正在开发一个网络应用程序(我们称之为图像库),我们已经确定了以下需求:

  • 该应用程序迎合由一组用户组成的客户。
  • 可以动态创建新客户并由客户管理其用户
  • 客户拥有可以动态更改的不同功能集
  • 客户可以开发自己的功能并进行部署。
  • 应用是同构的,有当前版本,但客户的版本提升仍然可以单独处理。
  • 应用程序应作为一个整体进行管理,客户共享应易于扩展的资源。

问题:我们应该在标准的 OSGi 框架上构建它,还是使用新兴的应用程序框架之一(Virgo、Aries 或即将推出的 OSGi 标准)更好?

更多背景和一些初步想法:

我们正在构建一个网络应用程序,我们设想它很快就会拥有数百个客户(公司)和数百个用户(员工),否则何必费心;)。我们想让它模块化,因此 OSGi。将来客户自己可能会开发和插入组件到他们的应用程序中,所以我们需要客户隔离。我们还可能希望不同的客户获得不同的功能集。

当不同客户端共享相同的捆绑包时,向应用程序的不同客户端提供不同服务实现的“正确”方式是什么?

我们可以使用应用服务器方法(我们已经研究过 Virgo)并将每个客户的每个捆绑包一次加载到他们自己的“应用程序”中。然而,它并不像拥抱 OSGi。我们没有托管大量应用程序,99% 的服务将共享相同的 impl。为所有客户。我们还希望将应用程序作为一个整体进行管理(配置、监控等)。

可以为每个客户注册(正确配置)一次服务以及一些“客户令牌”属性。这有点混乱,必须使用扩展器模式或 ManagedServiceFactory 来处理?此外,在为客户 A 注册服务之前,还需要获取其每个依赖项的 A 版本。

每个请求都知道“当前”客户,并且可以绑定到线程。每次搜索服务时都必须提供客户令牌有点麻烦。这使得使用像蓝图这样的组件框架变得很困难。为了解决这个问题,我们可以使用服务挂钩来代理每个注册的服务类型,并让代理根据当前客户(线程)分派到正确的实例。

通过实施上述解决方法(hack?)来开始我们的整个 OSGi 体验真的感觉像是我们走错了路。那么我们应该怎么做呢?回到处女座?尝试类似于上面概述的内容?完全不同的东西?!

ps。感谢您一直阅读这里! ;)

【问题讨论】:

  • 我编辑了问题以使其更具体,因此应该更容易接受答案,我真的很想做!我对stackoverflow很陌生,所以请原谅我有点笨拙......

标签: osgi eclipse-virgo


【解决方案1】:

解决方案有几个方面:

首先,您需要找到一种方法来配置您拥有的不同客户。在 ConfigurationAdmin 之上构建解决方案在这里很有意义,因为这样您就可以尽可能地利用现有的 OSGi 标准。您可能想要在上面构建一些东西的原因是 ConfigurationAdmin 允许您配置每个单独的服务,但您可能希望在上面添加一个层,以便您可以更方便地一次性配置整个应用程序(捆绑包的组合)。然后可以将这样的配置转换为服务的单独配置。

向具有客户特定实现的服务添加属性非常有意义。您可以使用 ManagedServiceFactory 对其进行设置,并且该属性使您可以轻松地使用过滤器为正确的客户查找服务。您甚至可以定义一个备用方案,您可以在其中查找特定于客户的服务或通用服务(因为并非所有服务都可能是特定于客户的)。由于您需要将此类过滤器显式添加到您的依赖项中,我建议您采用现有的依赖项管理解决方案并将其扩展为您的特定用例,以便依赖项自动添加正确的客户特定过滤器,而无需您手动指定。我意识到我可能需要在这里详细介绍,请告诉我...

接下来的问题是,如何在您的应用程序中跟踪客户“上下文”。传统上这里只有几个选项,线程本地上下文是最常用的一个。但是,将线程绑定到客户确实会限制您的实现选项,因为通常这可能意味着您必须禁止开发人员自己创建线程,并且很难将某些任务卸载到工作线程池中。如果您决定使用远程服务,情况会变得更糟,因为这意味着您将完全失去上下文。

因此,为了将客户身份从一个组件传递到另一个组件,我个人更喜欢以下解决方案:

  1. 一旦请求进入(例如在您的 HTTP servlet 中),就会以某种方式确定客户 ID。
  2. 将该 ID 明确传递到服务依赖链中。
  3. 仅使用解决方案,例如在单个捆绑包的边界内使用线程局部变量,例如,如果您在捆绑包中使用第三方库,需要这样做来跟踪客户。

【讨论】:

  • 很高兴阅读您的答案,因为它与我最初的想法非常一致。但是安全呢?如果我们继续在标准 OSGi 框架上所有 bundles 平等的道路上,最终是不是很难保持分离?例如,我们必须真正保护“客户服务令牌”,如果它被泄露,那么访问其他客户数据真的很容易..还请发展您对扩展另一个组件框架的想法。
  • 关于安全性,您至少必须为传入的 HTTP 请求设置屏障。保护应用程序的这一方面与 OSGi 几乎没有关系,无论如何您都必须这样做。第二个问题是,您想在 OSGi 框架内强制实施某些安全约束吗?最终,如果您这样做,您需要使用 OSGi 规范的安全部分(默认情况下未启用,例如 Apache Felix 的单独扩展)。关于客户安全令牌,如果您打算在 OSGi 之外公开它,那么它肯定需要受到保护。
  • 关于扩展另一个组件框架(我假设你在谈论依赖管理)我会以 Apache Felix 依赖管理器为例,它使用 Java API 来声明组件依赖,并构建一个层在上面。您可以使用自己的 XML 格式、注释,甚至是另一个 Java API,它们可以自动生成大部分依赖项(例如,在客户上下文中添加过滤器)。请注意,我编写了那个依赖管理器,所以显然我有偏见。 :)
【解决方案2】:

我一直在考虑同样的问题(我认为)一段时间了,希望您对以下类比发表意见。

考虑一系列使用单点登录 (SSO) 基础架构提供访问控制的 Web 应用程序。用户使用 SSO 服务器进行一次身份验证,并且 - 当请求进入时 - 目标 Web 应用程序询问 SSO 服务器用户是否(仍然)经过身份验证,并确定用户是否被授权。授权信息也可能由 SSO 服务器提供。

现在将您的应用程序包视为迷你应用程序。尽管它们不是 Web 应用程序,但使用 SSO 技术进行身份验证和提供授权信息的某种 SSO 捆绑包仍然没有意义吗?每个应用程序包都必须开发或配置为使用 SSO 包来验证身份验证(SSO 令牌),并通过询问 SSO 包是否允许用户访问此应用程序包来验证授权。

SSO 捆绑包维护某种会话存储库,还提供用户属性,例如识别此用户的(某种)数据存储库的信息。这样,您也不会通过(有意义的)“客户服务令牌”,而是通过 SSO 捆绑提供和管理的神秘 SSO 令牌。

【讨论】:

  • 是的,但真正的问题是如何将其映射到 OSGi 模型?我将其视为两个区域。一方面,您对框架的扩展,即使用 ServiceHook 和代理服务控制服务可见性。另一方面,应用程序捆绑。您不希望这些区域之间的接口尽可能不受阻碍和干净的 OSGi。我考虑了很多“服务供应”问题的解决方案,最终我意识到我或多或少设计了自己的服务注册表,并且必须自己处理很多动态。
【解决方案3】:

请注意 Virgo 是基于 Equinox 的 OSGi 容器,因此如果您不想使用 Virgo 的某些特定功能,则不必这样做。但是,如果您确实使用 Virgo,即使对于基本的 OSGi 应用程序,您也会得到很多 benefits。不过,这听起来像是您需要网络支持,它与 Virgo 网络服务器一起开箱即用,并且可以省去您自己拼凑的麻烦。

全面披露:我领导 Virgo 项目。

【讨论】:

  • 哇,你应该是最适合回答的人!以数据提供者服务为例。在 Virgo 模型中,它的所有类都将为每个客户单独加载,而实际上(动态)配置是服务实例之间唯一不同的东西。处女座有没有办法规避这种情况并仍然让客户分离服务实例
  • 我不认为 Virgo 或 OSGi 会强迫您为每个客户单独加载所有类。我不是应用程序开发人员,但我原以为您可以提供一个通用服务工厂,然后让每个客户根据他们的要求实例化一个单独的服务。
猜你喜欢
  • 1970-01-01
  • 2011-10-11
  • 2023-03-19
  • 2013-03-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多