Rabbitmq 406 error

RabbitMQ Аномально ответный код = 406, repile-text = precondition_faird-invalid arg ‘x-amssage-ttl‘ для очереди .., Русские Блоги, лучший сайт для обмена техническими статьями программиста.

Предисловие

(НЕОБХОДИМОСТЬ МЕТО ВСТАТЬ НА ЯМЕ позже, запишите здесь)

Это исключение было встречено временем настройки очереди настройки. Через долгое время я нашел много информации. Большая часть информации была двумя решениями:

1. Если очередь настроена автоматически, очередь удаляется напрямую.

2. Если клиент не настраивает автоматическую очередь создания, вручную перейдите к клиенту MQ, чтобы создать очередь и установить соответствующее значение TTL.

Ненормальный и раствор

Я попробовал два вышеупомянутых метода, и я все еще не решил эту проблему. Позже я наконец получил его после непрерывного теста.

Клиент автоматически создает очередь (это, как правило, то же самое), установите очередь X-Message-TTL, чтобы истечь, но не указывайте тип (я в данном случае)

Конфигурация:

@RabbitListener(bindings = {
            @QueueBinding(
                    Value = @queue (value = "direct.info", // указать имя очереди, длинная очередь по умолчанию, если не указано, временная очередь не указана.
                            arguments = {
                                                         @Argument (name = "x-dead-altter-excmeatory", value = "dlx.exchange"), // указать смертельный переключатель букв
                                                         @Argument (name = "x-dead-key-key", value = "deadkey"), // ключ для маршрута, чтобы указать переключатель мертвой буквы
                                                         @Argument (name = "x-amssage-ttl", value = "3000") // Укажите время истечения срока очереди
                    }),
                                         Exchange = @Exchenge (value = "Directions"), // Тип по умолчанию Exchange является прямым, поэтому тип не может писать без написания
                    key = {"info"}
            )
    })
    private void receive(Message message, Channel channel) throws Exception{
        System.out.println(new String(message.getBody()));
}

Начните клиента, чтобы сообщить об ошибке:

Caused by: com.rabbitmq.client.ShutdownSignalException: channel error; protocol method: #method<channel.close>(reply-code=406, reply-text=PRECONDITION_FAILED — invalid arg ‘x-message-ttl’ for queue ‘direct.info’ in vhost ‘/test’: {unacceptable_type,longstr}, class-id=50, method-id=10)

Обратите внимание, что красный шрифт отмечен, вероятно, смысл неприемлемого, но этоlongstrЯ не знаю, что это за тип. Оба анти -полная и строка попробуйте, сначала посмотрите на параметры @Argument

@Target({})
@Retention(RetentionPolicy.RUNTIME)
public @interface Argument {
    String name();

    String value() default "";

    String type() default "java.lang.String";
}

Если тип не указан, он по умолчанию типа укуса, затем замените его на долгое время, измените код

@Argument (name = "x-amssage-ttl", value = "3000", type = "java.lang.long") //

В результате это было неожиданно, и аномалия исчезла …

Резюме: это исключение состоит в том, чтобы указать тип типа X-Message-TTL. Вы не можете использовать строку по умолчанию. Лучше изменить ее на длинный тип. Я не знаю, почему это сделано. Как насчет строки по умолчанию ?

Другие случаи

Запишите здесь для других несчастных случаев

Создайте очередь на клиенте MQ и укажитеx-message-ttlВ настоящее время тип должен выбрать номер, а не выбрать строку. Если вы выберете String, вы запустите ошибку

Когда вы выбираете номер и успешно создаете очередь, но если @Argument (name = «x-amssage-ttl», value = «3000»).

Caused by: com.rabbitmq.client.ShutdownSignalException: channel error; protocol method: #method<channel.close>(reply-code=406, reply-text=PRECONDITION_FAILED — inequivalent arg ‘x-message-ttl’ for queue ‘direct.info’ in vhost ‘/test’: received ‘3000’ but current is ‘3000’, class-id=50, method-id=10)

Я видел эту аномальность в то время. X-Message-TTL, настроенный клиентом MQ, был, очевидно, 3000,@Arger (name = «x-amssage-ttl», value = «3000») также установлен. Почему вы сделали сообщить о таком исключении?В последнем анализе вам все еще нужно указать тип как java.lang.long при настройке X-Message-TTL (строка по умолчанию невозможна)

