The hardest core of the station, one million words strong liver, RocketMq source code is hot and updated~

Posted by jtown on Fri, 21 Jan 2022 12:18:30 +0100

@Override
public void updateBrokerConfig(String brokerAddr,
    Properties properties) throws RemotingConnectException, RemotingSendRequestException,
    RemotingTimeoutException, UnsupportedEncodingException, InterruptedException, MQBrokerException {
    defaultMQAdminExtImpl.updateBrokerConfig(brokerAddr, properties);
}

@Override
public Properties getBrokerConfig(final String brokerAddr) throws RemotingConnectException,
    RemotingSendRequestException, RemotingTimeoutException, UnsupportedEncodingException, InterruptedException, MQBrokerException {
    return defaultMQAdminExtImpl.getBrokerConfig(brokerAddr);
}

@Override
public void createAndUpdateTopicConfig(String addr, TopicConfig config) throws RemotingException, MQBrokerException,
    InterruptedException, MQClientException {
    defaultMQAdminExtImpl.createAndUpdateTopicConfig(addr, config);
}

The next three methods

Update broker configuration

Get the configuration of the broker

Create or upgrade broker configuration

@Override
public void createAndUpdatePlainAccessConfig(String addr,
    PlainAccessConfig config) throws RemotingException, MQBrokerException, InterruptedException, MQClientException {
    defaultMQAdminExtImpl.createAndUpdatePlainAccessConfig(addr, config);
}

@Override public void deletePlainAccessConfig(String addr,
    String accessKey) throws RemotingException, MQBrokerException, InterruptedException, MQClientException {
    defaultMQAdminExtImpl.deletePlainAccessConfig(addr, accessKey);
}

Addition, deletion and modification of ordinary access

@Override public void updateGlobalWhiteAddrConfig(String addr,
    String globalWhiteAddrs) throws RemotingException, MQBrokerException, InterruptedException, MQClientException {
    defaultMQAdminExtImpl.updateGlobalWhiteAddrConfig(addr, globalWhiteAddrs);
}

Update the global whitelist configuration, which is a global whitelist address

@Override public ClusterAclVersionInfo examineBrokerClusterAclVersionInfo(
    String addr) throws RemotingException, MQBrokerException, InterruptedException, MQClientException {
    return defaultMQAdminExtImpl.examineBrokerClusterAclVersionInfo(addr);
}

@Override public AclConfig examineBrokerClusterAclConfig(
    String addr) throws RemotingException, MQBrokerException, InterruptedException, MQClientException {
    return defaultMQAdminExtImpl.examineBrokerClusterAclConfig(addr);
}

Check the acl version information of the broker cluster and check the acl configuration of the broker cluster

This involves the concept of acl

RocketMQ ACL User Guide

ACL is short for access control list, commonly known as access control list. Access control basically involves the concepts of user, resource, permission and role. What objects do the above correspond to in RocketMQ?

  • user
    User is the basic element of access control, and it is not difficult to understand. RocketMQ ACL will inevitably introduce the concept of user, that is, it supports user name and password.
  • resources
    Resources, objects to be protected. In RocketMQ, topics involved in message sending and consumption groups involved in message consumption should be protected, so they can be abstracted into resources.
  • jurisdiction
    Operations that can be performed for resources,
  • role
    In RocketMQ, only two roles are defined: administrator or not.

In addition, RocketMQ also supports setting the whitelist according to the client IP.

Back to the code

@Override
public void createAndUpdateSubscriptionGroupConfig(String addr,
    SubscriptionGroupConfig config) throws RemotingException,
    MQBrokerException, InterruptedException, MQClientException {
    defaultMQAdminExtImpl.createAndUpdateSubscriptionGroupConfig(addr, config);
}

@Override
public SubscriptionGroupConfig examineSubscriptionGroupConfig(String addr, String group)
    throws InterruptedException, RemotingException, MQClientException, MQBrokerException {
    return defaultMQAdminExtImpl.examineSubscriptionGroupConfig(addr, group);
}

@Override
public TopicConfig examineTopicConfig(String addr, String topic) throws RemotingException, InterruptedException, MQBrokerException {
    return defaultMQAdminExtImpl.examineTopicConfig(addr, topic);
}

