zoukankan      html  css  js  c++  java
  • RocketMQ消息发布报错:No accessKey is configured

    No accessKey is configured 本来这个错误是很简单个错误,本意是mq上边开启了acl验证机制,而客户端没有配置accessKey。

    但是笔者这次遇到的这个问题比较有意思,废了我半天时间去研究。在这里记录一下。


    当时笔者是先行自己封装好了一个rocket的工具库,考虑到安全问题,决定引入acl机制,然后主要是参照了网上的两个文章。
    配置mq的broker和plain_acl两个配置文件,客户端加入acl相关代码,主要是加入了AclRPCHook,在发送消息之前插入accessKey和签名供mq进行校验。
    之后用测试工程引用本地maven库上安装的rocket工具库进行测试,结果之前能用的代码在用了acl之后一直报错:提示accessKey没配置。

    然后发现直接弄个带main方法的类运行例子里的代码是可以的,一样的代码copy到测试工程里就不行了。
    分析一下应该是客户端问题,mq的acl配置应该是对的。
    接下来1天各种实验无果,开始回到起点,潜心来看源代码,搞清楚客户端的mq发送消息以及acl的源码是怎么写的。

    当调用DefaultMQProducer的send方法,同步的向mq投递消息的时候,实际上是defaultMQProducerImpl.send(msg),
    也即DefaultMQProducerImpl的sendKernelImpl方法,关键代码:
    sendResult = this.mQClientFactory.getMQClientAPIImpl().sendMessage,里边其实是MQClientAPIImpl的如下方法:

    private SendResult sendMessageSync(
            final String addr,
            final String brokerName,
            final Message msg,
            final long timeoutMillis,
            final RemotingCommand request
        ) throws RemotingException, MQBrokerException, InterruptedException {
            RemotingCommand response = this.remotingClient.invokeSync(addr, request, timeoutMillis);
            assert response != null;
            return this.processSendResponse(brokerName, msg, response,addr);
        }

    其中remotingClient是接口,其实现是netty NettyRemotingClient invokeSync(),后者会doBeforeRpcHooks(addr, request);

    if (rpcHooks.size() > 0) {
                for (RPCHook rpcHook: rpcHooks) {
                    rpcHook.doBeforeRequest(addr, request);
                }
            }

    rpcHooks这里相当于是NettyRemotingClient的成员变量。

    对于acl的DefaultMQProducer
    DefaultMQProducer实例化的时候,是把rpcHook都给到了自己的defaultMQProducerImpl。

    factory是在defaultMQProducerImpl.start()也就是DefaultMQProducer.start()的时候实例化的。

    MQClientInstance是factory的实现,实例化的时候内部

    this.mQClientAPIImpl = new MQClientAPIImpl(this.nettyClientConfig, this.clientRemotingProcessor, rpcHook, clientConfig);
    然后factory提供这个mQClientAPIImpl实例。


    defaultMQProducerImpl的start方法中实例化factory时,会判断如果生成过,就不再生成了。也就是说整个进程只会有一个factory实例。
    关键代码:

    this.mQClientFactory = MQClientManager.getInstance().getOrCreateMQClientInstance(this.defaultMQProducer, rpcHook);


    刚好工程里有另外一个transactionProducer的代码,是笔者用来测试事务消息的,没加acl代码,所以一旦先transactionProducer.start()创建了factory,
    那之后一直用这个无acl的,所以发送消息到mq的时候一直提示没有accessKey就是这个原因。


  • 相关阅读:
    hihoCoder[Offer收割]编程练习赛1题目解析
    你的计划为什么运行不下去?怎么破?
    Activity的生命周期
    leetcode——Lowest Common Ancestor of a Binary Tree
    Spring学习笔记(四)-- Spring事务全面分析
    Docker技术-cgroup
    docker高级应用之cpu与内存资源限制(转)
    JMX 学习
    如何使用JVisualVM进行性能分析
    如何利用 JConsole观察分析Java程序的运行,进行排错调优(转)
  • 原文地址:https://www.cnblogs.com/lyhero11/p/14667654.html
Copyright © 2011-2022 走看看