Not a fun way to start a Saturday morning. With a bit of spare time this morning I wanted to continue some refactoring work on a tool I’ve been working on for checking broken links on any given website.

The project is quite cool (in my opinion), using a bunch of interesting software / tech such as RabbitMQ with Symfony’s Messenger component, STOMP for real time stuff, React with Hooks, Tailwinds for CSS… and a bunch more buzz-wordy, CV helping stuff that keeps me gainfully employed.

Anyway, the first thing I did was spin up the Symfony docker containers that run the various services to handle incoming broken link checking requests. And as ever, I ran a composer update to bring Symfony up to 4.3.x.

I’m not sure if bumping up to Symfony 4.3 was the cause of this problem. I suspect not. It’s been a while since I’ve worked on this part of the code, but it was all working the last time I brought the project up. And it’s working live and online, too, so something has gone awry.

Anyway, after the composer update completed successfully:

composer update
Loading composer repositories with package information
Updating dependencies (including require-dev)

Prefetching 49 packages 🎶 💨
  - Downloading (100%)

Package operations: 7 installs, 42 updates, 1 removal
  - Removing symfony/contracts (v1.0.2)
  - Updating symfony/flex (v1.2.3 => v1.2.5): Loading from cache
  - Installing symfony/service-contracts (v1.1.2): Loading from cache
  - Installing symfony/polyfill-php73 (v1.11.0): Loading from cache
  - Updating symfony/console (v4.2.8 => v4.3.0): Loading from cache
  - Installing symfony/event-dispatcher-contracts (v1.1.1): Loading from cache
  - Updating symfony/event-dispatcher (v4.2.8 => v4.3.0): Loading from cache
  - Updating symfony/css-selector (v4.2.8 => v4.3.0): Loading from cache
  - Updating symfony/dom-crawler (v4.2.8 => v4.3.0): Loading from cache
  - Updating symfony/messenger (v4.2.8 => v4.3.0): Loading from cache
  - Updating symfony/process (v4.2.8 => v4.3.0): Loading from cache
  - Updating symfony/serializer (v4.2.8 => v4.3.0): Loading from cache
  - Updating symfony/routing (v4.2.8 => v4.3.0): Loading from cache
  - Updating symfony/finder (v4.2.8 => v4.3.0): Loading from cache
  - Updating symfony/filesystem (v4.2.8 => v4.3.0): Loading from cache
  - Updating symfony/debug (v4.2.8 => v4.3.0): Loading from cache
  - Installing symfony/polyfill-intl-idn (v1.11.0): Loading from cache
  - Installing symfony/mime (v4.3.0): Loading from cache
  - Updating symfony/http-foundation (v4.2.8 => v4.3.0): Loading from cache
  - Updating symfony/http-kernel (v4.2.8 => v4.3.0): Loading from cache
  - Updating symfony/dependency-injection (v4.2.8 => v4.3.0): Loading from cache
  - Updating symfony/config (v4.2.8 => v4.3.0): Loading from cache
  - Updating symfony/var-exporter (v4.2.8 => v4.3.0): Loading from cache
  - Installing symfony/cache-contracts (v1.1.1): Loading from cache
  - Updating symfony/cache (v4.2.8 => v4.3.0): Loading from cache
  - Updating symfony/framework-bundle (v4.2.8 => v4.3.0): Loading from cache
  - Installing symfony/translation-contracts (v1.1.2): Loading from cache
  - Updating symfony/validator (v4.2.8 => v4.3.0): Loading from cache
  - Updating symfony/yaml (v4.2.8 => v4.3.0): Loading from cache
  - Updating nikic/php-parser (v4.2.1 => v4.2.2): Loading from cache
  - Updating symfony/translation (v4.2.8 => v4.3.0): Loading from cache
  - Updating nesbot/carbon (2.17.1 => 2.19.0): Loading from cache
  - Updating illuminate/contracts (v5.8.15 => v5.8.19): Loading from cache
  - Updating illuminate/support (v5.8.15 => v5.8.19): Loading from cache
  - Updating symfony/inflector (v4.2.8 => v4.3.0): Loading from cache
  - Updating symfony/property-access (v4.2.8 => v4.3.0): Loading from cache
  - Updating symfony/property-info (v4.2.8 => v4.3.0): Loading from cache
  - Updating symfony/monolog-bridge (v4.2.8 => v4.3.0): Loading from cache
  - Updating symfony/dotenv (v4.2.8 => v4.3.0): Loading from cache
  - Updating symfony/phpunit-bridge (v4.2.8 => v4.3.0): Loading from cache
  - Updating symfony/expression-language (v4.2.8 => v4.3.0): Loading from cache
  - Updating symfony/stopwatch (v4.2.8 => v4.3.0): Loading from cache
  - Updating composer/xdebug-handler (1.3.2 => 1.3.3): Loading from cache
  - Updating symfony/var-dumper (v4.2.8 => v4.3.0): Loading from cache
  - Updating twig/twig (v2.9.0 => v2.11.0): Loading from cache
  - Updating symfony/twig-bridge (v4.2.8 => v4.3.0): Loading from cache
  - Updating symfony/debug-bundle (v4.2.8 => v4.3.0): Loading from cache
  - Updating symfony/twig-bundle (v4.2.8 => v4.3.0): Loading from cache
  - Updating symfony/web-profiler-bundle (v4.2.8 => v4.3.0): Loading from cache
  - Updating roave/security-advisories (dev-master 1dfa887 => dev-master 4c0ba8a)