@Override
public TopicStatsTable examineTopicStats(
    String topic) throws RemotingException, MQClientException, InterruptedException,
    MQBrokerException {
    return defaultMQAdminExtImpl.examineTopicStats(topic);
}

Create and update subscription group configuration

View subscription group configuration

Check topic configuration

Check topic status

@Override
public TopicList fetchAllTopicList() throws RemotingException, MQClientException, InterruptedException {
    return this.defaultMQAdminExtImpl.fetchAllTopicList();
}

@Override
public TopicList fetchTopicsByCLuster(
    String clusterName) throws RemotingException, MQClientException, InterruptedException {
    return this.defaultMQAdminExtImpl.fetchTopicsByCLuster(clusterName);
}

@Override
public KVTable fetchBrokerRuntimeStats(
    final String brokerAddr) throws RemotingConnectException, RemotingSendRequestException,
    RemotingTimeoutException, InterruptedException, MQBrokerException {
    return this.defaultMQAdminExtImpl.fetchBrokerRuntimeStats(brokerAddr);
}

Get all topic s

Get all topic s according to the cluster

Gets the status of the broker runtime

Here, let's take a detailed look at how to obtain the topic of the cluster

The parameter passed in here is the cluster name clusterName

public TopicList getTopicsByCluster(final String cluster, final long timeoutMillis)
    throws RemotingException, MQClientException, InterruptedException {
    GetTopicsByClusterRequestHeader requestHeader = new GetTopicsByClusterRequestHeader();
    requestHeader.setCluster(cluster);
    RemotingCommand request = RemotingCommand.createRequestCommand(RequestCode.GET_TOPICS_BY_CLUSTER, requestHeader);

    RemotingCommand response = this.remotingClient.invokeSync(null, request, timeoutMillis);
    assert response != null;
    switch (response.getCode()) {
        case ResponseCode.SUCCESS: {
            byte[] body = response.getBody();
            if (body != null) {
                TopicList topicList = TopicList.decode(body, TopicList.class);
                return topicList;
            }
        }
        default:
            break;
    }

    throw new MQClientException(response.getCode(), response.getRemark());
}

Let's go straight to the bottom and take a look at this method

RemotingCommand request = RemotingCommand.createRequestCommand(RequestCode.GET_TOPICS_BY_CLUSTER, requestHeader);

RemotingCommand response = this.remotingClient.invokeSync(null, request, timeoutMillis);

Mainly these two lines. All topic s of the corresponding cluster will be directly obtained in the body of the result obtained after rpc call

Go and see what asynchronous calls are

You can't find it along the rpc. As expected, it's not as good as the global direct search

org.apache.rocketmq.namesrv.processor.DefaultRequestProcessor#getTopicsByCluster

private RemotingCommand getTopicsByCluster(ChannelHandlerContext ctx,
    RemotingCommand request) throws RemotingCommandException {
    final RemotingCommand response = RemotingCommand.createResponseCommand(null);
    final GetTopicsByClusterRequestHeader requestHeader =
        (GetTopicsByClusterRequestHeader) request.decodeCommandCustomHeader(GetTopicsByClusterRequestHeader.class);

    byte[] body = this.namesrvController.getRouteInfoManager().getTopicsByCluster(requestHeader.getCluster());

    response.setBody(body);
    response.setCode(ResponseCode.SUCCESS);
    response.setRemark(null);
    return response;
}

Finally, I found the implementation of the method here. Take a closer look

We can see the RemotingCommand request passed out

I got it here

byte[] body = this.namesrvController.getRouteInfoManager().getTopicsByCluster(requestHeader.getCluster());

Obviously, this is the most important line

Get the cluster name from the request header, and then

adopt

getTopicsByCluster(requestHeader.getCluster())

Method to get Topics

Note the location of this method

Routing information management in namesrvController RouteInfoManager

The naming here is still very standard

According to the theory we have learned, namesrv stores "names", including broker information ip. In short, all related to ip, name, etc

Go to namesrv

namesrv is actually something like eurake zk

Total routing

look down

getTopicsByCluster(requestHeader.getCluster())

This method

