Pautas de uso de middleware

1 conejo MQ

1.1 Introducción

1.1.1 Conceptos básicos

  • Broker: En pocas palabras, es la entidad del servidor de cola de mensajes.

  • Vinculante: vinculante, su función es vincular el intercambio y la cola de acuerdo con las reglas de enrutamiento.

  • Clave de enrutamiento: clave de enrutamiento, el intercambio entrega mensajes de acuerdo con esta clave.

  • vhost: host virtual, se pueden configurar múltiples vhosts en un intermediario para separar los permisos de diferentes usuarios.

  • productor: El productor de mensajes es el programa que entrega el mensaje.

  • Consumidor: El consumidor de mensajes es el programa que recibe el mensaje.

  • canal: Canal de mensajes En cada conexión de cliente se pueden establecer múltiples canales y cada canal representa una tarea de sesión.

1.1.2 Tres tipos de intercambio

  • directo: el
    mensaje se enruta a una cola específica mediante la clave de enrutamiento Hay un intercambio predeterminado en el sistema
    , el nombre es una cadena vacía y el mensaje se enruta de acuerdo con la clave de enrutamiento.

  • tema: coincidir con comodines de * y #, * (asterisco) puede sustituir exactamente una
    palabra, # (hash) puede sustituir a cero o más palabras.

  • fanout: envía mensajes a todas las colas, ignorando routing_key

1.1.3 Alta disponibilidad del clúster

Para garantizar la alta disponibilidad del clúster, generalmente se utilizan colas duplicadas. La cola duplicada se compone de un maestro y varios esclavos. Hay tres tipos de modo ha:

  • all: espejo para todos los nodos

  • exactamente: reflejado en el número especificado de nodos

  • nodos: espejo del nodo especificado

1.2 Uso

Las versiones utilizadas por RabbitMQ son las siguientes:

<dependency>
    <groupId>com.rabbitmq</groupId>
    <artifactId>amqp-client</artifactId>
    <version>4.2.0</version>
</dependency>

1.2.1 Crear conexión TCP

ConnectionFactory factory = new ConnectionFactory();
connectionFactory.setAutomaticRecoveryEnabled(true);// 故障自动重连
factory.setUsername(userName);
factory.setPassword(password);
factory.setVirtualHost(virtualHost);
factory.setHost(hostName);
factory.setPort(portNumber);
ThreadPoolExecutor executor=xxx;//用于执行consumer的线程池
Connection conn = factory.newConnection(executor);

1.2.2 Producción

Channel channel = conn.createChannel();
channel.queueDeclare(String queue, boolean durable, boolean exclusive, boolean autoDelete, Map<String, Object> arguments);
//durable-持久 ,exclusive-无连接自动删除队列 ,autoDelete-不使用自动删除队列
channel.confirmSelect() //设置确认机制

BasicProperties props = queueConfig.isDurable() ? MessageProperties.MINIMAL_PERSISTENT_BASIC: MessageProperties.MINIMAL_BASIC
channel.basicPublish(String exchange, String routingKey,BasicProperties props, byte[] body);//发送消息
channel.waitForConfirms(long timeout)// 等待队列发送确认

1.2.3 Consumo

Channel channel = conn.createChannel();
channel.queueDeclare(String queue, boolean durable, boolean exclusive, boolean autoDelete, Map<String, Object> arguments);
channel.basicQos() //流控


channel.basicConsume(queueName, autoAck, "myConsumerTag",   //autoAck=false queue等consumer 发送确认才删除消息
     new DefaultConsumer(channel) {
         @Override
         public void handleDelivery(String consumerTag,
                                    Envelope envelope,
                                    AMQP.BasicProperties properties,
                                    byte[] body)
             throws IOException
         {
             String routingKey = envelope.getRoutingKey();
             String contentType = properties.getContentType();
             long deliveryTag = envelope.getDeliveryTag();
             // (process the message components here ...)
             channel.basicAck(deliveryTag, false);  //void basicAck(long deliveryTag, boolean multiple) throws IOException; multiple表示是否一次确认多个 
         }
     });

1.2.4 Asuntos que requieren atención

  • El canal se puede almacenar en caché para garantizar el rendimiento

  • La concurrencia de consumidores está determinada por el número de canales y el menor número de subprocesos en el grupo de subprocesos.

  • queueDeclare se puede llamar repetidamente y la existencia de la cola está garantizada

  • Cuando falla el consumo de mensajes, existen las siguientes estrategias de procesamiento

