Una introducción simple al reactor.

Reactor es un marco de programación reactivo basado en flujos reactivos. Antes de comprender el proyecto del reactor del proyecto, debe estar familiarizado con el modo de observador (modo de publicación por suscripción) y los flujos reactivos.
Solo al comprender estos contenidos podemos comenzar a aprender mejor el reactor del proyecto. Puede aprender estos dos puntos de conocimiento simplemente leyendo
mi opinión sobre el modo de observador y
una introducción a la programación sensible a la contrapresión de flujos reactivos .

métodos de estudio sugeridos

Los pasos generales y las condiciones previas del reactor de aprendizaje.

  1. Primero comprenda el concepto de sincrónico y asincrónico, y comprenda por qué se necesita la asincronía
  2. Comprender el patrón de observador y entender por qué se necesita el patrón de observador
  3. Comprenda las transmisiones reactivas, al menos sepa cómo se requiere el modo observador (modo de publicación por suscripción) en las transmisiones reactivas.
  4. Para aprender y usar el método de operación y el estilo de transmisión en jdk 8
  5. Comience a aprender reactor.

Sugerencias al aprender reactor:

  1. Entender el proceso básico del reactor antes de aprender
  2. En primer lugar, comprenda la función y el estado de flux y mono en el modelo de suscripción, y no se deje confundir por el conocimiento de los métodos y operadores de flux y mono para generar datos.
  3. Entender los métodos y llamadas de suscripción.
  4. Probablemente conozca la función y el uso del programador, y probablemente sepa que hay un gancho y su función.
  5. Lea acerca de cómo flux y mono crean datos, y puede verificarlos cuando los use.
  6. Lea acerca de los operadores de flux y mono, y puede verificarlos cuando los use.
  7. Comience con un proyecto real, comience a usar reactor y consulte la documentación cuando sea necesario. Si es necesario en el proyecto, aprenda el contexto nuevamente.
  8. Espere a que el reactor comience con el proyecto y luego intente optimizar el proyecto a través del programador y los ganchos.

Si estás para una entrevista, no lo dije.

Fuentes de datos Flux y Mono

Reactor, como todos los modelos de publicación y suscripción, se ajusta a la especificación de secuencias reactivas. Entonces, reactor también incluye editor, suscriptor, suscripción, procesador, operador y otros conceptos.
Flux y Mono son los editores implementados por reactor.Pueden aceptar suscripciones de otros suscriptores, generar datos y enviar los datos a los suscriptores. Al mismo tiempo, también integran algunas operaciones sobre flujos de datos, como mapa, filtro, etc.

la diferencia

Flux es un flujo de datos que contiene de 0 a N elementos, y Mono es un flujo de datos que contiene 0 o 1 elementos.

proceso basico

Solo al comprender el proceso del reactor en general, no podemos perdernos por el concepto de asuntos triviales. De hecho, todo el reactor es un modelo de publicación por suscripción.
Flux y Mono son los editores predeterminados de todo el sistema, el propósito es simplificar el trabajo de personalización del editor.

Flux y Mono integran muchos operadores para reducir la carga de trabajo de nuestros suscriptores y procesadores personalizados.
Debido a la existencia de operadores, no necesitamos definir nuestros propios procesadores y suscriptores cuando operamos en fuentes de datos y elementos. Podemos usar directamente la combinación de operadores para completar el trabajo. No intente personalizar suscriptores y procesadores a menos que tengo
que

创建数据源
调用操作符对数据进行处理
subscibe订阅数据源

Crear una fuente de datos Flux/Mono

Después de comprender el modelo de publicación-suscripción y el papel del editor, comprenderá flux y mono. Para satisfacer las necesidades de Flux y mono, existe una gran cantidad de métodos para generar datos.
Debido a limitaciones de espacio, he organizado esta parte del contenido por separado. Para obtener más información, consulte la generación de fuentes de datos de Reactor.

operador

En el proceso básico, se ha mencionado que reactor integra muchos operadores para reducir la carga de trabajo de personalizar abonados y procesadores.
En primer lugar, debe tener una comprensión general de las funciones y los escenarios de aplicación de los operadores, y solo necesita saber qué tipos de operadores existen.
Es posible que desee leer la documentación oficial cuando la necesite. No recuerde los que se usan comúnmente, porque se usan con frecuencia. No es necesario memorizar los que no son de uso común, porque no se utilizarán si se memorizan.
Debido a problemas de espacio, clasifiqué esta parte del contenido por separado. Para más detalles, consulte al operador del reactor.