public byte[] getTopicsByCluster(String cluster) {
    TopicList topicList = new TopicList();
    try {
        try {
            this.lock.readLock().lockInterruptibly();
            Set<String> brokerNameSet = this.clusterAddrTable.get(cluster);
            for (String brokerName : brokerNameSet) {
                Iterator<Entry<String, List<QueueData>>> topicTableIt =
                    this.topicQueueTable.entrySet().iterator();
                while (topicTableIt.hasNext()) {
                    Entry<String, List<QueueData>> topicEntry = topicTableIt.next();
                    String topic = topicEntry.getKey();
                    List<QueueData> queueDatas = topicEntry.getValue();
                    for (QueueData queueData : queueDatas) {
                        if (brokerName.equals(queueData.getBrokerName())) {
                            topicList.getTopicList().add(topic);
                            break;
                        }
                    }
                }
            }
        } finally {
            this.lock.readLock().unlock();
        }
    } catch (Exception e) {
        log.error("getAllTopicList Exception", e);
    }

    return topicList.encode();

Sure enough, we see that there is no mystery at the bottom, that is, we store all the information in memory~

The first is a cluster address table. The clusterAddrTable stores the mapping of cluster name and broker name

Then there is a topic queue table, which stores the mapping between topic name and queue. It can be seen that the relationship is one to many

If the broker name of the queue is consistent with the broker name obtained from the cluster name

Then the topic corresponding to the queue is the topic corresponding to the cluster name

To sum up:

The cluster name cluster actually has a one to many relationship with broker

private HashMap<String/* clusterName */, Set<String/* brokerName */>> clusterAddrTable;
@Override
public ConsumeStats examineConsumeStats(
    String consumerGroup) throws RemotingException, MQClientException, InterruptedException,
    MQBrokerException {
    return examineConsumeStats(consumerGroup, null);
}

@Override
public ConsumeStats examineConsumeStats(String consumerGroup,
    String topic) throws RemotingException, MQClientException,
    InterruptedException, MQBrokerException {
    return defaultMQAdminExtImpl.examineConsumeStats(consumerGroup, topic);
}

@Override
public ClusterInfo examineBrokerClusterInfo() throws InterruptedException, RemotingConnectException, RemotingTimeoutException,
    RemotingSendRequestException, MQBrokerException {
    return defaultMQAdminExtImpl.examineBrokerClusterInfo();
}

Keep going

Check consumption status (Progress) and broker cluster information

org.apache.rocketmq.common.admin.ConsumeStats

Here's what is the consumption status (Progress)

public class ConsumeStats extends RemotingSerializable {
    private HashMap<MessageQueue, OffsetWrapper> offsetTable = new HashMap<MessageQueue, OffsetWrapper>();
    private double consumeTps = 0;

There is a schedule offsetTable and a consumption tps consumeTps

MessageQueue is the basic information of message queue

private String topic;
private String brokerName;
private int queueId;

org.apache.rocketmq.common.admin.OffsetWrapper

Information of offsetWrapper:

private long brokerOffset;
private long consumerOffset;

private long lastTimestamp;

The progress of the broker, the progress of the consumer, and the timestamp of the last update

@Override
public ClusterInfo examineBrokerClusterInfo() throws InterruptedException, RemotingConnectException, RemotingTimeoutException,
    RemotingSendRequestException, MQBrokerException {
    return defaultMQAdminExtImpl.examineBrokerClusterInfo();
}

@Override
public TopicRouteData examineTopicRouteInfo(
    String topic) throws RemotingException, MQClientException, InterruptedException {
    return defaultMQAdminExtImpl.examineTopicRouteInfo(topic);
}

@Override
public ConsumerConnection examineConsumerConnectionInfo(
    String consumerGroup) throws InterruptedException, MQBrokerException,
    RemotingException, MQClientException {
    return defaultMQAdminExtImpl.examineConsumerConnectionInfo(consumerGroup);
}

Check the broker cluster information, topic routing information, and consumer connection information

Look at the cluster information. What is ClusterInfo

org.apache.rocketmq.common.protocol.body.ClusterInfo

Take a look at the mysterious rocketmq cluster:

public class ClusterInfo extends RemotingSerializable {
    private HashMap<String/* brokerName */, BrokerData> brokerAddrTable;
    private HashMap<String/* clusterName */, Set<String/* brokerName */>> clusterAddrTable;

A table of breaker name brokerName and breaker data BrokerData

A table of cluster name clusterName and circuit breaker name brokerName

In fact, one cluster name corresponds to multiple brokers, and then the brokers correspond to their own data

Topics: Java Hadoop kafka source code RocketMQ