Writing lock file
Generating autoload files
ocramius/package-versions:  Generating version class...
ocramius/package-versions: ...done generating version class

What about running composer global require symfony/thanks &amp;&amp; composer thanks now?
This will spread some 💖  by sending a ★  to the GitHub repositories of your fellow package maintainers.

Executing script cache:clear [OK]
Executing script assets:install public [OK]

I tried to run my messenger consumer:

www-data@1fbf5db0f719:~/app.checkforbrokenlinks.com$ bin/console messenger:consume --bus messenger.bus.fetch fetch -vvv

                                                                                                                        
 [OK] Consuming messages from transports "fetch".                                                                       
                                                                                                                        

 // The worker will automatically exit once it has received a stop signal via the messenger:stop-workers command.       

 // Quit the worker with CONTROL-C.                                                                                     


In AmqpReceiver.php line 56:
                                                                                                                                                             
  [SymfonyComponentMessengerExceptionTransportException]                                                                                                 
  Server channel error: 406, message: PRECONDITION_FAILED - inequivalent arg 'type' for exchange 'fetch' in vhost '/': received 'fanout' but current is 'di  
  rect'                                                                                                                                                      
                                                                                                                                                             

Exception trace:
 () at /var/www/app.checkforbrokenlinks.com/vendor/symfony/messenger/Transport/AmqpExt/AmqpReceiver.php:56
 SymfonyComponentMessengerTransportAmqpExtAmqpReceiver->getEnvelope() at /var/www/app.checkforbrokenlinks.com/vendor/symfony/messenger/Transport/AmqpExt/AmqpReceiver.php:47
 SymfonyComponentMessengerTransportAmqpExtAmqpReceiver->get() at /var/www/app.checkforbrokenlinks.com/vendor/symfony/messenger/Worker.php:92
 SymfonyComponentMessengerWorker->run() at /var/www/app.checkforbrokenlinks.com/vendor/symfony/messenger/Worker/StopWhenRestartSignalIsReceived.php:54
 SymfonyComponentMessengerWorkerStopWhenRestartSignalIsReceived->run() at /var/www/app.checkforbrokenlinks.com/vendor/symfony/messenger/Command/ConsumeMessagesCommand.php:224
 SymfonyComponentMessengerCommandConsumeMessagesCommand->execute() at /var/www/app.checkforbrokenlinks.com/vendor/symfony/console/Command/Command.php:255
 SymfonyComponentConsoleCommandCommand->run() at /var/www/app.checkforbrokenlinks.com/vendor/symfony/console/Application.php:939
 SymfonyComponentConsoleApplication->doRunCommand() at /var/www/app.checkforbrokenlinks.com/vendor/symfony/framework-bundle/Console/Application.php:87
 SymfonyBundleFrameworkBundleConsoleApplication->doRunCommand() at /var/www/app.checkforbrokenlinks.com/vendor/symfony/console/Application.php:273
 SymfonyComponentConsoleApplication->doRun() at /var/www/app.checkforbrokenlinks.com/vendor/symfony/framework-bundle/Console/Application.php:73
 SymfonyBundleFrameworkBundleConsoleApplication->doRun() at /var/www/app.checkforbrokenlinks.com/vendor/symfony/console/Application.php:149
 SymfonyComponentConsoleApplication->run() at /var/www/app.checkforbrokenlinks.com/bin/console:39