suscribir

El operador de suscripción se usa para suscribirse a elementos en la transmisión.
Cuando los elementos de la secuencia no están suscritos, no se desencadenarán todas las operaciones y solo cuando los elementos de la secuencia estén suscritos, se desencadenarán todas las operaciones.
La interfaz de suscripción comúnmente utilizada es la siguiente


Flux.subscribe();
/**
 * @param consumer 消费者接口,用来消费流中的元素
 *                 
 */
Flux.subscribe(Consumer<? super T> consumer);

/**
 * @param consumer 消费者接口,用来消费流中的元素
 * @param errorConsumer 错误消费者接口,用来消费流中的错误
 */
Flux.subscribe(Consumer<? super T> consumer, Consumer<? super Throwable> errorConsumer);

/**
 * @param consumer 消费者接口,用来消费流中的元素
 * @param errorConsumer 错误消费者接口,用来消费流中的错误
 * @param completeConsumer 完成消费者接口,用来消费流中的完成
 */
Flux.subscribe(Consumer<? super T> consumer, Consumer<? super Throwable> errorConsumer, Runnable completeConsumer);

/**
 * @param consumer 消费者接口,用来消费流中的元素
 * @param errorConsumer 错误消费者接口,用来消费流中的错误
 * @param completeConsumer 完成消费者接口,用来消费流中的完成
 * @param subscriptionConsumer 订阅消费者接口,用来消费流中的订阅
 */              
Flux.subscribe(Consumer<? super T> consumer, Consumer<? super Throwable> errorConsumer, Runnable completeConsumer, Consumer<? super Subscription> subscriptionConsumer)

programador

Reactor también se puede considerar independiente de la concurrencia. Es decir, no impone ningún modelo de concurrencia.
Yendo un paso más allá, pone la elección en manos de los desarrolladores. Sin embargo, proporciona algunas bibliotecas convenientes para la ejecución simultánea.
Reactor proporciona dos formas de ajustar el Programador en la cadena reactiva: publicar y suscribir.
Ambos aceptan un Programador como argumento, lo que permite cambiar el programador.
Pero la posición de PublishOn en la cadena es particular, pero subscribeOn no importa.
publicarEn Cambiará el hilo de ejecución de los operadores posteriores. Y subscribeOn cambia el programador del operador descendente.

En Reactor, el modo de ejecución y el proceso de ejecución dependen del Scheduler utilizado.

  • Subproceso actual (Schedulers.immediate())
  • Subproceso único (Schedulers.single())
  • Grupo de subprocesos de tamaño fijo (Schedulers.parallel())
  • Grupo de subprocesos elásticos (Schedulers.elastic())
Flux.just(1, 2, 3)
        .publishOn(Schedulers.parallel()) //指定在parallel线程池中执行
        .map(i -> {
    
    
            System.out.println("map1: " + Thread.currentThread().getName());
            return i;
        })
        .publishOn(Schedulers.elastic()) // 指定下游的执行线程
        .map(i -> {
    
    
            System.out.println("map2: " + Thread.currentThread().getName());
            return i;
        })
        .subscribeOn(Schedulers.single())
        .subscribe(i -> System.out.println("subscribe: " + Thread.currentThread().getName()));

Además, algunos operadores utilizan un planificador específico.

Flux.interval(Duration.ofSeconds(1), Schedulers.single())
        .subscribe(System.out::println);

procesador

El procesador es un objeto que implementa las interfaces del publicador y el suscriptor, y se puede usar para conectar el publicador y el suscriptor.
En la mayoría de los casos, debe evitar el uso de Procesadores, son difíciles de usar correctamente y se usan principalmente en algunos escenarios especiales.
En lugar de usar los procesadores de Reactor directamente, una mejor manera es obtener el disipador del procesador llamando a sink() una vez.

FluxProcessor<String, String> processor = DirectProcessor.create();
processor.subscribe(System.out::println);
processor.onNext("foo");
processor.onNext("bar");
processor.onNext("baz");
processor.onComplete();

hundir

Sink es una interfaz que define algunos métodos para enviar datos al procesador.

UnicastProcessor<Integer> processor = UnicastProcessor.create();
FluxSink<String> sink = processor.sink();
sink.next("foo");
sink.next("bar");
sink.next("baz");
sink.complete();

