Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the best way to make bundles run parallel, threaded, in OSGI

I'm working with the OSGI framework to make an application that heavily relies on processing of packages of data.

Every bundle processes a package and then sends it to the next. What I want is that every bundle works parallel. So I want to make every bundle run in it's own Thread or multiple Threads. The 'problem' is that OSGI doesn't really support multithreading. Every bundle running on the same JVM just runs in 1 Thread, so it follows a synchronous model.

My thoughts: So the nature of the application is kinda producer consumer like. Bundle A offers a service with a method that is used to send a package to A, let's call it method ain. Bundle B has a likewise setup, and so does C. They all have a a/b/cout method, in this method they use the service of the next bundle so in A.aout you would call bin like this: bservice.bin(package).

So every bundle is a consumer and a producer of data packages, this leads me to think that using ExecutorService and BlockingQueues might work, but I'm not quite sure how to implement this 'correctly' between bundles, and with all of them being both Consumer and Producer I'm not quite sure if this is the best way to go around this problem.

I hope you guys can help and/or have any suggestions.

-- EDIT --

Bundle A AServiceImplementation

public class AServiceImplementation implements AService {

    private BService bservice;

    public void bindBService(BService service) {
        bservice = service;
        System.out.println("bundle gateway bound to b service");
    }

    public void unbindBService(BService service) {
        this.bservice = null;
    }

    public void process(int id) {
        bservice.transmitIn(id);        
    }
}

Bundle B BServiceImplementation

public class BServiceImplementation implements BService {

    private CService cservice;

    public void bindCService(CService service) {
        cservice = service;
        System.out.println("bundle gateway bound to b service");;
    }

    public void unbindCService(CService service) {
        this.cservice = null;
    }

    public void transmitIn(int id){
        // So if I would implement it THIS is where I would assign the data to 
        // a thread to get it processed in the process method.
        // but doesn't that make THIS method, transmitIn a bottleneck since all packages
        // need to pass through here?
        process(id);
    }

    public void process(int id) {
        // Lots of processing happens here  
    }
}

I don't really understand how to make it that for example bundle A transmits the data to bundle B through the transmitIn method without transmitIn being a bottleneck, since I'd make my 'workdistribution' to different threads in that method (as seen in the code above)

like image 769
Spyral Avatar asked Dec 08 '22 14:12

Spyral


1 Answers

Ahum, a full misunderstanding. OSGi could not care less what you do with concurrency, one of its great advantages is that it does not change the computing model like so many app servers do. From a bundle or package point of view, threads are utterly irrelevant. So any Java solution works here.

In your example all processing would take place on the initial callers thread, the one that calls AServiceImplementation. If you want to have processing in parallel you can use an executor for every task you submit, this is the pattern where Executors come in handy. This makes the processing async so you have no return value. Watch out that processing will be limited by the # of available threads in the Executor you provide. You also have to write your processing code very careful to handle proper synchronization for non-local variables.

Another method is to queue. Each service call creates an object with the task's information and this object is then posted into a blocking queue. In an OSGi activator you create a Thread that reads the queue and processes it. In this model you can process without worrying (too much) about concurrency since all the processing always happens in the same thread. For performance reasons you could start multiple threads, but processing is than a bit harder.

However, my advice is to skip this optimization and built your system as simple as possible first. If it runs, and you find you have performance problems, it is early enough to start worrying about these issues. With your current level of understanding I am afraid that you stand the chance to create a highly complex solution to a 'possible' problem.

like image 78
Peter Kriens Avatar answered Dec 11 '22 04:12

Peter Kriens