In Connection.php line 348:
                                                                                                                                                             
  [AMQPExchangeException (406)]                                                                                                                              
  Server channel error: 406, message: PRECONDITION_FAILED - inequivalent arg 'type' for exchange 'fetch' in vhost '/': received 'fanout' but current is 'di  
  rect'                                                                                                                                                      
                                                                                                                                                             

Exception trace:
 () at /var/www/app.checkforbrokenlinks.com/vendor/symfony/messenger/Transport/AmqpExt/Connection.php:348
 AMQPExchange->declareExchange() at /var/www/app.checkforbrokenlinks.com/vendor/symfony/messenger/Transport/AmqpExt/Connection.php:348
 SymfonyComponentMessengerTransportAmqpExtConnection->setup() at /var/www/app.checkforbrokenlinks.com/vendor/symfony/messenger/Transport/AmqpExt/Connection.php:311
 SymfonyComponentMessengerTransportAmqpExtConnection->get() at /var/www/app.checkforbrokenlinks.com/vendor/symfony/messenger/Transport/AmqpExt/AmqpReceiver.php:54
 SymfonyComponentMessengerTransportAmqpExtAmqpReceiver->getEnvelope() at /var/www/app.checkforbrokenlinks.com/vendor/symfony/messenger/Transport/AmqpExt/AmqpReceiver.php:47
 SymfonyComponentMessengerTransportAmqpExtAmqpReceiver->get() at /var/www/app.checkforbrokenlinks.com/vendor/symfony/messenger/Worker.php:92
 SymfonyComponentMessengerWorker->run() at /var/www/app.checkforbrokenlinks.com/vendor/symfony/messenger/Worker/StopWhenRestartSignalIsReceived.php:54
 SymfonyComponentMessengerWorkerStopWhenRestartSignalIsReceived->run() at /var/www/app.checkforbrokenlinks.com/vendor/symfony/messenger/Command/ConsumeMessagesCommand.php:224
 SymfonyComponentMessengerCommandConsumeMessagesCommand->execute() at /var/www/app.checkforbrokenlinks.com/vendor/symfony/console/Command/Command.php:255
 SymfonyComponentConsoleCommandCommand->run() at /var/www/app.checkforbrokenlinks.com/vendor/symfony/console/Application.php:939
 SymfonyComponentConsoleApplication->doRunCommand() at /var/www/app.checkforbrokenlinks.com/vendor/symfony/framework-bundle/Console/Application.php:87
 SymfonyBundleFrameworkBundleConsoleApplication->doRunCommand() at /var/www/app.checkforbrokenlinks.com/vendor/symfony/console/Application.php:273
 SymfonyComponentConsoleApplication->doRun() at /var/www/app.checkforbrokenlinks.com/vendor/symfony/framework-bundle/Console/Application.php:73
 SymfonyBundleFrameworkBundleConsoleApplication->doRun() at /var/www/app.checkforbrokenlinks.com/vendor/symfony/console/Application.php:149
 SymfonyComponentConsoleApplication->run() at /var/www/app.checkforbrokenlinks.com/bin/console:39

messenger:consume [-l|--limit LIMIT] [-m|--memory-limit MEMORY-LIMIT] [-t|--time-limit TIME-LIMIT] [--sleep SLEEP] [-b|--bus BUS] [-h|--help] [-q|--quiet] [-v|vv|vvv|--verbose] [-V|--version] [--ansi] [--no-ansi] [-n|--no-interaction] [-e|--env ENV] [--no-debug] [--] &lt;command> [&lt;receivers>...]

Knickers. It all blew up quite badly.

There’s a lot of info to process, and without some nice terminal colouring it’s all a bit of a blur.

The interesting line is:

