Get the Producer instance through container, and you can deliver the message. It is not reasonable for the following examples to use Application Context directly to get the Producer. For the specific use of container, see the di module.
There are three parameters that affect the rate of consumption
- you can modify the `#[Consumer]` annotation `nums` to open multiple consumers
- The `ConsumerMessage` base class has an attribute `$qos` that controls the number of messages pulled from the server at a time by overriding `prefetch_size` or `prefetch_count` in `$qos`
-`concurrent.limit` in the configuration file, which controls the maximum number of consumer coroutines
### Consumption results
The framework will determine the response behavior of the message based on the result returned by the `consume` method in `Consumer`. There are 4 response results, namely `\Hyperf\Amqp\Result::ACK`, `\Hyperf\Amqp\ Result::NACK`, `\Hyperf\Amqp\Result::REQUEUE`, `\Hyperf\Amqp\Result::DROP`, each return value represents the following behavior:
| \Hyperf\Amqp\Result::ACK | Confirm that the message has been consumed correctly |
| \Hyperf\Amqp\Result::NACK | The message was not consumed correctly, respond with the `basic_nack` method |
| \Hyperf\Amqp\Result::REQUEUE | The message was not consumed correctly, respond with the `basic_reject` method and requeue the message |
| \Hyperf\Amqp\Result::DROP | The message was not consumed correctly, respond with the `basic_reject` method |
### Customize the number of consumer processes according to the environment
In the `#[Consumer]` annotation, you can set the number of consumer processes through the `nums` attribute. If you need to set different numbers of consumer processes according to different environments, you can override the `getNums` method. The example is as follows:
```php
#[Consumer(
exchange: 'hyperf',
routingKey: 'hyperf',
queue: 'hyperf',
name: 'hyperf',
nums: 1
)]
final class DemoConsumer extends ConsumerMessage
{
public function getNums(): int
{
if (is_debug()) {
return 10;
}
return parent::getNums();
}
}
```
## Delay queue
AMQP's delay queue is not sorted according to the delay time. Therefore, once you deliver a task with a delay of 10 seconds and then deliver a task with a delay of 5 seconds to this queue, it will definitely be in the first place. After the first 10s task is completed, the second 5s task will be consumed.
Therefore, you need to set up different queues according to time. If you want a more flexible delay queue, you can try using asynchronous queue (async-queue) in conjunction with AMQP.
In addition, AMQP needs to download [delay plug-in](https://github.com/rabbitmq/rabbitmq-delayed-message-exchange/releases) and activate it for normal use
Create a `producer` using the `gen:amqp-producer` command. Here is an example of the `direct` type. For other types such as `fanout` and `topic`, just change the `type` in the producer and consumer.
In addition to typical message queue scenarios, we can also implement RPC remote procedure calls through AMQP. This component also provides corresponding support for this implementation.
### Create consumer
The consumer used by RPC is basically the same as the consumer implementation in a typical message queue scenario. The only difference is that the data needs to be returned to the producer by calling the `reply` method.
public function consumeMessage($data, AMQPMessage $message): string
{
$data['message'] .= 'Reply:' . $data['message'];
$this->reply($data, $message);
return Result::ACK;
}
}
```
### Make an RPC call
It is also very simple to initiate an RPC remote procedure call as a generator. You only need to obtain the `Hyperf\Amqp\RpcClient` object through the dependency injection container and call the `call` method in it. The returned result is the consumer reply data. As follows:
The above RPC calling process directly completes the definition of Exchange and RoutingKey through the `Hyperf\Amqp\Message\DynamicRpcMessage` class, and transfers message data. In the design of production projects, we can perform a layer of abstraction on RpcMessage to unify Exchange. and the definition of RoutingKey.
We can create the corresponding RpcMessage class such as `App\Amqp\FooRpcMessage` as follows:
```php
<?php
use Hyperf\Amqp\Message\RpcMessage;
class FooRpcMessage extends RpcMessage
{
protected $exchange = 'hyperf';
protected $routingKey = 'hyperf';
public function __construct($data)
{
// 要传递数据
$this->payload = $data;
}
}
```
In this way, when we make an RPC call, we only need to directly pass the `FooRpcMessage` instance to the `call` method without having to define Exchange and RoutingKey every time it is called.