Hi All, First of all, I believe that we must accept the fact that there will be situations in which multiple tenants are hosted by the same OSGi container. I think there will be several use cases in which we cannot effort to start an isolated container for each tenant, for resource consumption reasons or other. That means that we will have to deal with the fact that some services will be tenant aware while others will not. If a developer creates a service that is tenant aware, a separate service instance will be available for each tenant within that container. For a tenant unaware service, there will be only one service instance running to be used by any tenant. Now the problem is how service dependencies between tenant aware and unaware services are resolved. If I created a tenant aware service and have a service dependency on another service, I need to know if that service is tenant aware as I need to define the 'tenantid' service property defining this dependency. But it might be the case that at the time I programmed my tenant aware service, this other service was not tenant aware but has been made tenant aware later on. So that means that we need to think of a way that even for a programmer, it is irrelevant if a service on which his service depends is tenant aware or not. He should just get the proper tenant aware service injected.
<braindump> Now I think the 'context' I'm currently working on might be the/a solution to this problem. In general a 'context' defines the context of an execution. In case of a HTTP request for example, it is a 'request context' and the current tenant could be resolved from the hostname and the current user from the token cookie. In case of a scheduled job, the context is a 'job execution context' and the job itself may define the tenant of that context. In case of a remote service, the context should be send along with the rpc. Anyway, I think that there is always some 'context' and that context determines, amongst many other things, the tenant that is 'active' in the current method invocation. Now if a service is tenant ware, this just means that it reads the current tenant from the available context and acts upon. This would add a little more complexity to the implementation of a tenant aware service as upon each method invocation it needs to pull this tenant information from the context, but we could simplify that for example by using AOP (the tenant is an aspect). However, if the context is available as a service (as I'm planning to), retrieving the current tenant from the context is rather easy and might do for the first implementation. </braindump> Please let me know what you think of this brain dump and if it could contribute to solving our 'tenant problem'. Regards, Ivo -----Original Message----- From: amdatu-developers-bounces at amdatu.org [mailto:[email protected]] On Behalf Of Marcel Offermans Sent: vrijdag 31 december 2010 11:18 To: amdatu-developers at amdatu.org Subject: Re: [Amdatu-developers] Multi-tenancy (and more) design Hello Mark, all, On 31 Dec 2010, at 10:04 , Mark Machielsen wrote: > In the last conference call we concluded that some services will be tenant > aware. For example the Cassandra bundle won't we deployed in every tenant > container because this would not scale. So we now have two options: a tenant > aware bundle, and a bundle which is not tenant aware and runs in every tenant > container. Agreed, in even more generic terms you could say that there are components that provide services (if you need more than one, you need to deploy multiple components) and components that provide service factories (which is our tenant aware option). Then there are different deployment options in the sense that you can deploy all components in the same container, or in different ones. We concluded that if a component is not tenant aware it needs to be deployed in a separate container per tenant. If it is, it can be deployed in one container and, via remote services, be published in each tenant specific container. > Question which arise: > - when to use which option When the savings in resource consumption are worth it, create a multi tenant aware component. In theory, we never need them, if each tenant gets its own container. However, we might not be using the available resources (memory, threads, ports, ...) effectively if we do it like that. At the container level that's why we're considering running multiple JVMs and multiple containers per JVM. At the component level, multi tenancy can help us pool resources. The downsides? Added complexity and individual service invocations will be slower. That last point is important, as normal service calls will be direct method invocations and these will be remote service calls. Even with an efficient implementation, those calls will be significantly slower so any gains of going for a multi tenant aware implementation should be big enough to counteract that. > - what are we going to communicate: is the default tenant aware or not The default, and easiest, is to not make your component tentant aware. > - is it explainable that there are two ways of developing I think so. And if you can't explain it to someone, just tell them there's only one way. ;) > - we should prevent that a bundle is developed as tenant unaware and must be > transformed to tenant aware because of scaling issues. Or worse: a tenant > unaware bundle can be used in a certain application, but not in another > application, because of a different deployment So when in general do you resolve performance issues? A lot of the time they are hard to predict. Of course that does not mean you cannot properly design a component, use scalable algorithms, etc. I don't think there is a generic recipe though. > - when we are building an application where all tenants are the same (for > example BC), why should we develop tenant unaware bundles (besides the > programming model) See above (downsides). However, if you deploy all tenant aware bundles in the same container and there effectively is no "container per tenant" then one of the downsides (slower invocations) can be avoided. If the added complexity is no issue, and the lack of isolation is not either, I see no reason not to do it like that. As a side note, if you're running an application for tenants A, B and C and suddenly A starts consuming a lot of resources, a cluster manager might decide to migrate A to a different container. Without trying to start a full thread in this discussion about how to migrate components, migrating some tenants of a multi tenant aware component might also be more difficult and you have to take that into account as well. > @Bram: for the cons you state "I got OOM at 500 tenant with 256M memory in > poc setup": what causes this OOM? It seems to me as a pretty simple > application which only 500 tenants (and sure, only 256M memory). It is the > overhead of 500 containers or something else? My guess would be it is, but you can quite easily run a benchmark that instantiates and starts 500 completely empty containers and measure memory consumption. Only half a megabyte of memory for a container does not sound too bad. > What would be the memory footprint for BC assuming all BC specific bundles > are tenant unaware, assuming BC also needs memory for caching purposes. I'll leave that one to Bram, but in general I think it's a hard question to answer because I cannot imagine that it's independent of how BC is being used. Unless you're talking about code size, not runtime consumption. > How well does it scale when I have a small application (eg openID server) > with lots of tenants. You'll have the overhead of each OSGi framework instance (which you can measure as mentioned above). Other than that, there should not be much overhead if each tenant uses its own data. I mean you might be able to more effectively share resources if you have a multi tenant aware implementation (one pool for every shared resource instead of lots of smaller pools) but that's about it. > A more practical question: assume I have a tenant unaware service with a REST > interface. I assume the REST is received by the tenant aware HTTP service > (which listens to a certain port) in the tenant aware container. How is this > call forwarded to the tenant unaware service? I don't think we currently have > a mechanism to go from tenant aware to tenant unaware, where you need to know > in what container the tenant lives. So far we only talked about OSGi services, and there we use remote services to publish the right tenant service into its container. For REST services, there is no such thing as a service registry, so we cannot discover them. That means we need to somehow configure them. In this case it means we need to map each tenant onto the appropriate REST URL. Greetings, Marcel _______________________________________________ Amdatu-developers mailing list Amdatu-developers at amdatu.org http://lists.amdatu.org/mailman/listinfo/amdatu-developers

