Stream processing avec Apache Pulsar

Stream processing avec Apache Pulsar

Présentation de Apache Pulsar et de ses possibilités pour le développement d'applications de Stream Processing, faite lors de Paris Open Source Summit 2019.

Bc34f46fdfa199da05a78f26584ecec3?s=128

Bruno Bonnin

December 11, 2019
Tweet

Transcript

  1. Stream Processing avec Apache Pulsar

  2. None
  3. Yahoo ! 2016 2018 2015

  4. None
  5. Topic 1 Producteur 2 Consommateur 1 Topic 2 Topic 3

    Producteur 1 Consommateur 2 Consommateur 3
  6. 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
  7. Système de stockage une solution pour la haute disponibilité stockage

    des données et des offsets
  8. Bookie 1 Broker 1 Broker 2 Bookie 2 Bookie 3

    Bookie 4 Producteurs Consommateurs Broker 3 Bookie 5
  9. Broker segment 1 Bookie 1 segment 1 segment 1 segment

    1 Bookie 2 Bookie 3 topic ensemble de segments Bookie 4
  10. Broker segment 1 Bookie 1 segment 1 segment 1 segment

    1 Bookie 2 Bookie 3 Bookie 4
  11. None
  12. Topic Producteur Consommateur - A1 Exclusive Subscription A Consommateur -

    A2
  13. Topic Producteur Consommateur - B1 Fail-over Subscription B Consommateur -

    B2
  14. Topic Producteur Consommateur - C1 Subscription C Consommateur - C2

    -> aucune garantie d’ordre ! Shared
  15. Topic Producteur Consommateur - B1 Consommateur - B2 Consommateur -

    A1 Consommateur - C1 Consommateur - C2
  16. None
  17. Tableau d’octets Clé propriétés Id de séquence

  18. 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é message acquitté message acquitté Messages supprimés Non traités (sauvegardés dans BookKeeper) message non acquitté message non acquitté message acquitté message acquitté
  19. None
  20. Type de topic Nom de l’entité (tenant) Nom du namespace

    Nom du topic persistent://public/default/demo-topic
  21. Sales Ops DC1 Online Stores persistent://Sales/Stores/Clients

  22. None
  23. Cluster A Topic 1 Producteur Cluster B Topic 1 Cluster

    C Topic 1 Consommateur topics namespace global asynchrone synchrone persistence local d’abord restreindre la réplication Producteur
  24. None
  25. # Installation “à l’ancienne”: # >>>> https://pulsar.apache.org $ wget http://.../pulsar/apache-pulsar-2.4.1-bin.tar.gz

    $ tar xzf apache-pulsar-2.4.1-bin.tar.gz # Lancement de tous les composants # broker, bookie, zookeeper (pour des tests/dev) $ pulsar standalone
  26. # Producteur: 100 messages, 1msg/sec $ pulsar-client produce \ -m

    "Hello Open Source Summit !" \ -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
  27. None
  28. Apache Pulsar Producteur de commandes Traitement des commandes Analytics Transformation

    / Enrichissement Connecteurs
  29. + API WebSocket

  30. // 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) ...
  31. Producer<byte[]> producer = client.newProducer() .topic("demo-topic") .producerName("demo-producer") .... .create(); // Envoi

    synchrone MessageId msgId = producer.send("Hi OS Summit!".getBytes()); // Envoi asynchrone (retourne une CompletableFuture) producer.sendAsync("Hi OS Summit!".getBytes()) .thenAccept(msgId -> { System.out.printf("Msg %s successfully sent", msgId); });
  32. 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
  33. byte[] uniquement valable pour les clients Java !! automatiquement uploadés

    sur les brokers Gestion des versions
  34. // Côté producteur Producer<Order> producer = client.newProducer(JSONSchema.of(Order.class)) .topic("orders") .create(); Order

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

    Message<Order> msg = consumer.receive(1000, TimeUnit.SECONDS); Order order = msg.getValue();
  36. None
  37. Topic de sortie F 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. 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 (order.total() > 10000) return order; // Envoi vers le topic des “grosses” commandes return null; }
  42. 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; }
  43. 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); }
  44. Broker 1 Function workers Broker 2 Function workers Broker 1

    Function worker 1 Broker 2 Function worker 2 Function workers
  45. # Déploiement d’une fonction $ pulsar-admin functions create \ --jar

    my_pulsar_fct.jar \ --className MyPulsarFunction \ --fqfn demo/test/hello \ --inputs persistent://demo/test/input \ --output persistent://demo/test/output \ --log-topic persistent://demo/test/logs \ --cpu 8 \ --ram 8589934592 \ --disk 10737418240
  46. None
  47. Pulsar Topic Connecteur Source Connecteur Sink

  48. None
  49. None
  50. None
  51. $ pulsar sql-worker run

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

    pulsar; presto> show tables in pulsar."demo/ecommerce"; Catalog --------- pulsar system Schema ----------------------- information_schema public/default public/functions demo/ecommerce Table --------------- orders-all orders-not-us orders-us TOPICS NAMESPACES
  53. presto> select id, orderdate, ipaddress, amount, email from pulsar."demo/ecommerce"."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. Apache Pulsar Analytics Connecteurs Consommateurs de commandes Transformation / Enrichissement

    Producteur de commandes Broker Topic orders-all Topic orders-us Stockage Bookie Functions FilterOrder Consommateurs API Pulsar Connectors (IO) Elasticsearch Sink Analytics Pulsar SQL (Presto) Producteurs API Pulsar
  55. None
  56. - - tier-storage (AWS, Google, HDFS, …), - - -

    - intégration avec Spark, Flink, Nifi - Yahoo ! https://streaml.io/blog
  57. None
  58. None