basicNack(deliveryTag, false, true)   
队列中的消息会被派发到别的consumer,做出此响应的consumer仍然可以收到消息,直到所有消息完成
 
basicNack(deliveryTag, false, false)   
做出此响应的consumer仍然可以收到消息,直到所有消息完成,但是失败的消息不会再出现在队列
 
无动作   
消息处于没确定状态(对队列来讲),消息不会被派发给别的消费者(当该consumer被取消注册以后,消息被派发给别的consumer)

2 Redis

Versión 2.1

Redis generalmente usa el cliente Jedis e introduce dependencias de la siguiente manera:

<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>2.9.0</version>
    <type>jar</type>
    <scope>compile</scope>
</dependency>

2.2 Cómo utilizar

Hay muchas formas de usar Redis, y el método de operación específico se puede encontrar en https://redis.io/commands.
Los códigos de muestra se pueden encontrar en
https://github.com/xetorthio/jedis/tree/master/src/test/java/redis/clients/jedis/tests
.

2.2.1 Nodo único

//初始化链接
HostAndPort hnp = xxx ;
Jedis jedis = new Jedis(hnp.getHost(), hnp.getPort(), 500); 
jedis.connect();
jedis.auth("xxx");

//操作
String status = jedis.set("foo", "bar");
assertEquals("OK", status);

//关闭链接
jedis.disconnect();
  • new Jedis(hnp.getHost(), hnp.getPort(), 500)
    Usado para inicializar el objeto jedis, existen múltiples métodos sobrecargados, principalmente usados ​​para establecer parámetros de tiempo de espera de TCP

  • jedis.connect()
    Se utiliza para mostrar el establecimiento del enlace TCP, y es posible que la llamada no se muestre, y el establecimiento de TCP estará garantizado cuando se envíen comandos internos.

  • Las siguientes operaciones de Redis están usando Jedisobjetos y se realiza Jedisuna capa de encapsulación.

Si desea utilizar Pool para administrar la conexión, puede hacerlo.

JedisPool pool = new JedisPool(new JedisPoolConfig(), hnp.getHost(), hnp.getPort(), 2000);
Jedis jedis = pool.getResource();

jedis.close();
pool.close();

2.2.2 Hash consistente

//初始化
List<JedisShardInfo> shards = new ArrayList<JedisShardInfo>(2);
JedisShardInfo shard1 = new JedisShardInfo(redis1.getHost(), redis1.getPort());
shard1.setPassword("foobared");
shards.add(shard1);
JedisShardInfo shard2 = new JedisShardInfo(redis2.getHost(), redis2.getPort());
shard2.setPassword("foobared");
shards.add(shard2);
ShardedJedis jedis = new ShardedJedis(shards);

//操作
String status = jedis.set("foo", "bar");
assertEquals("OK", status);

//关闭链接
jedis.close();
  • JedisShardInfo Información diversa utilizada para especificar fragmentos

  • ShardedJedis(List<JedisShardInfo> shards, Hashing algo) Se puede especificar el algoritmo hash

Si desea utilizar Pool para administrar la conexión, puede hacerlo.

List<JedisShardInfo> shards = xxx;
ShardedJedisPool pool = new ShardedJedisPool(new GenericObjectPoolConfig(), shards);
ShardedJedis jedis = pool.getResource();
Jedis jedis = pool.getResource();

jedis.close();
pool.close();

2.2.3 Centinela

// 初始化
HostAndPort sentinel1 = xxx;
HostAndPort sentinel2 = xxx;
Set<String> sentinels = new HashSet<String>();
sentinels.add(sentinel1.toString());
sentinels.add(sentinel2.toString());
JedisSentinelPool pool = new JedisSentinelPool(MASTER_NAME, sentinels,
        new GenericObjectPoolConfig(), 2000, "foobared", 2);

// 获取Jedis
Jedis borrowed = pool.getResource();
borrowed.set("foo", "bar");
borrowed.close();

// 释放资源
pool.close();

3 Guardián del zoológico

3.1 Introducción

Zookeeper es un pequeño sistema de archivos distribuido y está diseñado para una alta disponibilidad. Los puntos únicos de falla se pueden evitar mediante algoritmos de elección y replicación de clústeres. Por lo general, Zookeeper consta de 2n + 1 servidores, y cada servidor conoce la existencia de los demás. Cada servidor mantiene la duplicación del estado de la memoria y el almacenamiento persistente de los registros de transacciones y las instantáneas.

