Last year I been working for 6 months on a project to turn a system built on 
top of osgi from single to multi tenant.
We used mixed approach and I can share what worked well and what caused 
troubles.

First of all, there is very little OSGi itself can do for you in order to 
support multi tenancy if your application is not handling this kind of 
deployment scenario already.
I had a bunch of implicit and explicit correlations spread over codebase which 
got documented and used properly over time. Main trouble is connecting values 
set in configuration with data and authentication. Remember that our system was 
a single tenant and idea to have multiple entities accessing same system 
instance was first of all brave and second of all tricky to handle properly. 
Additionally we were forced to keep a single tenant behavior, meaning access to 
all data, for limited set of power users.

Reason why I’m saying that there is very little OSGi can do is because you need 
to decide how tenant information gets into system and how requests (if any) are 
matched with them. In our case we had bunch of http endpoints, messaging queues 
and databases linked together.
One of places which worked quite stable was powered by chain of service 
trackers. For every configured database connection which had tenant id set we 
published new http endpoint (daos-> services -> http endpoint to be precise) 
which was then called by 3rd party system.
In other places we had a static http endpoints used by user interface which, 
based on authentication information, was pushing this information down the hill 
to lower layers of system. Parts of systems which were built before multi 
tenancy got few changes in order to propagate user/tenant context (thread local 
but not only).
Most difficult part was cache management which took us over a month to 
stabilize. I think that from time perspective it would be much better to write 
some parts of system from scratch and follow above scenario with db connection 
because at some point we really got quite magic setup. 
Depending on assembly/distribution we had a different set of persistence and 
cache implementation bundles which were aware of tenant context. Thanks to that 
we had a physical data separation.
Whole thing worked, and I believe it still works, but debugging and maintenance 
of it become quite difficult.
Because amount of static endpoints was quite high - I think we reached about 
200 if not more different operations where some of them had several hundred 
lines of code to join and analyze data  before returning it to ui we couldn’t 
manage them easily. We thought that pushing tenant context will save us a time, 
but in the end it still requires a lot of work. Some operations worked out of 
the box, quite many required tweaking. Some we had to write from scratch using 
higher level apis instead of raw db access in order to propagate tenant 
information to persistence layer.
Given past experiences I got in this field I would recommend you to select 
dynamically a backend service for tenant as early as possible and dispatch 
request to it.

Sadly OSGi service factories will not help much in this area because they are 
linked with bundles. You can’t rely on find hooks alone because they will 
require unique bundles for tenants and results of their calls are kept over 
time. You can try to use them to inject tenant selection logic but it will work 
only with prototype scope (service lookup upon each request). 

Cheers,
Łukasz Dywicki

> On 1 Jul 2018, at 21:03, David Leangen via osgi-dev <osgi-dev@mail.osgi.org> 
> wrote:
> 
> 
> Hi Clément,
> 
> We ended up doing this via ServiceFactory.
> 
> A service is either “tenant-aware” (meaning that the tenant logic is built 
> into the service), or more commonly “tenant-unaware” (meaning that it’s like 
> you write below: the service has no knowledge of the tenant). For those that 
> are tenant-aware, we only need one instance (assuming it is a singleton). For 
> those that are not tenant-aware, we need once instance per tenant. All we 
> need to do for a tenant-aware service is add the “factory” property to the 
> component. The FactoryService listens for both tenants and tenant-aware 
> services, and will instantiate a tenant-aware service as required. This 
> allows us to dynamically adapt if a new tenant is registered.
> 
> This approach has also allowed us to customize services for a specific tenant 
> as required, which was an unexpected bonus.
> 
> All services that can be shared are shared, which means that I think (have 
> not actually calculated) that we are using computing resources efficiently.
> 
> In any case, this has been working well for us so far.
> 
> Cheers,
> =David
> 
> 
>> On Jul 2, 2018, at 2:11, Clément Delgrange via osgi-dev 
>> <osgi-dev@mail.osgi.org> wrote:
>> 
>> Hi,
>> 
>> What is the way to achieve multi-tenancy with OSGI service. I would like to 
>> design my API without a tenant context per method to concentrate on the 
>> functional part, but also have an OSGI instance which could be scaled up. I 
>> was thinking to let the service implementation  decides if the service can 
>> be shared between multiple tenants or not, and in this later case rely on a 
>> standard way to bound service instances specifically for a tenant. Does 
>> configuration admin can help with this?
>> For example, a service could be configured with multiple PIDs, one for 
>> shared configuration and one factory configuration for tenant specific 
>> configuration and then filter references in component, does that could work? 
>> Is there some good practice for multi tenancy in OSGI?
>> 
>> Thanks,
>> Clément.
>> 
>> 
>> 
>> _______________________________________________
>> OSGi Developer Mail List
>> osgi-dev@mail.osgi.org
>> https://mail.osgi.org/mailman/listinfo/osgi-dev
> 
> _______________________________________________
> OSGi Developer Mail List
> osgi-dev@mail.osgi.org
> https://mail.osgi.org/mailman/listinfo/osgi-dev
_______________________________________________
OSGi Developer Mail List
osgi-dev@mail.osgi.org
https://mail.osgi.org/mailman/listinfo/osgi-dev

Reply via email to