Server channel error: 406, message: PRECONDITION_FAILED - inequivalent arg 'type' for exchange 'my_exchange' in vhost '/': received 'fanout' but current is 'direct'

What I think has gone wrong is that at some point in the past, I’ve switched over my RabbitMQ exchange to use direct, and by default, Symfony’s Messenger component will try to create an exchange with the type of fanout.

To clarify, my exchange and queue combo already exists at: amqp://{username}:{password}@rabbitmq:5672/%2f/fetch

It exists because I have previously configured my RabbitMQ instance to boot up with this exchange / queue combo ready and good to go.

Because Symfony’s Messenger component is not immediately aware that this queue will already exist, it tries to create it.

It cannot create it because the default type of exchange that Symfony’s Messenger component will try to use is fanout.

In order to make this work, I needed to manually specify the config that explicitly sets this exchange / queue combo to the desired setting of direct.

Finding this out via the documentation wasn’t super straightforward. Here’s a few of the steps I took:

bin/console config:dump-reference framework

This shows that for each framework.messenger.transports entry in your config/packages/messenger.yaml file, you can have a variety of additional settings.

As it was, my original config looked like this:

By providing just a DSN (by way of environment variables), all the default config would be used.

What I needed to do was swap over to this:

framework:
    messenger:
        transports:
             fetch:
                dsn: '%env(MESSENGER_TRANSPORT_DSN_FETCH)%'
                options:
                    exchange:
                        type: 'direct'
             scrape:
                dsn: '%env(MESSENGER_TRANSPORT_DSN_SCRAPE)%'
                options:
                    exchange:
                        type: 'direct'

And after doing so, it all started working again:

In short, this isn’t directly a Symfony / Symfony Messenger problem. It’s a config problem. The messaging could be a little more clear, as could the documentation for what things are viable as options.

1. The error information is as follows:

File «C:projectsproject_namemqrabbitclient.py», line 26, in __init__
self.channel.queue_declare(queue=conf.queue_name)
File «C:envproject_namelibsite-packagespikaadaptersblocking_connection.py», line 2507, in queue_declare
self._flush_output(declare_ok_result.is_ready)
File «C:envproject_namelibsite-packagespikaadaptersblocking_connection.py», line 1340, in _flush_output
raise self._closing_reason # pylint: disable=E0702

pika.exceptions.ChannelClosedByBroker: (406, «PRECONDITION_FAILED — parameters for queue ‘test_queue’ in vhost ‘/test’ not equivalent»)

2. The code is as follows:

# -*- coding: utf-8 -*-

import json
import pika
import Config


class RabbitMQClient(object):
    """
    RabbitMQ Client
    """
    def __init__(self):
        conf = Config()
        credentials = pika.PlainCredentials(conf.rabbit_user, conf.rabbit_password)
        self.conn = pika.BlockingConnection(pika.ConnectionParameters(
            host=conf.rabbit_ip,
            port=conf.rabbit_port,
            virtual_host=conf.vhost,
            credentials=credentials
        ))

        self.channel = self.conn.channel()
        self.exchange = conf.exchange
        self.routing_key = conf.routing_key
        self.channel.exchange_declare(exchange=self.exchange, exchange_type='direct', durable=True)
        self.channel.queue_declare(queue=conf.queue_name)
        self.channel.queue_bind(
            queue=conf.queue_name,
            exchange=self.exchange,
            routing_key=self.routing_key
        )

    def send(self, msg):
        try:
            self.channel.basic_publish(
                exchange=self.exchange,
                routing_key=self.routing_key,
                body=json.dumps(msg),
                properties=pika.BasicProperties(
                    delivery_mode=2
                )
            )
        except Exception as e:
            raise e

    def close(self):
        self.conn.close()


if __name__ == '__main__':
        client = RabbitMQClient()
        client.send(exec_info)
        client.close()

3. Positioning problem

We added the following parameters when declaring Exchange: durable = true, representative persistence;
When the information is issued, the following parameters are added: DELIVERY_MODE = 2, represents persistence messages;
How do we look at the queue?
In Rabbitmq, you don’t lose your message after you want to restart. To add DELIVERY_MODE = 2 parameters for information, only for message boiling limit, after the MQ restart, Exchange and Queue are all lost, and it is also necessary for Exchange and Queue. Doing persistence is controlled by durable = true.