3.1.1 Modelo de datos

Zookeeper tiene un espacio de nombres jerárquico, que es muy similar a un sistema de archivos distribuido. La diferencia es el Znode en el espacio de nombres de ZooKeeper, que tiene características de archivo y directorio. No solo mantiene estructuras de datos como datos, metainformación, ACL y marca de tiempo como un archivo, sino que también se puede usar como parte de la identificación de ruta como un directorio y puede tener subznodes. Los usuarios pueden agregar, eliminar, modificar y verificar znodes.

Cada nodo del árbol de directorios de ZooKeeper corresponde a un Znode. Cada Znode mantiene una estructura de atributos, que contiene información de estado, como el número de versión (dataVersion), la marca de tiempo (ctime, mtime), etc.

3.1.2 Rol

  • Líder, responsable del inicio y resolución de la votación, y actualizar el estado del sistema.

  • Alumno, incluidos seguidores y observadores,

  • Seguidor, utilizado para aceptar solicitudes de clientes y devolver resultados al cliente, participar en la votación en el proceso de elección del maestro.

  • El observador puede aceptar solicitudes de clientes y enviar solicitudes de escritura al líder, pero el observador no participa en el proceso de votación y solo sincroniza el estado del líder. El propósito del observador es expandir el sistema y mejorar la velocidad de lectura.

  • Cliente, iniciador de solicitudes

3.2 API básica

<dependency>
    <groupId>org.apache.curator</groupId>
    <artifactId>curator-framework</artifactId>
    <version>2.12.0</version>
</dependency>

Todos los códigos de muestra se pueden encontrar en
https://github.com/apache/curator/tree/master/curator-framework/src/test/java/org/apache/curator/framework/imps
.

3.2.1 Crear sesión

RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3)
CuratorFramework client =
        CuratorFrameworkFactory.builder()
                .connectString(connectionInfo)
                .sessionTimeoutMs(5000)
                .connectionTimeoutMs(5000)
                .retryPolicy(retryPolicy)
                .build();
client.start();

3.2.2 Crear nodo

Modo de creación de nodos de Zookeeper

PERSISTENT: persistente
PERSISTENT_SEQUENTIAL: persistente con número de serie
EPHEMERAL: temporal
EPHEMERAL_SEQUENTIAL: temporal con número de serie

client.create().forPath("/my/path", myData)
client.create().creatingParentsIfNeeded().forPath("/my/path", myData);//递归创建
client.create().withMode(CreateMode.EPHEMERAL).forPath("path");

3.2.3 Eliminar nodo

client.delete().forPath("/my/path"); //只删除叶子节点
client.delete().deletingChildrenIfNeeded().forPath("path"); //递归删除其所有的子节点

3.2.4 Obtener nodos secundarios

client.getChildren().forPath("/")

3.2.5 Leer datos

client.getData().forPath("path");//此方法返的返回值是byte[];
Stat stat = new Stat();
client.getData().storingStatIn(stat).forPath("path");//读取一个节点的数据内容,同时获取到该节点的stat

3.2.6 Actualizar datos

client.setData().forPath("path","data".getBytes());

3.2.7 Verifique si el nodo existe

client.checkExists().forPath("path");

3.2.8 Ejecución asincrónica

Si el inBackground()método no especifica un ejecutor, el EventThread de Curator se utilizará de forma predeterminada para el procesamiento asincrónico.

Executor executor = Executors.newFixedThreadPool(2);
client.create()
      .creatingParentsIfNeeded()
      .withMode(CreateMode.EPHEMERAL)
      .inBackground((curatorFramework, curatorEvent) -> {      
        System.out.println(String.format("eventType:%s,resultCode:%s",curatorEvent.getType(),curatorEvent.getResultCode()));
      },executor)
      .forPath("path");

3.3 API avanzada

<dependency>
    <groupId>org.apache.curator</groupId>
    <artifactId>curator-recipes</artifactId>
    <version>2.12.0</version>
</dependency>

Todos los códigos de muestra se pueden encontrar en
https://github.com/apache/curator/tree/master/curator-recipes/src/test/java/org/apache/curator/framework/recipes
.

3.3.1 Seguimiento

3.3.1.1 PathChildrenCache

