2011-02-07 10 views
7

Stiamo sviluppando un web-application (consente di chiamare una banca immagini) per il quale abbiamo individuato le seguenti esigenze:Come fornitura di servizi OSGi per cliente

  • L'applicazione si rivolge ai clienti che consistono in una serie di utenti.
  • Un nuovo cliente possono essere creati in modo dinamico e un cliente gestisce i suoi utenti
  • clienti hanno diversi set di funzionalità che possono essere modificati dinamicamente
  • clienti possono sviluppare le proprie caratteristiche e li hanno distribuiti.
  • L'applicazione è omogenea e ha una versione corrente, ma la versione di sollevamento dei clienti può ancora essere gestita individualmente.
  • L'applicazione deve essere gestita nel suo complesso e i clienti condividono le risorse che dovrebbero essere facilmente scalabili.

Domanda: Dovremmo costruire questo su un framework OSGi standard o ci sarebbe stato meglio di utilizzare uno dei framework applicativi emergenti (Virgo, Ariete o moderno standard OSGi)?

più di fondo e alcune riflessioni iniziali:

Stiamo costruendo una web-app, che prevediamo avrà presto centinaia di clienti (aziende) con centinaia di utenti ciascuno (dipendenti), altrimenti perché fastidio;). Vogliamo renderlo modulare quindi OSGi. In futuro i clienti stessi potrebbero sviluppare e integrare componenti per la loro applicazione, quindi abbiamo bisogno dell'isolamento del cliente. Potremmo anche volere che clienti diversi ottengano set di funzionalità differenti.

Qual è il modo "corretto" per fornire diverse implementazioni di servizi a diversi client di un'applicazione quando diversi client condividono gli stessi bundle?

Potremmo utilizzare l'approccio app-server (abbiamo esaminato Virgo) e caricare ogni pacchetto una volta per ogni cliente nella propria "app". Tuttavia non ha voglia di abbracciare OSGi. Non stiamo ospitando una moltitudine di applicazioni, il 99% dei servizi condividerà la stessa impl. per tutti i clienti. Inoltre vogliamo gestire (configurare, monitorare ecc.) L'applicazione come una sola.

Ogni servizio può essere registrato (correttamente configurato) una volta per ciascun cliente insieme ad alcune proprietà "cliente-token". È un po 'disordinato e dovrebbe essere gestito con un pattern di estensione o forse un ManagedServiceFactory? Inoltre, prima di registrare un servizio per il cliente A sarà necessario acquisire la versione A di ciascuna delle sue dipendenze.

Il cliente "corrente" sarà noto a ciascuna richiesta e può essere associato alla discussione. È un po 'un casino dover fornire un token cliente ogni volta che si cerca un servizio. Rende difficile l'utilizzo di framework di componenti come blueprint. Per aggirare il problema, è possibile utilizzare i ganci di servizio per eseguire il proxy di ciascun tipo di servizio registrato e lasciare che il proxy venga inviato all'istanza corretta in base al cliente corrente (thread).

Iniziare la nostra intera esperienza OSGi implementando la soluzione alternativa (hack?) Sopra sembra davvero un'indicazione che siamo sulla strada sbagliata. Quindi cosa dovremmo fare? Torna alla Vergine? Prova qualcosa di simile a ciò che è descritto sopra? Qualcosa di completamente diverso ?!

ps. Grazie per aver letto fino in fondo!;)

+0

Ho modificato la domanda per renderla più concreta, quindi dovrebbe essere più semplice accettare una risposta, che voglio davvero fare! Sono abbastanza nuovo per lo stackoverflow quindi scusami per essere un po 'goffo ... –

risposta

5

Ci sono un paio di aspetti da una soluzione:

Prima di tutto, è necessario trovare un modo per configurare i diversi clienti che avete. Costruire una soluzione su ConfigurationAdmin ha senso qui, perché in questo modo è possibile sfruttare il più possibile lo standard OSGi esistente. Il motivo per cui potresti voler costruire qualcosa in cima è che ConfigurationAdmin ti permette di configurare ogni singolo servizio, ma potresti voler aggiungere un layer in cima in modo da poter configurare più comodamente l'intera applicazione (l'insieme dei bundle) in un colpo solo. Tale configurazione può quindi essere tradotta nelle singole configurazioni dei servizi.

L'aggiunta di una proprietà ai servizi che hanno implementazioni specifiche per il cliente ha molto senso. È possibile impostarli utilizzando un ManagedServiceFactory e la proprietà semplifica la ricerca del servizio per il cliente giusto utilizzando un filtro. È anche possibile definire uno scenario di fallback in cui si cerca un servizio specifico per il cliente o uno generico (perché non tutti i servizi saranno probabilmente specifici del cliente). Poiché devi aggiungere esplicitamente tali filtri alle tue dipendenze, ti consigliamo di utilizzare una soluzione di gestione delle dipendenze esistente ed estenderla per il tuo caso d'uso specifico, in modo che le dipendenze aggiungano automaticamente i filtri specifici del cliente giusto senza doverli specificare manualmente. Mi rendo conto che potrei andare più nel dettaglio qui, fammelo sapere ...

La prossima domanda è quindi, come tenere traccia del "contesto" del cliente all'interno della vostra applicazione. Tradizionalmente ci sono solo alcune opzioni qui, con un contesto locale del thread che è il più usato. I thread di binding ai clienti tendono a limitare l'utente in termini di opzioni di implementazione, poiché in generale probabilmente significa che è necessario proibire agli sviluppatori di creare thread stessi ed è difficile scaricare alcune attività nei pool di thread di lavoro. Diventa ancora peggio se decidi di utilizzare Servizi remoti in quanto ciò significa che perderai completamente il contesto.