Descripción general de los procesadores existentes

  • DirectProcessor: Procesador directo, es un procesador sincrónico, enviará todos los datos a todos los suscriptores.
  • UnicastProcessor: Procesador Unicast, es un procesador síncrono, solo enviará datos al primer suscriptor.
  • ReplayProcessor: el procesador de reproducción, que es un procesador asíncrono, envía todos los datos a todos los suscriptores, incluidos aquellos que se suscriben después de la suscripción.
  • WorkQueueProcessor: el procesador de colas de trabajo, que es un procesador asíncrono, enviará todos los datos a todos los suscriptores, incluidos aquellos que se suscriban después de la suscripción.
  • TopicProcessor: el procesador de temas, que es un procesador asíncrono, envía todos los datos a todos los suscriptores, incluidos los que se suscriben después de la suscripción.
  • EmitterProcessor: el procesador Emitter, que es un procesador asíncrono, enviará todos los datos a todos los suscriptores, incluidos aquellos que se suscriban después de la suscripción.

Manos

Los ganchos se pueden considerar como una clase de herramienta.Después de la configuración, los métodos establecidos por Hooks serán llamados de vuelta para los siguientes Flux y Mono, similar a los ganchos del sistema operativo.

Esta parte se considera una parte relativamente avanzada del reactor. Se recomienda conocer este concepto antes de comenzar a utilizar el reactor para proyectos.
Después de hacer uno o dos proyectos, regrese y observe lo que hacen los ganchos

Separo el contenido de esta parte, ver: Ganchos de reactor

Contexto

Al cambiar de un estilo de programación imperativo a un estilo de programación reactivo, uno de los mayores desafíos técnicos es la creación de subprocesos.
En el estilo de programación imperativa, podemos pasar datos a través de ThreadLocal,
pero en el estilo de programación reactiva, no podemos pasar datos a través de ThreadLocal.
Debido a que los subprocesos son administrados por Reactor, no tenemos control sobre la creación y destrucción de subprocesos.
El contexto se utiliza para resolver este problema. El contexto es una interfaz que define métodos para obtener y configurar datos.

Esta parte del contenido es relativamente difícil de entender. Se recomienda poner el aprendizaje y la comprensión más adelante. En resumen, cuando necesite usar la clase ThreadLocal en un entorno de subprocesos múltiples, no es demasiado tarde para aprender esta parte.

String key = "key";
Mono<String> r = Mono.just("hello")
        .flatMap(s -> Mono.subscriberContext()
                .map(ctx -> s + " " + ctx.get(key)))
        .subscriberContext(ctx -> ctx.put(key, "world"));
r.subscribe(System.out::println);
// 输出:hello world

API de contexto

Context es una interfaz similar a Map (esta estructura de datos): almacena pares clave-valor (clave-valor), y necesita obtener el valor por clave:

  • método put: poner un par clave-valor en contexto.
  • get method: obtiene el valor por clave.
  • Método de eliminación: elimina el par clave-valor por clave.
  • método hasKey: usa key para determinar si hay un par clave-valor.
  • método de flujo: devuelve un flujo, que se utiliza para atravesar todos los pares clave-valor en el Contexto.
  • Método isEmpty: determina si el Contexto está vacío.
  • método de tamaño: devuelve el número de pares clave-valor en el Contexto.
  • Método putAll: coloca todos los pares clave-valor de un contexto en otro contexto.
  • método currentContext: devuelve el Contexto del hilo actual.
  • método vacío: devuelve un Contexto vacío.
  • método raíz: devuelve un Contexto vacío.

Vincular contexto a Flux y escribir

String key = "key";
Flux<String> r = Flux.just("hello")
        .flatMap(s -> Mono.subscriberContext()
        .subscriberContext(ctx -> ctx.put(key, "world"));
                .map(ctx -> s + " " + ctx.get(key)))

leer datos del contexto

String key = "key"
Flux<String> r = Flux.just("hello")
        .flatMap(s -> Mono.subscriberContext()
                .map(ctx -> s + " " + ctx.get(key)))
        .subscriberContext(ctx -> ctx.put(key, "world"));
r.subscribe(System.out::println);
// 输出:hello world

Supongo que te gusta

Origin blog.csdn.net/aofengdaxia/article/details/128975491
Recomendado
Clasificación