Therefore, modify the above code 26th line is as follows:
self.channel.queue_declare(queue=conf.queue_name, durable=True)
Test again will not report it.

I’m new to Docker and RabbitMQ and I’ve been trying for 2 days to solve an error in my docker containers which contains: api_client, api_consumer, RabbitMQ. I’ve done a research and tried to read as many threads with this problem as I found but unfortunately nothing helped.

So here is my code:
compose.yml

  services:
    api_client:
     build:
      context: ""
      dockerfile: apps/api_client/Dockerfile
     env_file:
      - ./config/.env.local
     restart: always
     ports:
       - "3000:3000"
     depends_on:
       - rabbitmq

    api_consumer:
     build:
      context: ""
      dockerfile: apps/api_consumer/Dockerfile
    env_file:
      - ./config/.env.local
    restart: always
    depends_on:
      - rabbitmq

  rabbitmq:
    image: rabbitmq:3.9.2-management
    container_name: rabbitmq
    hostname: rabbitmq
    volumes:
      - /var/lib/rabbitmq
      - ./rabbitmq.conf:/etc/rabbitmq/rabbitmq.conf
    ports:
      - "5672:5672"
      - "15672:15672"

main.ts (in api_consumer)

async function bootstrap() {
    const app = await NestFactory.createMicroservice<MicroserviceOptions>(
        ApiConsumerModule,
        {
            transport: Transport.RMQ,
            options: {
                queue: 'test_queue',
                urls: ['amqp://guest:[email protected]:5672'],
                queueOptions: {
                    durable: true
                }
            }
        },
    );
    const AWSAppConfig = app.get(AwsAppconfigLoaderService);
    const Log = new Logger(ApiClientService.name);

    await AWSAppConfig.loadAWSAppConfig()
        .then((_) => {
            Log.log(AWSAppConfig.getAppName());
        })
        .catch((err) => {
            Log.error(
                `Error occured while downloading AWS Config: ${JSON.stringify(
                    err,
                )}`,
            );
        });

    await app.listen();
}
bootstrap();

api-client.module.ts (in api_client)

@Module({
    imports: [
        ConfigModule.forRoot({
            isGlobal: true,
            load: [AppConfig],
        }),
        ClientsModule.register([{
            name: GET_MATCHED_DEVICES,
            transport: Transport.RMQ,
            options: {
                queue: 'test_queue',
                urls: ['amqp://guest:[email protected]:5672'],
                queueOptions: {
                    durable: true
                }
            }
        },
        ]),
        AwsAppconfigLoaderModule,
    ],
    controllers: [ApiClientController],
    providers: [ApiClientService],
})
export class ApiClientModule {}

Functionality is simple- when GET on localhost:3000 (api_client) is called, it calls (in controller)
return this.client.send('getSample', "hello")

and then in api_consumer it should call (in controller)

@MessagePattern('getSample')
    getSample(data): string {
        Logger.debug(data)
        return "It works!";
    }

When all docker services start there is the first error:

Disconnected from RMQ. Trying to reconnect.
{
 "err": {
  "code": 406,
  "classId": 60,
  "methodId": 40
 }
}

And then when I try to access the localhost:3000, this error always occur:

Error: Channel closed by server: 406 (PRECONDITION-FAILED) with message "PRECONDITION_FAILED - fast reply consumer does not exist"

Both errors come from api_client.

What I’ve tried and didn’t help:
-change durable to false or remove durable options completely
-add noAck
-remove queue in adminer on localhost:15672 (which works fine)
-remove port from urls in both microservices
-as you can see the queue options are the same in both microservices

Now the most absurd thing is that this code did work absolutely fine until I started to work on second compose file (and dockerfiles) for local (faster) development with volumes. Then suddenly these errors have started to occur and even if I undid all my code changes the errors are still there. Because of this I’ve wiped all my volumes (with docker system prune -a —volumes) many times but still nothing. My OS is Ubuntu 20.04
I am completely out of ideas so I’ve written it here in hope for some help, please.

Понравилась статья? Поделить с друзьями:
  • Rabbit listener error handler
  • Rails translation missing error
  • Rabbit error destiny 2
  • Rails rescue error
  • Rails flash error