Introduction à Apache Pulsar

Introduction à Apache Pulsar

Introduction à Apache Pulsar, système de messagerie distribué, performant, hautement disponible, multi-tenant, avec garantie de livraison et de nombreuses autres fonctionnalités !
Présentation faite lors de SunnyTech 2019 à Montpellier.

Bc34f46fdfa199da05a78f26584ecec3?s=128

Bruno Bonnin

June 28, 2019
Tweet

Transcript

  1. Introduction à Apache Pulsar Bruno Bonnin @_bruno_b_

  2. Consultant-Couteau Suisse @ Zenika Nantes

  3. None
  4. Pulsar, un système de messagerie distribué Né chez Yahoo !

    pour compenser certaines limites des solutions de l’époque Pour des apps critiques comme Yahoo Mail, Yahoo Finance, Yahoo Sports, etc Open sourcé en 2016 Devenu Top Level Project de la fondation Apache en sept 2018 Premier déploiement Q2 2015
  5. Pulsar, un système de messagerie distribué Architecture Gestion des messages

    Développement Functions Geo-replication Multi-tenancy IO SQL
  6. Concepts & architecture

  7. Des producteurs, des consommateurs, des topics, ... Topic 1 Producteur

    Consommateur Topic 2 Topic 3
  8. Gestion des messages Producteurs Stockage des messages Bookie 1 Bookie

    2 Bookie 3 Bookie 4 Consommateurs zkServer 1 zkServer 2 zkServer 3 Broker 1 Broker 2 Broker 3 lecture stockage meta-données coordination clusters stockage meta-données stockage des données Des brokers, des bookies, ... écriture Apache BookKeeper Apache Zookeeper
  9. Bookie 1 Une architecture scalable Broker 1 Broker 2 Bookie

    2 Bookie 3 Bookie 4 Gestion des messages Stockage des messages Producteurs Consommateurs Broker 3 Bookie 5 Topic 1
  10. Apache BookKeeper Système de stockage scalable, tolérant aux pannes et

    à faible latence Conçu à l’origine comme une solution pour la haute disponibilité du NameNode de HDFS (WAL) Avec Pulsar: stockage des données et des offsets (cursors)
  11. Broker Topic 1 segment 2 segment 1 segment x ...

    Bookie 1 segment 1 Une architecture hautement disponible segment 1 segment 1 segment x segment x segment 2 segment 2 Bookie 2 Bookie 3 Un topic est constitué d’un ensemble de segments (ledgers) contenant les messages. Les segments sont stockés et répartis sur les bookies. segment x segment 2 Bookie 4
  12. Broker Topic 1 segment 2 segment 1 segment x ...

    Bookie 1 segment 1 Une architecture hautement disponible segment 1 segment 1 segment x segment x segment 2 segment 2 Bookie 2 Bookie 3 Sur défection d’un bookie, automatiquement, récupération des segments manquants pour respecter le facteur de réplication segment x segment 2 Bookie 4 segment x segment 1
  13. Modes de consommation

  14. Topic Producteur Consommateur - A1 Exclusive subscription Subscription A Consommateur

    - A2 Les tentatives de connexions de A2 échoueront Topics et abonnements
  15. Topic Producteur Consommateur - B1 Fail-over subscription Subscription B Consommateur

    - B2 Messages consommés par B2, uniquement en cas d’échec de B1 Topics et abonnements
  16. Topic Producteur Consommateur - C1 Subscription C Consommateur - C2

    Les messages sont envoyés aux deux consommateurs (round robin) -> aucune garantie d’ordre ! Topics et abonnements Shared subscription
  17. Topic Producteur Consommateur - B1 Consommateur - B2 Consommateur -

    A1 Consommateur - C1 Consommateur - C2 Exclusive Subscription Il peut y avoir plusieurs abonnements sur un topic Fail-over Subscription Shared Subscription Topics et abonnements
  18. Les messages

  19. Messages Contenu d’un message: - Tableau d’octets (peut être conforme

    à un schéma) - Clé (optionnel) - Ensemble de propriétés (optionnel) - Nom du producteur - Id de séquence (numéro d’ordre dans le topic, attribué par le producteur) - Timestamps
  20. Cycle de vie des messages Avec rétention message acquitté message

    acquitté Messages supprimés (hors rétention) Messages gardés car dans la période de rétention Non traités message acquitté message acquitté message non acquitté message non acquitté Messages supprimés Messages supprimés car au-delà du TTL Non traités et encore dans le TTL message non acquitté message non acquitté message non acquitté message non acquitté message acquitté message acquitté Avec TTL message acquitté message acquitté Messages supprimés Non traités (sauvegardés dans BookKeeper) message non acquitté message non acquitté message acquitté message acquitté Cas nominal
  21. Démo

  22. # Lancement de tous les composants # broker, bookie, zookeeper

    (pour des tests/dev) $ pulsar standalone $ pulsar-admin clusters list standalone $ pulsar-admin clusters get standalone { "serviceUrl":"http://hostname:8080", "brokerServiceUrl": "pulsar://hostname:6650" }
  23. # Producteur: 100 messages, 1msg/sec $ pulsar-client produce \ -m

    "hello SunnyTech" \ -n 100 -r 1 \ demo-topic # Consommateur: 1msg/sec sans arrêt $ pulsar-client consume \ -n 0 -r 1 \ -s "demo-subs-exclusive" \ -t Exclusive \ demo-topic
  24. Développons avec Pulsar

  25. + API WebSocket

  26. // Création d’un client (idem producteur et conso) PulsarClient client

    = PulsarClient.builder() .serviceUrl("pulsar://myhostname:6650") .build(); .authentication(...) .connectionsPerBroker(5) .ioThreads(10) .keepAliveInterval(2, TimeUnit.MINUTES) .maxNumberOfRejectedRequestPerConnection(5) .operationTimeout(10, TimeUnit.SECONDS) ...
  27. Producer<byte[]> producer = client.newProducer() .topic("demo-topic") .producerName("demo-producer") .batchingMaxPublishDelay(10, TimeUnit.MILLISECONDS) .sendTimeout(10, TimeUnit.SECONDS)

    .blockIfQueueFull(true) .create(); // Envoi synchrone MessageId msgId = producer.send("Hi SunnyTech!".getBytes()); // Envoi asynchrone producer.sendAsync("Hi SunnyTech!".getBytes()) .thenAccept(msgId -> { System.out.printf("Msg %s successfully sent", msgId); });
  28. Consumer consumer = client.newConsumer() .topic("demo-topic") .subscriptionName("demo-exclusive-sub") .subscriptionType(SubscriptionType.Exclusive) .subscribe(); // Lecture

    à partir du premier message non acquitté Message msg = consumer.receive(1000, TimeUnit.SECONDS); System.out.printf("Message: %s, from %s with id=%s\n", new String(msg.getData()), msg.getProducerName(), msg.getMessageId()); consumer.acknowledge(msg); // A ne pas oublier
  29. Schéma Registry Par défaut, le type des messages est byte[]

    Pulsar fournit un système de contrôle des types de données: uniquement valable pour les clients Java !! Les schémas sont automatiquement uploadés sur les brokers à la création des producteurs (et bien sûr sauvegardés dans BookKeeper ) Gestion des versions
  30. // Côté producteur Producer<Order> producer = client.newProducer(JSONSchema.of(Order.class)) .topic("orders") .create(); Order

    order = new Order(product, quantity); producer.send(order);
  31. // Côté consommateur Consumer<Order> consumer = client.newConsumer(JSONSchema.of(Order.class)) .topic("orders") .subscriptionName(subsName) .subscriptionType(subType)

    .subscribe(); Message<Order> msg = consumer.receive(1000, TimeUnit.SECONDS); Order order = msg.getValue();
  32. Multi-tenancy

  33. Multi-tenancy Type de topic Nom de l’entité (tenant) Nom du

    namespace Nom du topic persistent://public/default/demo-topic
  34. Multi-tenancy Pulsar Cluster Sales Ops Tenants DC1 Online Namespaces Stores

    20 To Topics Rétention: 10j Fraud Clients Orders Logs persistent://Sales/Stores/Clients
  35. # Multi-tenancy # - création entité $ pulsar-admin tenants create

    sales # - création namespace $ pulsar-admin namespaces create sales/online # - ajout de quotas $ pulsar-admin namespaces set-retention \ --size 20T --time 2d sales/online
  36. Pulsar Functions

  37. Pulsar Functions Topic de sortie F But: offrir un cadre

    d’exécution de traitements des données sans utiliser d’environnement complémentaire Topic d’entrée 1 Topic d’entrée 2 Topic des logs State
  38. def process(input): return "Hi %s!" % input

  39. // Exemple le plus simple, sans framework import java.util.function.Function; public

    class HiFunction implements Function<String, String> { @Override public String apply(String inputMsg) { return String.format("Hi %s!", inputMsg); } }
  40. import org.apache.pulsar.functions.api.Context; import org.apache.pulsar.functions.api.Function; import org.slf4j.Logger; public class EnhancedHiFunction implements

    Function<String, String> { @Override public String process(String input, Context context) throws Exception { Logger logger = context.getLogger(); String functionTenant = context.getTenant(); String functionNamespace = context.getNamespace(); String functionName = context.getFunctionName(); logger.info("Function {}/{}/{}: input={}", functionTenant, functionNamespace, functionName, input); return String.format("Hi %s!", input); } }
  41. Dans les brokers Pulsar Functions - Déploiement Broker 1 Function

    workers Broker 2 Function workers Broker 1 Dans des containers Function worker 1 Broker 2 Function worker 2 En local Function workers
  42. # Déploiement d’une fonction $ pulsar-admin functions create \ --jar

    my_pulsar_fct.jar \ --className MyPulsarFunction \ --fqfn talk/demo/hello \ --inputs persistent://talk/demo/input \ --output persistent://talk/demo/output \ --log-topic persistent://talk/demo/logs \ --cpu 8 \ --ram 8589934592 \ --disk 10737418240
  43. Pulsar Functions Exemples de cas d’utilisation des Functions: - Routage

    des messages - Filtrage if ("US".equals(order.country()) context.publish("sales/online/orders-us", order); else context.publish("sales/online/orders-not-us", order); public Order process(Order order) { if ("US".equals(order.country()) return order; return null; }
  44. Pulsar Functions Exemples de cas d’utilisation des Functions: - Modification

    des messages - Alertes public Order process(Order order) { order.setEmail(anonymize(order.getEmail())); return order; } public String process(Sensor sensor) { if (sensor.getTemp() > 50) // Envoi d’un mail ... return null; }
  45. Pulsar Functions Et quoi d’autres ? - stockage de métriques,

    de compteurs (stockés dans Apache BookKeeper, bien sûr) - utilisation de paramètres de config, - fenêtrage (sliding window, tumbling window) public Void process(Order order, Context context) { Double threshold = context.getUserConfigValue("threshold"); Float previous = context.getState(order.getId() + "-metric"); context.incrCounter(order.getId() + "-metric", 1); }
  46. Pulsar IO

  47. Pulsar IO Pulsar Topic Connecteur Source Connecteur Sink

  48. Pulsar IO CDC basé sur

  49. SQL

  50. Pulsar SQL Basé sur Lecture directe sur Apache BookKeeper

  51. $ pulsar sql-worker run

  52. $ pulsar sql presto> show catalogs; presto> show schemas in

    pulsar; presto> show tables in pulsar."talk/demo"; Catalog --------- pulsar system Schema ----------------------- information_schema public/default public/functions talk/demo Table --------------- orders-all orders-but-us orders-us
  53. presto> select id, orderdate, ipaddress, amount, email from pulsar."talk/demo"."orders-all"; id

    | orderdate | ipaddress | amount | email -------------+---------------+-----------------+--------+---------------------------------- 307-02-9402 | 1561409774204 | 94.244.112.41 | 596.59 | robyn.kutch@hotmail.com 470-87-6280 | 1561409774501 | 82.244.158.201 | 135.39 | alexia.powlowski@gmail.com 842-89-5722 | 1561409774704 | 60.73.130.208 | 112.89 | zora.mccullough@hotmail.com 795-45-3565 | 1561409775408 | 231.96.223.0 | 60.75 | gerard.smitham@hotmail.com 876-36-9065 | 1561409775924 | 29.189.193.82 | 768.13 | ehtel.towne@gmail.com 840-97-8273 | 1561409776044 | 93.240.237.245 | 308.92 | don.gerlach@yahoo.com 043-41-7461 | 1561409776348 | 186.116.245.21 | 206.03 | raymond.bosco@gmail.com 069-72-8645 | 1561409776591 | 106.113.25.240 | 144.54 | alexandra.predovic@gmail.com
  54. Geo-replication

  55. Réplication géographique Cluster A Topic 1 Producteur 1 Cluster B

    Topic 1 Producteur 2 Cluster C Topic 1 Producteur 3 Les topics doivent appartenir à un namespace global Réplication asynchrone ou synchrone (persistence local d’abord, puis envoi aux autres clusters) Possibilité pour un producteur de restreindre la réplication à des clusters donnés
  56. Gestion des messages Brokers Stockage Bookies En résumé... Traitements Pulsar

    Functions Connecteurs Pulsar IO Analytics Pulsar SQL (Presto) Stockage tiers AWS Google Azure HDFS Clients Producteurs / Consommateurs
  57. Démo Broker orders-all Producteur “Order Generator” Consommateur “pulsar-client” Function FilterOrder

    orders-us Connector (IO) Elasticsearch Sink State (BookKeeper)
  58. Conclusion Il existe beaucoup de fonctions intéressantes (plus ou moins

    matures): - découplage broker et stockage - tier-storage, - geo-replication, - Pulsar IO - Pulsar Functions - Schema registry, - SQL, - … Environnement complet pour couvrir vos besoins en termes de stream processing Aujourd’hui chez Yahoo ! - > 2 millions de topics - > 100 milliards de messages / jour - > 150 brokers Plus d’infos: https://streaml.io/blog
  59. Auto-promo : https://github.com/bbonnin/pulsar-express

  60. Merci ! @_bruno_b_ #SeaTechAndSun Illustrations: https://undraw.co/illustrations