Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Fürs Karma: Konfiguration zur Laufzeit

Fürs Karma: Konfiguration zur Laufzeit

Anwendungen benötigen Konfigurationsdaten: für die Adressen der Nachbarsysteme und fachliche Parameter. Wie wäre es, wenn Änderungen zur Laufzeit möglich sind - ohne Wartungsfenster, für alle Knoten im Cluster auf einmal? Und neue Funktionen ohne Redeployment aktiviert werden?
Ist Konfiguration zur Laufzeit einmal eingebaut, so macht es das Leben von Fachabteilung, Entwicklern, Betrieb und Anwendern einfacher. Es werden Beispiele auf Basis der Open-Source-Projekte Togglz, Netflix Archaius und CoreOS etcd vorgestellt.

Alexander Schwartz

March 09, 2016
Tweet

More Decks by Alexander Schwartz

Other Decks in Technology

Transcript

  1. .consulting .solutions .partnership
    Fürs Karma: Konfiguration zur Laufzeit
    Alexander Schwartz, Principal IT Consultant
    JavaLand – 9. März 2016

    View full-size slide

  2. Konfiguration zur Laufzeit
    © msg | Konfiguration zur Laufzeit | Alexander Schwartz | JavaLand 2016 | 9. März 2016 2
    Alltägliche Konfigurationsänderungen
    1
    Archaius: Zugriff auf sich ändernde Konfigurationen
    2
    etcd: Zentrale Konfigurationsdatenbank
    3
    Consul und Ribbon: Service Discovery für Clients
    4
    Togglz: Aktivieren von neuen Funktionen steuern
    5
    Besser mit Konfiguration zur Laufzeit?
    6

    View full-size slide

  3. Mein Sponsor und Arbeitgeber – msg systems ag
    © msg | Konfiguration zur Laufzeit | Alexander Schwartz | JavaLand 2016 | 9. März 2016 3
    1980 gegründet
    mehr als 5.500 Kollegen
    727 Mio € Umsatz 2015
    24 Länder
    in 14 Städten
    in Deutschland präsent

    View full-size slide

  4. Wer ich bin – Alexander Schwartz
    © msg | Konfiguration zur Laufzeit | Alexander Schwartz | JavaLand 2016 | 9. März 2016 4
    13 Jahre Java
    7 Jahre PL/SQL
    7 Jahre
    Absatzfinanzierung
    3,5 Jahre Direktbank
    1 Frau
    2 Kinder
    458 gefundene
    Geocaches
    @ahus1de

    View full-size slide

  5. Konfiguration zur Laufzeit
    © msg | Konfiguration zur Laufzeit | Alexander Schwartz | JavaLand 2016 | 9. März 2016 5
    Alltägliche Konfigurationsänderungen
    1
    Archaius: Zugriff auf sich ändernde Konfigurationen
    2
    etcd: Zentrale Konfigurationsdatenbank
    3
    Consul und Ribbon: Service Discovery für Clients
    4
    Togglz: Aktivieren von neuen Funktionen steuern
    5
    Besser mit Konfiguration zur Laufzeit?
    6

    View full-size slide

  6. Alltägliche Konfigurationsänderungen
    Wenn eine Konfigurationsänderung einen Neustart erfordert, so kann
    dies nur im Wartungsfenster erfolgen
    © msg | Konfiguration zur Laufzeit | Alexander Schwartz | JavaLand 2016 | 9. März 2016 6
    Die Kundendatenbank hat eine neue IP-
    Adresse, bitte passe die Konfiguration der
    Online-Registrierung an.
    Kein Problem, habe ich geändert, ich muss die
    Anwendung heute Nacht nur noch neu starten!
    Bin ich ein Held, weil ich mitten in
    der Nacht aufstehe, um die
    Anwendung neu zu starten?

    View full-size slide

  7. Alltägliche Konfigurationsänderungen
    Wenn neue Funktionen durch ein Deployment aktiviert werden, ist ein
    Fallback schwierig möglich
    © msg | Konfiguration zur Laufzeit | Alexander Schwartz | JavaLand 2016 | 9. März 2016 7
    Die neue Funktion in der Anwendung, könnt ihr
    die bitte freischalten?
    Ok, dann rollen wir die neue
    Anwendungsversion jetzt aus. Dann können
    alle Anwender darauf zugreifen.
    Sollte man das wirklich an
    einem Freitagabend tun?

    View full-size slide

  8. Alltägliche Konfigurationsänderungen
    Konfigurationen zur Laufzeit spart Zeit und Nerven – und vermeidet Wartungsfenster
    © msg | Konfiguration zur Laufzeit | Alexander Schwartz | JavaLand 2016 | 9. März 2016 8
    • Parameter der Anwendung zur Laufzeit ändern
     Ziel-Adressen für Server
     Verzeichnisnamen
     Timeouts und fachliche Parameter
    • Zentrale Konfigurationsdatenbank
     Konfigurationsparameter
     Service-Discovery
    • Aktivieren von neuen Funktionen steuern
     Für bestimmte Kunden oder Nutzer
     Für einen Teil der Kunden
     Zeitgesteuerte Aktivierung

    View full-size slide

  9. Alltägliche Konfigurationsänderungen
    Karma: Jede unserer Handlungen hat eine Folge für uns selbst
    © msg | Konfiguration zur Laufzeit | Alexander Schwartz | JavaLand 2016 | 9. März 2016 9
    • Wir sind verantwortlich für unser Tun
    • Konfigurationsänderung soll zum gewünschten Ergebnis führen
    – ohne andere zu beeinträchtigen
    • Einsicht: Konfigurationen ändern sich regelmäßig
    • Güte: Wir sind freundlich zu den Nutzern und brauchen
    dafür kein Wartungsfenster
    • Bescheidenheit: Wir verzichten darauf, als „Helden“
    die Konfiguration mitten in der Nacht zu ändern

    View full-size slide

  10. Konfiguration zur Laufzeit
    © msg | Konfiguration zur Laufzeit | Alexander Schwartz | JavaLand 2016 | 9. März 2016 10
    Alltägliche Konfigurationsänderungen
    1
    Archaius: Zugriff auf sich ändernde Konfigurationen
    2
    etcd: Zentrale Konfigurationsdatenbank
    3
    Consul und Ribbon: Service Discovery für Clients
    4
    Togglz: Aktivieren von neuen Funktionen steuern
    5
    Besser mit Konfiguration zur Laufzeit?
    6

    View full-size slide

  11. Netflix Archaius
    Netflix Archaius regelt den Zugriff auf Parameter für Java-Clients
    © msg | Konfiguration zur Laufzeit | Alexander Schwartz | JavaLand 2016 | 9. März 2016 11
    1. Laden von Konfigurationdaten
    aus: Properties-Dateien, URLs, Datenbanken
    2. Kaskadierte Konfigurationen
    für: Standardeinstellungen, verschiedene Umgebungen,
    einzelne Server
    3. Typsicherer Zugriff auf den aktuellen Wert
    4. Callbacks, wenn sich ein Wert ändert Quelle: http://en.wikipedia.org/wiki/Archaius_tigris
    (CC) Hans Stieglitz

    View full-size slide

  12. Netflix Archaius
    Beim Start kann zusätzlich eine Umgebung mitgegeben werden
    © msg | Konfiguration zur Laufzeit | Alexander Schwartz | JavaLand 2016 | 9. März 2016 12
    java
    -Darchaius.deployment.environment=test
    ...
    # database.properties
    db.url=jdbc:postgresql://localhost:5432/standard-db
    # database-test.properties
    db.url=jdbc:postgresql://localhost:5432/test-db
    // Java Startup
    ConfigurationManager.loadCascadedPropertiesFromResources("database");

    View full-size slide

  13. Netflix Archaius
    Die Java-Anwendung wird mit Angabe der Konfigurationsdatei gestartet
    © msg | Konfiguration zur Laufzeit | Alexander Schwartz | JavaLand 2016 | 9. März 2016 13
    java
    -Darchaius.configurationSource.additionalUrls=file:///.../archaius.properties
    -Darchaius.fixedDelayPollingScheduler.delayMills=1000
    -Darchaius.fixedDelayPollingScheduler.initialDelayMills=1000
    –jar application.jar
    # archaius.properties
    app.timeout=1000
    app.url=http://myserver:3000/

    View full-size slide

  14. // construct type safe accessor for property
    DynamicIntProperty timeoutProperty =
    DynamicPropertyFactory.getInstance()
    .getIntProperty("app.timeout", 10);
    // access current value
    int timeout = timeoutProperty.get();
    // get notified once the value changes
    timeoutProperty.addCallback(() -> {
    System.out.println("property has changed: " + property.get());
    });
    Netflix Archaius
    Archaius ermöglicht typsicheren Zugriff auf den aktuellen Wert
    © msg | Konfiguration zur Laufzeit | Alexander Schwartz | JavaLand 2016 | 9. März 2016 14
    Callbacks werden aufgerufen, wenn sich ein Parameterwert ändert.

    View full-size slide

  15. Netflix Archaius
    Überlegungen Pro und Kontra Archaius
    © msg | Konfiguration zur Laufzeit | Alexander Schwartz | JavaLand 2016 | 9. März 2016 15
    Pro:
    • Konfigurationen können wie gehabt als Datei ausgerollt werden
    (z. B. mit Chef, Puppet, Ansible, Salt)
    • Verschiedene Ablagemöglichkeiten außer Dateien werden unterstützt
    • Hierarchische Struktur vereinfacht die Konfiguration
    • Erprobte Bibliothek basierend auf der Apache Commons Configuration API
    • Callback-Funktion ermöglicht komplexe Rekonfiguration
    Kontra:
    • Zeitgleiche konsistente Änderung mehrerer Parameter kann je nach Ablageart eine Herausforderung
    sein
    Ähnliche Projekte und Weiterentwicklungen:
    Apache DeltaSpike, Apache Commons Configuration 2.0 und Archaius 2.0, Apache Tamaya

    View full-size slide

  16. Konfiguration zur Laufzeit
    16
    © msg | Konfiguration zur Laufzeit | Alexander Schwartz | JavaLand 2016 | 9. März 2016
    Alltägliche Konfigurationsänderungen
    1
    Archaius: Zugriff auf sich ändernde Konfigurationen
    2
    etcd: Zentrale Konfigurationsdatenbank
    3
    Consul und Ribbon: Service Discovery für Clients
    4
    Togglz: Aktivieren von neuen Funktionen steuern
    5
    Besser mit Konfiguration zur Laufzeit?
    6

    View full-size slide

  17. CoreOS etcd
    etcd ist eine zentrale Konfigurationsdatenbank
    © msg | Konfiguration zur Laufzeit | Alexander Schwartz | JavaLand 2016 | 9. März 2016 17
    Geeignet für Konfiguration und Service Discovery
    • Einfach: HTTP/REST mit JSON
    • Zuverlässig: hochverfügbar und konsistent
    • Sicher: optional mit SSL-Client-Zertifikaten
    • Schnell: mehrere Tausend Schreiboperationen pro Sekunde
    Operationen: GET/PUT/DELETE/CAS/WAIT/TTL
    # PUT
    curl -L -X PUT http://127.0.0.1:4001/v2/keys/foo-service/container1 –d value="localhost:1111"
    # GET
    curl -L http://127.0.0.1:4001/v2/keys/foo-service/container1
    # WAIT
    curl -L http://127.0.0.1:4001/v2/keys/foo-service?wait=true\&recursive=true

    View full-size slide

  18. CoreOS etcd + Hightower´s confd
    Wenn sich Werte in etcd ändern, aktualisiert confd die Konfiguration
    © msg | Konfiguration zur Laufzeit | Alexander Schwartz | JavaLand 2016 | 9. März 2016 18
    confd

    View full-size slide

  19. CoreOS etcd + Hightower´s confd
    Wenn sich Werte in etcd ändern, aktualisiert confd die Konfiguration
    © msg | Konfiguration zur Laufzeit | Alexander Schwartz | JavaLand 2016 | 9. März 2016 19
    • Service-Beschreibung (*.toml)
    • Vorlage für die Konfigurationsdatei (*.tmpl)
    # nginx.toml
    [template]
    src = "nginx.tmpl"
    dest = "/etc/nginx/sites-enabled/app.conf"
    keys = [ "/foo-service" ]
    check_cmd = "/usr/sbin/nginx -t"
    reload_cmd = "/usr/sbin/service nginx reload"
    # nginx.tmpl
    upstream app_pool {
    {{ range getvs "/foo-service/*" }}
    server {{ . }};
    {{ end }}
    }
    confd

    View full-size slide

  20. CoreOS etcd + Jurmous´ Java Client
    Jurmos Java Client spricht etcd über ein Java API an
    © msg | Konfiguration zur Laufzeit | Alexander Schwartz | JavaLand 2016 | 9. März 2016 20
    • Java-API für alle etcd-Funktionen
    • Implementiert auf Basis von Netty (für asynchrones, non-blocking IO)
    // Simple put
    etcd.put("/foo-service/container1","localhost:1111").send();
    // Wait for next change on foo
    EtcdResponsePromise promise = etcd.getDir("/foo-service/")
    .recursive().waitForChange().send();
    // Java 8 lambda construction
    promise.addListener(promise -> {
    // do something with change
    });

    View full-size slide

  21. CoreOS etcd
    Überlegungen Pro und Kontra etcd
    © msg | Konfiguration zur Laufzeit | Alexander Schwartz | JavaLand 2016 | 9. März 2016 21
    Pro:
    • Einfacher Zugriff (REST), einfache Installation (Go-Binary), Transport-Sicherheit (SSL)
    • Änderungen werden sofort an die Clients weitergegeben
    • Generische Struktur für flexiblen Einsatz
    Kontra:
    • Keine Zugriffsbeschränkung für einzelne Clients
    • Junges Open-Source-Projekt
    Ergänzungen und Alternativen:
    • Vulcan (HTTP Load Balancer, Konfigurationsablage in etcd)
    • SkyDNS (Servicediscovery über DNS, Datenablage in etcd)
    • Apache Zookeeper (zentrale Konfigurationsdatenbank und Synchronisation)
    • Hazelcast (Leader Election, Distributed Locks, Topics, In-Memory-Data-Grid)
    • Netflix Eureka (Servicediscovery)
    • Hashicorp Consul (Servicediscovery und Konfigurationsdatenbank)

    View full-size slide

  22. Konfiguration zur Laufzeit
    22
    © msg | Konfiguration zur Laufzeit | Alexander Schwartz | JavaLand 2016 | 9. März 2016
    Alltägliche Konfigurationsänderungen
    1
    Archaius: Zugriff auf sich ändernde Konfigurationen
    2
    etcd: Zentrale Konfigurationsdatenbank
    3
    Consul und Ribbon: Service Discovery für Clients
    4
    Togglz: Aktivieren von neuen Funktionen steuern
    5
    Besser mit Konfiguration zur Laufzeit?
    6

    View full-size slide

  23. Hashicorp Consul
    Consul
    © msg | Konfiguration zur Laufzeit | Alexander Schwartz | JavaLand 2016 | 9. März 2016 23
    Geeignet für Service Discovery, Konfiguration und Monitoring
    • Einfach: HTTP/REST mit JSON
    • Zuverlässig: hochverfügbar und konsistent
    • Sicher: eingebaute Access Control Lists und Verschlüsselung
    Haupt-Sponsor: HashiCorp (die, die auch Vagrant machen)
    Homepage: https://www.consul.io/

    View full-size slide

  24. Netflix Ribbon
    Ribbon
    © msg | Konfiguration zur Laufzeit | Alexander Schwartz | JavaLand 2016 | 9. März 2016 24
    Geeignet für Client-Seitiges Load-Balancing
    • Ribbon arbeitet gut zusammen mit Feign: Typsichere Web-APIs
    • Feign arbeitet gut zusammen mit Hystrix: Roboste Synchrone Schnittstellen
    Haupt-Sponsor: Netflix
    Homepage: https://github.com/Netflix/ribbon/

    View full-size slide

  25. Consul und Ribbon
    Der Client nimmt direkt Verbindung mit dem funktionierenden Service auf
    © msg | Konfiguration zur Laufzeit | Alexander Schwartz | JavaLand 2016 | 9. März 2016 25
    Ein hochverfügbares
    Consul-Server-Ensemble
    (für Key-Value-Store
    und Service-Catalog)
    Services
    Client

    View full-size slide

  26. Consul und Ribbon
    Anwendungs-Code für Ribbon
    © msg | Konfiguration zur Laufzeit | Alexander Schwartz | JavaLand 2016 | 9. März 2016 26
    MyService api = HystrixFeign.builder()
    .contract(new JAXRSContract())
    .encoder(new JacksonEncoder())
    .decoder(new JacksonDecoder())
    .client(RibbonClient.builder()
    .lbClientFactory(new ConsulLbFactory())
    .build())
    .target(MyService.class, "http://web");
    api.call();

    View full-size slide

  27. Consul und Ribbon
    Glue-Code für Ribbon und Consul
    © msg | Konfiguration zur Laufzeit | Alexander Schwartz | JavaLand 2016 | 9. März 2016 27
    public class ConsulLbFactory implements LBClientFactory {
    private Map clients = new HashMap<>();
    public synchronized LBClient create(String clientName) {
    LBClient client = clients.get(clientName);
    if(client == null) {
    ILoadBalancer lb = new ConsulLoadBalancer(clientName);
    IClientConfig clientConfig = new DefaultClientConfigImpl();
    clientConfig.loadDefaultValues();
    client = LBClient.create(lb, clientConfig);
    clients.put(clientName, client);
    }
    return client;
    }
    }
    public class ConsulLoadBalancer extends BaseLoadBalancer {
    public ConsulLoadBalancer(String serviceName) {
    Consul consul = Consul.builder().build();
    HealthClient client = consul.healthClient();
    ServiceHealthCache svHealth = ServiceHealthCache.newCache(client, serviceName);
    svHealth.addListener(map -> {
    List newServers = new ArrayList<>();
    map.forEach((hostAndPort, serviceHealth) ->
    newServers.add(new Server(hostAndPort.getHostText(),
    hostAndPort.getPort())));
    setServersList(newServers);
    });
    /* ... */
    }
    }

    View full-size slide

  28. Consul und Ribbon
    Überlegungen Pro und Kontra Service Discovery mit Consul
    © msg | Konfiguration zur Laufzeit | Alexander Schwartz | JavaLand 2016 | 9. März 2016 28
    Pro:
    • Kontakt zu Services ohne Single Point of Failure
    • Fertige Bibliotheken verfügbar
    • Dezentrales Monitoring von Services
    • GUI für Key-Value-Store und Monitoring
    • Zusätzliche Semantik für Services (statt nur Key-Value-Store)
    Kontra:
    • Zusätzliche Bibliotheken in Projekt

    View full-size slide

  29. Konfiguration zur Laufzeit
    29
    © msg | Konfiguration zur Laufzeit | Alexander Schwartz | JavaLand 2016 | 9. März 2016
    Alltägliche Konfigurationsänderungen
    1
    Archaius: Zugriff auf sich ändernde Konfigurationen
    2
    etcd: Zentrale Konfigurationsdatenbank
    3
    Consul und Ribbon: Service Discovery für Clients
    4
    Togglz: Aktivieren von neuen Funktionen steuern
    5
    Besser mit Konfiguration zur Laufzeit?
    6

    View full-size slide

  30. Togglz: Feature Toggles für Java
    Togglz schaltet Funktionen eines Programms zur Laufzeit ein und aus
    © msg | Konfiguration zur Laufzeit | Alexander Schwartz | JavaLand 2016 | 9. März 2016 30
    Szenarien:
    • Noch nicht freigegebene Funktionen sind nur in Testumgebungen aktiv
    • Aktivierung und Deaktivierung kann über ein Web-Frontend erfolgen
    • Über Regeln können Funktionen z. B. für ausgewählte Nutzer oder zeitgesteuert aktiviert werden

    View full-size slide

  31. Togglz: Feature Toggles für Java
    Togglz hat eine Web-Oberfläche für Änderungen
    © msg | Konfiguration zur Laufzeit | Alexander Schwartz | JavaLand 2016 | 9. März 2016 31
    Status und Rollout-Strategie können für jedes Feature zur Laufzeit geändert werden.

    View full-size slide

  32. Togglz: Feature Toggles für Java
    Die Feature Toggles werden im Programmcode abgefragt
    © msg | Konfiguration zur Laufzeit | Alexander Schwartz | JavaLand 2016 | 9. März 2016 32
    Einzelne Features werden als Enums im Java-Code deklariert.
    Anschließend werden sie im Java-Code abgefragt, bevor der neue Code ausgeführt wird.
    // declaration and documentation of features
    public enum Features implements Feature {
    @Label("First Feature")
    FEATURE_ONE;
    public boolean isActive() {
    return FeatureContext.getFeatureManager().isActive(this);
    }
    } // making use of toggles within the code
    if(Features.FEATURE_ONE.isActive()) {
    // do new exciting stuff here
    }

    View full-size slide

  33. Togglz: Feature Toggles für Java
    Überlegungen Pro und Kontra Feature Toggles
    © msg | Konfiguration zur Laufzeit | Alexander Schwartz | JavaLand 2016 | 9. März 2016 33
    • Feature Toggles sind ein bekanntes und gut verstandenes Pattern
    • Es gibt verschiedene Implementierungen für verschiedene Programmiersprachen
    • Feature Toggles machen Tests komplexer
    • Wenn ein neues Feature erfolgreich ausgerollt ist, sollte das Feature Toggle entfernt werden
    Der zusätzliche Aufwand von Feature Toggles lohnt sich:
    • Bei häufigen Releases (Continuous Delivery), damit fertige Features nicht von unfertigen Features
    blockiert werden
    • Wenn langlaufende Feature-Branches mit anschließendem Merge vermieden werden
    • Wenn aus einem graduellen Rollout Informationen für die Fertigstellung des Features gewonnen werden
    können

    View full-size slide

  34. Konfiguration zur Laufzeit
    34
    © msg | Konfiguration zur Laufzeit | Alexander Schwartz | JavaLand 2016 | 9. März 2016
    Alltägliche Konfigurationsänderungen
    1
    Archaius: Zugriff auf sich ändernde Konfigurationen
    2
    etcd: Zentrale Konfigurationsdatenbank
    3
    Consul und Ribbon: Service Discovery für Clients
    4
    Togglz: Aktivieren von neuen Funktionen steuern
    5
    Besser mit Konfiguration zur Laufzeit?
    6

    View full-size slide

  35. Konfiguration zur Laufzeit
    Besser mit Konfiguration zur Laufzeit? Ja!
    © msg | Konfiguration zur Laufzeit | Alexander Schwartz | JavaLand 2016 | 9. März 2016 35
    Zugriff auf sich ändernde Konfigurationen
    • Hilft bereits bei der Entwicklung der Anwendung
    • Minimaler initialer Aufwand, große Flexibilität für die Produktion
    Zentrale Konfigurationsdatenbank
    • Anwendungsübergreifende Konfiguration
    • Service-Discovery in Cloud-Szenarien
    Feature Toggles
    • Wenn es Entwicklung und Deployment vereinfacht
    • Wenn frühe Rückmeldung zu einem Feature aus der Produktion
    einen fachlichen Nutzen hat
    @ahus1de

    View full-size slide

  36. Konfiguration zur Laufzeit
    Links
    © msg | Konfiguration zur Laufzeit | Alexander Schwartz | JavaLand 2016 | 9. März 2016 36
    Netflix Archaius: https://github.com/Netflix/archaius
    Apache Commons Configuration:
    http://commons.apache.org/proper/commons-configuration/
    Apache Tamaya: http://tamaya.incubator.apache.org/
    Übersicht über verschiedene Methoden:
    http://javaeeconfig.blogspot.de/2014/08/
    overview-of-existing-configuration.html
    HashiCorps Consul für Service Discovery,
    Monitoring und Konfigurationsmanagement
    http://heise.de/-3040847
    Saltstack and Consul Examples
    https://github.com/ahus1/saltconsul-examples
    Togglz: http://www.togglz.org/
    Übersicht über Feature Toggle Implementierungen:
    http://www.beautifulbuilds.com/feature-toggle-frameworks-list/ @ahus1de
    CoreOS etcd: https://github.com/coreos/etcd
    Jurnous etcdj: https://github.com/jurmous/etcd4j
    Vulcan: http://www.vulcanproxy.com/
    SkyDNS: https://github.com/skynetservices/skydns
    Netflix Eureka: https://github.com/Netflix/eureka
    Hazelcast: http://hazelcast.com/
    Apache Zookeeper: https://zookeeper.apache.org/
    Netflix exhibitor: https://github.com/Netflix/exhibitor
    HashiCorp Consul: http://consul.io/

    View full-size slide

  37. .consulting .solutions .partnership
    Alexander Schwartz
    Principal IT Consultant
    +49 171 5625767
    [email protected]
    @ahus1de
    msg systems ag (Headquarters)
    Robert-Buerkle-Str. 1, 85737 Ismaning
    Germany
    www.msg-systems.com

    View full-size slide