Quindi, per il passaggio sulla identificazione del cliente da un componente all'altro, io personalmente preferisco una soluzione in cui:

  1. Non appena la richiesta arriva (per esempio nel vostro servlet HTTP) determinano in qualche modo il cliente ID.
  2. Trasferisci esplicitamente tale ID lungo la catena delle dipendenze del servizio.
  3. Utilizzare solo soluzioni come l'utilizzo di thread locals all'interno dei confini di un singolo bundle, se ad esempio si sta utilizzando una libreria di terze parti all'interno del pacchetto che necessita di questo per tenere traccia del cliente.
+0

È bello leggere la tua risposta perché è praticamente in linea con ciò che inizialmente avevo pensato. Ma per quanto riguarda la sicurezza? Se continuiamo sulla strada di tutti i pacchetti uguali sul framework standard OSGi, non sarà alla fine molto difficile mantenere la separazione? Ad esempio, dobbiamo davvero proteggere il "token del servizio clienti" se questo è fuoriuscito sarebbe davvero facile accedere a dati di altri clienti .. Si prega inoltre di sviluppare le vostre idee sull'estensione di un altro quadro di componenti. –

+1

Per quanto riguarda la sicurezza, è necessario almeno creare una barriera per le richieste HTTP in arrivo. L'aspetto di proteggere un'applicazione ha poco a che fare con OSGi, dovresti farlo comunque. La seconda domanda è: vuoi applicare determinati vincoli di sicurezza all'interno del framework OSGi? In definitiva, se lo fai, devi usare la parte di sicurezza della specifica OSGi (non abilitata di default, ad esempio un'estensione separata per Apache Felix). Per quanto riguarda il token di sicurezza del cliente, se si tratta di qualcosa che si intende esporre al di fuori di OSGi, è necessario proteggerlo. –

+1

Per quanto riguarda l'estensione di un altro framework di componenti (presumo che si stia parlando di gestione delle dipendenze), ad esempio, prenderei Apache Felix Dependency Manager, che usa un'API Java per dichiarare dipendenze dei componenti e costruirne uno sopra. È possibile utilizzare il proprio formato XML, o annotazioni o anche un'altra API Java che automatizza gran parte della generazione di dipendenze (ad esempio, aggiungendo filtri nei contesti dei clienti). Nota che ho scritto quel responsabile delle dipendenze, quindi ovviamente sono di parte. :) –

1

Ho pensato a questo stesso problema (credo) da un po 'di tempo e vorrei le vostre opinioni sulla seguente analogia.

Considerare una serie di applicazioni Web in cui si fornisce il controllo dell'accesso utilizzando un'infrastruttura SSO (single sign-on). L'utente effettua l'autenticazione una sola volta utilizzando il server SSO e, quando arriva una richiesta, l'applicazione Web di destinazione chiede al server SSO se l'utente è (ancora) autenticato e determina se stesso se l'utente è autorizzato. Le informazioni di autorizzazione potrebbero anche essere fornite dal server SSO.

Ora pensa ai pacchetti di applicazioni come mini-applicazioni. Anche se non sono applicazioni Web, non avrebbe ancora senso disporre di una sorta di pacchetto SSO che utilizza tecniche SSO per eseguire l'autenticazione e fornire informazioni di autorizzazione? Ogni bundle di applicazioni dovrebbe essere sviluppato o configurato per utilizzare il pacchetto SSO per convalidare l'autenticazione (token SSO) e convalidare l'autorizzazione chiedendo al pacchetto SSO se l'utente è autorizzato ad accedere a questo pacchetto di applicazioni.

Il bundle SSO mantiene una sorta di repository di sessione e fornisce anche proprietà utente, ad es. informazioni per identificare il repository di dati (di qualche tipo) di questo utente. In questo modo non si passa nemmeno attraverso un "significativo" token del servizio clienti, ma piuttosto un criptato token SSO che viene fornito e gestito dal bundle SSO.

+0

Sì, ma la vera domanda è come si mappa questo al modello OSGi? Lo vedo come due regioni. Da un lato le estensioni al framework, ovvero il controllo della visibilità del servizio con ServiceHooks e i servizi di proxy. E dall'altra parte i pacchetti di applicazioni. Non vorresti che l'interfaccia tra queste regioni fosse la più libera e pulita possibile per OSGi. Ho pensato a molte soluzioni al problema del "provisioning del servizio", in cui alla fine mi rendo conto di avere più o meno progettato il mio registro di servizio personale e di dover gestire personalmente molte delle dinamiche. –

1

Si prega di notare che Virgo è un contenitore OSGi basato su Equinox, quindi se non si desidera utilizzare alcune funzioni specifiche della Vergine, non è necessario. Tuttavia, riceverai un sacco di benefits se usi Virgo, anche per un'applicazione OSGi di base. Sembra, però, che tu voglia il supporto web, che esce dalla scatola con il server web Virgo e ti risparmierai il problema di metterlo insieme.

Divulgazione completa: guido il progetto Virgo.

+0

Wow, dovresti essere l'uomo perfetto per rispondere! Prendiamo ad esempio un servizio di fornitore di dati. Nel modello Virgo tutte le sue classi verrebbero caricate separatamente per ogni cliente, mentre in realtà la configurazione (dinamica) è l'unica cosa che differisce tra le istanze del servizio. C'è un modo in Virgo per aggirare questo e ottenere comunque la separazione del servizio clienti ** istanze **? –

+0

Non penso che Virgo, o OSGi, per questo, ti costringa a caricare tutte le classi separatamente per ogni cliente. Non sono uno sviluppatore di applicazioni, ma avrei pensato che potessi fornire una fabbrica di servizi generali e quindi fare in modo che ogni cliente istituisca un servizio separato in base alle sue esigenze. –