Cuando se agrega, actualiza o elimina un nodo secundario, Path Cache cambiará su estado,
incluido el último nodo secundario,
los datos y el estado del nodo secundario, y el cambio de estado se notificará a través de PathChildrenCacheListener.

Timing timing = new Timing();
CuratorFramework client = CuratorFrameworkFactory.newClient(server.getConnectString(), new RetryOneTime(1));
PathChildrenCache cache = new PathChildrenCache(client, "/a/b/test", true);
try
{
    client.start();

    final BlockingQueue<PathChildrenCacheEvent.Type> events = Queues.newLinkedBlockingQueue();
    PathChildrenCacheListener listener = new PathChildrenCacheListener()
    {
        @Override
        public void childEvent(CuratorFramework client, PathChildrenCacheEvent event) throws Exception
        {
            events.add(event.getType());
        }
    };
    cache.getListenable().addListener(listener);
    cache.start(PathChildrenCache.StartMode.POST_INITIALIZED_EVENT);
    Assert.assertEquals(events.poll(timing.forWaiting().milliseconds(), TimeUnit.MILLISECONDS), PathChildrenCacheEvent.Type.CONNECTION_RECONNECTED);
    Assert.assertEquals(events.poll(timing.forWaiting().milliseconds(), TimeUnit.MILLISECONDS), PathChildrenCacheEvent.Type.INITIALIZED);

    client.create().forPath("/a/b/test/one");
    client.create().forPath("/a/b/test/two");
    Assert.assertEquals(events.poll(timing.forWaiting().milliseconds(), TimeUnit.MILLISECONDS), PathChildrenCacheEvent.Type.CHILD_ADDED);
    Assert.assertEquals(events.poll(timing.forWaiting().milliseconds(), TimeUnit.MILLISECONDS), PathChildrenCacheEvent.Type.CHILD_ADDED);

    client.delete().forPath("/a/b/test/one");
    client.delete().forPath("/a/b/test/two");
    client.delete().forPath("/a/b/test");
    Assert.assertEquals(events.poll(timing.forWaiting().milliseconds(), TimeUnit.MILLISECONDS), PathChildrenCacheEvent.Type.CHILD_REMOVED);
    Assert.assertEquals(events.poll(timing.forWaiting().milliseconds(), TimeUnit.MILLISECONDS), PathChildrenCacheEvent.Type.CHILD_REMOVED);

    timing.sleepABit();

    client.create().creatingParentContainersIfNeeded().forPath("/a/b/test/new");
    Assert.assertEquals(events.poll(timing.forWaiting().milliseconds(), TimeUnit.MILLISECONDS), PathChildrenCacheEvent.Type.CHILD_ADDED);
}
finally
{
    CloseableUtils.closeQuietly(cache);
    CloseableUtils.closeQuietly(client);
}

3.3.1.2 NodeCache

Node Cache solo monitorea un nodo específico.

NodeCache           cache = null;
Timing              timing = new Timing();
CuratorFramework    client = CuratorFrameworkFactory.newClient(server.getConnectString(), timing.session(), timing.connection(), new RetryOneTime(1));
client.start();
try
{
    client.create().forPath("/test");

    cache = new NodeCache(client, "/test/node");
    cache.start(true);

    final Semaphore     semaphore = new Semaphore(0);
    cache.getListenable().addListener
    (
        new NodeCacheListener()
        {
            @Override
            public void nodeChanged() throws Exception
            {
                semaphore.release();
            }
        }
    );

    Assert.assertNull(cache.getCurrentData());

    client.create().forPath("/test/node", "a".getBytes());
    Assert.assertTrue(timing.acquireSemaphore(semaphore));
    Assert.assertEquals(cache.getCurrentData().getData(), "a".getBytes());

    client.setData().forPath("/test/node", "b".getBytes());
    Assert.assertTrue(timing.acquireSemaphore(semaphore));
    Assert.assertEquals(cache.getCurrentData().getData(), "b".getBytes());

    client.delete().forPath("/test/node");
    Assert.assertTrue(timing.acquireSemaphore(semaphore));
    Assert.assertNull(cache.getCurrentData());
}
finally
{
    CloseableUtils.closeQuietly(cache);
    TestCleanState.closeAndTestClean(client);
}

3.3.1.3 TreeCache

Tree Cache puede monitorear todos los nodos en todo el árbol, similar a la combinación de PathCache y NodeCache.

