6. Cambio de estado de Akka

En Akka, los actores a menudo se encuentran en un estado en el que no pueden procesar ciertos mensajes. Por ejemplo, si el cliente de la base de datos está fuera de línea, no podrá procesar ningún mensaje hasta que vuelva a estar en línea. Podemos optar por continuar restableciendo la conexión del cliente hasta que la conexión sea exitosa. En este caso, el cliente descartará todos los mensajes recibidos antes de conectarse correctamente. Otro enfoque consiste en dejar de lado los mensajes que el cliente no puede procesar y esperar a que el cliente restaure el estado de la conexión antes de procesarlo.

Akka proporciona un mecanismo llamado alijo , que se utiliza para alternar entre estados de mensajes en Akka:

  • stash: almacena temporalmente los mensajes en una cola independiente, que almacena los mensajes que no se pueden procesar actualmente:
  • unstash: saca el mensaje de la cola de almacenamiento temporal y vuelve a colocarlo en la cola del buzón, el actor puede continuar procesando estos mensajes

Cabe señalar que, aunque stash () y unstash () son muy convenientes de usar cuando desea cambiar rápidamente el estado, el estado del mensaje de reserva debe estar sujeto a un límite de tiempo determinado, de lo contrario, el buzón puede llenarse. Puede programar la ejecución de este mensaje en el constructor del actor o en el método preStart:

System.scheduler().scheduleOnce(
Duration.create(1000,TimeUnit.MILLISECONDS),self(),CheckConnected,system.dispacher(),null);

Declaraciones condicionales

La forma más intuitiva es almacenar el estado en el actor y luego usar una declaración condicional para determinar qué debe hacer el actor.

public PartialFunction receive() {
    
    
    return RecieveBuilder
            .match(GetRequest.class, x -> {
    
    
                if (online) {
    
    
                    processMessage(x);
                } else {
    
    
                    stash();
                }
            })
            .match(Tcp.Connected.class, x -> {
    
    
                online = true;
                unstash();
            )
            .match(Disconnected.class, x -> online = false).build();
    }
}

Se usa Stash / Unstash, por lo que una vez que el Actor esté en línea, se procesarán todos los mensajes de Stash.

Muchas veces, los actores almacenan el estado y luego tienen diferentes comportamientos según el valor de este estado. El uso de declaraciones condicionales es un método muy procedimental para manejar el comportamiento y el estado.

Hotswap: Convertirse / No convertirse

  • convertirse (comportamiento PartialFunction): este método modifica el comportamiento definido en el bloque de recepción a un nuevo PartialFunction.
  • unbecome (): este método cambia el comportamiento del actor de nuevo al comportamiento predeterminado.
public PartialFunction receive() {
    
    
    return RecieveBuilder
            .match(
                GetRequest.class, x -> stash())
            .match(Connected.class, x -> {
    
    
                context().become(online); // become
                unstash();
            }).build();
}

final private PartialFunction<Object, BoxedUnit> online(final ActorRef another) {
    
    
    return RecieveBuilder.match(
            GetRequest.class, x -> processMessage(x)
    ).build();
}

En comparación con los enunciados condicionales, el comportamiento de cada estado se define en su propia PartialFunction independiente.

El actor está desconectado al principio y no puede responder a GetRequest en este momento, por lo que oculta el mensaje. Antes de recibir el mensaje Conectado, estos mensajes se almacenarán y dejarán de lado temporalmente. Una vez que se recibe el mensaje Conectado, las llamadas del actor pasan a cambiar el estado a en línea. En este momento, el actor también llamará a unstash para recuperar todos los mensajes temporales en la cola de trabajo. De esta forma, puede utilizar el comportamiento definido en el método de estado en línea para procesar todos los mensajes. Si el actor recibe un mensaje Desconectado, se llama a unbecome para restaurar el comportamiento del actor a la configuración predeterminada.

Máquina de estado finito (FSM)

De "Akka Introducción a la práctica", el código es solo para referencia. Preste atención a la cuenta pública: Data PorterResponda para Akkarecibir el libro "Introducción y práctica de Akka"

También hay cambios de comportamiento basados ​​en estados y estados en FSM. En comparación con el intercambio en caliente, FSM es un concepto abstracto más pesado que requiere más códigos y tipos para poder implementarlo y ejecutarlo. Entonces, en términos generales, el intercambio de calor es una opción más simple y legible.

El tipo en FSM tiene dos parámetros: estado y contenedor.

Definir el estado

  • Desconectado: fuera de línea, no hay ningún mensaje en la cola;
  • Desconectado y Pendiente: Fuera de línea, la cola contiene mensajes;
  • Conectado: en línea, sin mensajes en la cola;
  • Conectado y pendiente: en línea, la cola contiene mensajes
enum State{
    
      
	DISCONNECTED,   
	CONNECTED,   
	CONNECTED_AND_PENDING,  
}

Definir el contenedor de estado

El contenedor de estado es donde se almacenan los mensajes. FSM nos permite definir el contenedor de estado y modificar el contenedor de estado al cambiar de estado.

public class EventQueue extends LinkedList<Request> {}

  1. Heredar akka.actor.AbstractFSM <S, D>

    public class BunchingAkkademyClient extends AbstractFSM<State, RequestQueue>{
          
              {
          
          //init block  } } 
    
  2. Definir el comportamiento en el bloque de inicialización.

    {
          
            
    	startWith(DISCONNECTED, null); //init block 
    }  
    
  3. Defina cómo los diferentes estados responden a diferentes mensajes y cómo cambiar de estado según el mensaje recibido.

    when(DISCONNECTED,
         matchEvent(FlushMsg.class, (msg, container) -> stay())
            .event(GetRequest.class, (msg, container) -> {
          
          
                container.add(msg);
                return stay();
            })
            .event(Tcp.Connected.class, (msg, container) -> {
          
          
                if(container.getFirst() == null) {
          
          
                    return goTo(CONNECTED);
                } else {
          
          
                    return goTo(CONNECTED_AND_PENDING);
                }
            }));
    when(CONNECTED,
         matchEvent(FlushMsg.class, (msg, container) -> stay()) {
          
          
            .event(GetRequest.class, (msg, container) -> {
          
          
                container.add(msg);
                return goTo(CONNECTED_AND_PENDING);
        }));
    when(CONNECTED_AND_PENDING,
         matchEvent(FlushMsg.class, (msg, container) -> {
          
          
                container = new EventQueue();
                return stay();
         })
         .event(GetRequest.class, (msg, container) -> {
          
          
                container.add(msg);
                return goTo(CONNECTED_AND_PENDING);
         }));
    
    scala.PartialFunction pf = ReceiveBuilder.match(String.class,
                x -> System.out.println(x)).build(); 
    when(CONNECTED, pf);
    

    Algunos mensajes se ignoran en algunos estados y se procesan en otros estados. El actor debe devolver una descripción del estado, ya sea permaneciendo en un estado determinado en el FSM o pasando a otro estado.

  4. inicializar()

    Lo último que se debe hacer en este bloque de código es llamar a initialize ();

referencias

  • "Introducción y práctica de Akka"

Siga la Akkacuenta pública y responda para recibir el libro "Introducción y práctica de Akka"

¡Preste atención a la cuenta oficial 数据工匠记y concéntrese en los productos secos técnicos en tiempo real y fuera de línea en el campo de big data para compartir con regularidad! Sitio web personal www.lllpan.top
Inserte la descripción de la imagen aquí

Supongo que te gusta

Origin blog.csdn.net/lp284558195/article/details/112596242
Recomendado
Clasificación