Este tópico apresenta um exemplo de cliente Go que usa o protocolo AMQP para se conectar à IoT Platform da Alibaba Cloud e receber mensagens de uma assinatura no lado do servidor.
Pré-requisitos
Obtenha um ID de grupo de consumidores e assine as mensagens dos tópicos necessários.
Gerenciar grupos de consumidores AMQP: Use o grupo de consumidores padrão (DEFAULT_GROUP) na IoT Platform ou crie um novo grupo.
Configurar uma assinatura AMQP no lado do servidor: Assine as mensagens dos tópicos desejados usando um grupo de consumidores.
Preparar o ambiente de desenvolvimento
Este exemplo usa a versão Go 1.12.7.
Baixe o SDK
Execute o comando a seguir para importar o SDK AMQP para Go.
import "pack.ag/amqp"
Para mais detalhes sobre como usar o SDK, consulte package amqp.
Exemplo de código
package main
import (
"os"
"context"
"crypto/hmac"
"crypto/sha1"
"encoding/base64"
"fmt"
"pack.ag/amqp"
"time"
)
// For parameter descriptions, see the AMQP client connection guide.
const consumerGroupId = "${YourConsumerGroupId}"
const clientId = "${YourClientId}"
// iotInstanceId: The instance ID.
const iotInstanceId = "${YourIotInstanceId}"
// The endpoint. For more information, see the AMQP client connection guide.
const host = "${YourHost}"
func main() {
// If you leak the project code, your AccessKey may be exposed. This compromises the security of all resources in your account.
// The following code provides an example on how to use an environment variable to obtain the AccessKey. This method is for reference only.
accessKey := os.Getenv("ALIBABA_CLOUD_ACCESS_KEY_ID")
accessSecret := os.Getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET")
address := "amqps://" + host + ":5671"
timestamp := time.Now().Nanosecond() / 1000000
// For information about how to construct the user name, see the AMQP client connection guide.
userName := fmt.Sprintf("%s|authMode=aksign,signMethod=Hmacsha1,consumerGroupId=%s,authId=%s,iotInstanceId=%s,timestamp=%d|",
clientId, consumerGroupId, accessKey, iotInstanceId, timestamp)
stringToSign := fmt.Sprintf("authId=%s×tamp=%d", accessKey, timestamp)
hmacKey := hmac.New(sha1.New, []byte(accessSecret))
hmacKey.Write([]byte(stringToSign))
// Calculate the signature. For information about how to construct the password, see the AMQP client connection guide.
password := base64.StdEncoding.EncodeToString(hmacKey.Sum(nil))
amqpManager := &AmqpManager{
address:address,
userName:userName,
password:password,
}
// To accept messages or cancel operations, derive the context from context.Background().
ctx := context.Background()
amqpManager.startReceiveMessage(ctx)
}
// Business function. This is a custom implementation. The function is executed asynchronously. Consider the resource consumption of your system.
func (am *AmqpManager) processMessage(message *amqp.Message) {
fmt.Println("data received:", string(message.GetData()), " properties:", message.ApplicationProperties)
}
type AmqpManager struct {
address string
userName string
password string
client *amqp.Client
session *amqp.Session
receiver *amqp.Receiver
}
func (am *AmqpManager) startReceiveMessage(ctx context.Context) {
childCtx, _ := context.WithCancel(ctx)
err := am.generateReceiverWithRetry(childCtx)
if nil != err {
return
}
defer func() {
am.receiver.Close(childCtx)
am.session.Close(childCtx)
am.client.Close()
}()
for {
// Blocks to receive messages. If the context is background, the process is not interrupted.
message, err := am.receiver.Receive(ctx)
if nil == err {
go am.processMessage(message)
message.Accept()
} else {
fmt.Println("amqp receive data error:", err)
// If the operation is actively canceled, exit the program.
select {
case <- childCtx.Done(): return
default:
}
// If the operation is not actively canceled, re-establish the connection.
err := am.generateReceiverWithRetry(childCtx)
if nil != err {
return
}
}
}
}
func (am *AmqpManager) generateReceiverWithRetry(ctx context.Context) error {
// Back off and reconnect. Start with 10 ms and double the interval up to 20s.
duration := 10 * time.Millisecond
maxDuration := 20000 * time.Millisecond
times := 1
// In case of an exception, back off and reconnect.
for {
select {
case <- ctx.Done(): return amqp.ErrConnClosed
default:
}
err := am.generateReceiver()
if nil != err {
time.Sleep(duration)
if duration < maxDuration {
duration *= 2
}
fmt.Println("amqp connect retry,times:", times, ",duration:", duration)
times ++
} else {
fmt.Println("amqp connect init success")
return nil
}
}
}
// The connection and session states cannot be determined because the package is not visible. Restart the connection to retrieve the states.
func (am *AmqpManager) generateReceiver() error {
if am.session != nil {
receiver, err := am.session.NewReceiver(
amqp.LinkSourceAddress("/queue-name"),
amqp.LinkCredit(20),
)
// If a network disconnection occurs, the connection closes and session creation fails.
// If the connection remains open, the session is created successfully.
if err == nil {
am.receiver = receiver
return nil
}
}
// Clean up the previous connection.
if am.client != nil {
am.client.Close()
}
client, err := amqp.Dial(am.address, amqp.ConnSASLPlain(am.userName, am.password), )
if err != nil {
return err
}
am.client = client
session, err := client.NewSession()
if err != nil {
return err
}
am.session = session
receiver, err := am.session.NewReceiver(
amqp.LinkSourceAddress("/queue-name"),
amqp.LinkCredit(20),
)
if err != nil {
return err
}
am.receiver = receiver
return nil
}
Configure os parâmetros do código anterior conforme descrito na tabela a seguir. Para mais informações, consulte Conectar um cliente AMQP à IoT Platform.
Especifique valores válidos para os parâmetros. Caso contrário, o cliente AMQP não conseguirá se conectar à IoT Platform.
|
Parâmetro |
Descrição |
|
accessKey |
Faça login no console da IoT Platform, passe o mouse sobre sua foto de perfil e clique em AccessKey Management para obter o AccessKey ID e o AccessKey secret. Nota
Se você usar um usuário do Resource Access Management (RAM), conceda a permissão AliyunIOTFullAccess a esse usuário. Essa permissão é necessária para gerenciar a IoT Platform. Sem ela, a conexão falhará. Para saber como conceder permissões, consulte Acesso de usuários RAM. |
|
accessSecret |
|
|
consumerGroupId |
ID do grupo de consumidores na instância da IoT Platform. Faça login no console da IoT Platform. Na instância correspondente, acesse para visualizar o ID do seu grupo de consumidores. |
|
iotInstanceId |
ID da instância. Visualize o ID da instância atual na página Instance Overview no console da IoT Platform.
|
|
clientId |
ID do cliente. Defina este ID, que pode ter até 64 caracteres. Recomendamos usar um identificador exclusivo, como UUID, endereço MAC ou endereço IP do servidor onde o cliente AMQP está localizado. Após a conexão e inicialização do cliente AMQP, faça login no console da IoT Platform. Na aba Consumer Groups da página da instância, clique em View ao lado do grupo de consumidores. A página Consumer Group Details exibirá este parâmetro, facilitando a identificação dos diferentes clientes. |
|
host |
Endpoint AMQP. Para obter informações sobre o endpoint AMQP correspondente a |
Resultados da execução de exemplo
-
Sucesso: Uma mensagem de log semelhante à seguinte é retornada, indicando que o cliente AMQP se conectou com êxito à IoT Platform e recebeu mensagens do dispositivo.
amqp connect init success data received: {"deviceType":"CustomCategory","iotId":"xxx","requestId":"1613726251726","checkFailedData":0,"productKey":"xxx","gmtCreate":"1613726121717,"deviceName":"xxx","items":{"Temperature":{"value":24,"time":1613726121715},"Humidity":{"value":19,"time":1613726121715}}} properties: map[generateTime:1613726121721 messageId:xxx xxx s:1 topic: /xxx/thing/event/property/post] data received: {"deviceType":"CustomCategory","iotId":"xxx","requestId":"1613725651726","checkFailedData":0,"productKey":"xxx","gmtCreate":"1613725521715,"deviceName":"xxx","items":{"Temperature":{"value":28,"time":1613725521712},"Humidity":{"value":19,"time":1613725521712}}} properties: map[generateTime:1613725521719 messageId:1362689721104473600 qos:1 topic: /xxx/thing/event/property/post] -
Falha: Uma mensagem de log semelhante à seguinte é retornada, indicando que o cliente AMQP não conseguiu se conectar à IoT Platform.
Use o log de erros para verificar seu código e as configurações de rede. Corrija o problema e execute o código novamente.
amqp connect retry,times: 1 ,duration: 20ms amqp connect retry,times: 2 ,duration: 40ms amqp connect retry,times: 3 ,duration: 80ms amqp connect retry,times: 4 ,duration: 160ms amqp connect retry,times: 5 ,duration: 320ms amqp connect retry,times: 6 ,duration: 640ms amqp connect retry,times: 7 ,duration: 1.28s amqp connect retry,times: 8 ,duration: 2.56s amqp connect retry,times: 9 ,duration: 5.12s amqp connect retry,times: 10 ,duration: 10.24s amqp connect retry,times: 11 ,duration: 20.48s
Referências
Para mais informações sobre códigos de erro relacionados a mensagens de assinatura no lado do servidor, consulte Códigos de erro relacionados a mensagens.