3.3.2 Elección de líder

3.3.2.1 LeaderLatch

El constructor es el siguiente:

public LeaderLatch(CuratorFramework client, String latchPath)
public LeaderLatch(CuratorFramework client, String latchPath,  String id)

El método principal ::
start()iniciar la elección
hasLeadership(): determinar si actualmente es líder
await(): no regresar hasta convertirse en líder
close(): liberar LeaderShip

Manejo de excepciones: la
instancia de LeaderLatch puede agregar ConnectionStateListener para monitorear los problemas de conexión de red. Cuando está SUSPENDIDO
o PERDIDO, el
líder ya no piensa que sigue siendo el líder. Cuando la conexión después de LOST se vuelve a conectar y se vuelve a conectar, LeaderLatch eliminará el ZNode anterior y creará uno nuevo.

Vea el código de muestra:
TestLeaderLatch

3.3.2.2 LeaderSelector

El constructor es el siguiente:

public LeaderSelector(CuratorFramework client, String mutexPath,LeaderSelectorListener listener)
public LeaderSelector(CuratorFramework client, String mutexPath, ThreadFactory threadFactory, Executor executor, LeaderSelectorListener listener)

Métodos principales:
start()Iniciar elección
takeLeadership(): se llama cuando la instancia obtiene el liderazgo y libera el liderazgo cuando regresa
autoRequeue(): la llamada al método garantiza que la instancia también puede obtener el liderazgo después de que se libera el liderazgo.
close(): Lanzamiento LeaderShip

Manejo de excepciones: la
clase LeaderSelectorListener hereda ConnectionStateListener . LeaderSelector debe tener cuidado con los
cambios en el estado de la conexión . Si la instancia se convierte en el líder, debe corresponder a SUSPENDED o LOST. Cuando aparece el estado SUSPENDED, la
instancia debe asumir que ya no puede ser el líder antes de que la reconexión sea exitosa. Si aparece el estado PERDIDO, la
instancia ya no es el líder y el método takeLeadership regresa.

Vea el código de muestra:
TestLeaderSelector

3.3.3 Barrera

La clase DistributedBarrier implementa la función de una valla. Su constructor es el siguiente:

public DistributedBarrier(CuratorFramework client, String barrierPath)
client - client
barrierPath - path to use as the barrier

El método principal:
setBarrier()Coloque la cerca, bloqueará los hilos que
waitOnBarrier()esperan en ella : Espere la condición de liberación
removeBarrier(): Retire la cerca, todos los hilos en espera continuarán ejecutándose

Manejo de excepciones:
DistributedBarrier monitoreará el estado de la conexión y el método waitOnBarrier () lanzará una excepción cuando la conexión se desconecte.

Ver código de muestra:
TestDistributedBarrier

Double Barrier
permite al cliente sincronizar al principio y al final del cálculo. Cuando se agrega suficiente progreso a la valla doble, el progreso comienza a contar, y
cuando se completa el cálculo, abandone la valla.

Vea el código de muestra:
TestDistributedDoubleBarrier

3.3.4 Contador

DistributedAtomicLong intenta configurar el contador utilizando un bloqueo optimista.

Métodos principales:
get()Obtener el valor actual
increment(): Sumar uno
decrement(): Restar uno
add(): Aumentar un valor específico
subtract(): Restar un valor específico
trySet(): Intentar establecer el valor de recuento
forceSet(): Forzar el valor de recuento

Debes marcar el Successeded () que devuelve el resultado, que representa si la operación fue exitosa. Si la operación es exitosa,
preValue () representa el valor antes de la operación y postValue () representa el valor después de la operación.

Para obtener un código de muestra, consulte:
TestDistributedAtomicLong

3.3.5 Bloqueo

3.3.5.1 Bloqueo reentrante

Constructor:

public InterProcessMutex(CuratorFramework client, String path)

El método principal :: acquire()Adquirir el bloqueo release(): liberar el bloqueo no debe estar en

Manejo de excepciones:
use ConnectionStateListener para manejar el cambio de estado de conexión. Ya no eres dueño de la cerradura cuando te conectas a LOST.

3.3.5.2 Bloqueo no reentrante

Constructor:

public InterProcessSemaphoreMutex(CuratorFramework client, String path)

Supongo que te gusta

Origin blog.csdn.net/qq_31281327/article/details/115234064
Recomendado
Clasificación