Giter Site home page Giter Site logo

tencent / tubemq Goto Github PK

View Code? Open in Web Editor NEW
2.0K 87.0 397.0 9.85 MB

TubeMQ has been donated to the Apache Software Foundation and renamed to InLong, please visit the new Apache repository: https://github.com/apache/incubator-inlong

Home Page: https://inlong.apache.org/

tubemq's Introduction

tubemq's People

Contributors

0xflotus avatar aloyszhang avatar carylu avatar chenjunjiedada avatar ctide avatar dependabot[bot] avatar dongxuwang avatar fireapp avatar gaurav9822 avatar gosonzhang avatar guangxucheng avatar jennifer88huang-zz avatar junpingdu avatar klboke avatar lamberliu avatar lizhiboo avatar netroby avatar quaff avatar slievrly avatar tisonkun avatar waterlx avatar yiheng avatar ykgarfield avatar zehuaiwang avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

tubemq's Issues

Improvement the exception type of MasterConfig throws

Motivation
MasterConfig load configs of master.ini, parse and check.If has problems, almost of them throws NullPointerException or IllegalArgumentException.But in some cases, throw NullPointerException probably inappropriate.For example:

  • code snippet 1:
try {
	this.hostName = masterConf.get("hostName").trim();
	AddressUtils.validLocalIp(this.hostName);
} catch (Throwable e) {
	throw new NullPointerException(new StringBuilder(256)
			.append("Illegal hostName value in ").append(SECT_TOKEN_MASTER)
			.append(" section!").toString());
}
  • code snippet 2:
if (!this.startConsumeAuthenticate && this.startConsumeAuthorize) {
	throw new NullPointerException(
			"startConsumeAuthenticate must set true if startConsumeAuthorize is true!");
}

IllegalArgumentException may more reasonable or use cusutom exception(for example: ConfigException).

In addition, the following exception message not clear enough:

String tmpAuthToken = masterConf.get("confModAuthToken").trim();
if (tmpAuthToken.length() > TServerConstants.CFG_MODAUTHTOKEN_MAX_LENGTH) {
	throw new IllegalArgumentException(
			"Invalid value: confModAuthToken's value > " + TServerConstants.CFG_MODAUTHTOKEN_MAX_LENGTH);
}

Here is the string length illegal, the more detail exception message should be:

"Invalid value: the length of confModAuthToken's value > " + TServerConstants.CFG_MODAUTHTOKEN_MAX_LENGTH);

(optional) Design

(optional) Example snippet

Useless `main` method in subclass of Action

I found some main method just sleep 100000000ms in a new thread in some subClass of Action,

public static void main(String[] args) {
        new Thread() {
            @Override
            public void run() {
                try {
                    Thread.sleep(100000000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }.start();
    }

It seems useless. and I think wo can remove these code. What do think about it ?
@gosonzhang

broker的HA方案是什么,有规划吗?

从文档上看数据是没有多副本策略,如果一台broker宕机了,是不是这台机器的未消费的消息都丢失了?数据的丢失是mq的一个核心指标,如果没有数据不丢失的保证,生产环境使用还是有风险的

redundancy encoding when loading meta-data from BDB-JE

There are some redundancy encoding when loading meta-data from BDB-JE like this :

if (logger.isDebugEnabled()) {
                StringBuilder sBuilder = new StringBuilder(512);
                logger.debug("[Load topic config] load broker topic record start:");
                for (BdbTopicConfEntity bdbEntity : cursor) {
                    if (bdbEntity == null) {
                        logger.warn("[BDB Error] Found Null data while loading from topicConfIndex!");
                        continue;
                    }
                    ConcurrentHashMap<String/* topicName */, BdbTopicConfEntity> brokerTopicMap =
                            brokerIdTopicEntityMap.get(bdbEntity.getBrokerId());
                    if (brokerTopicMap == null) {
                        brokerTopicMap =
                                new ConcurrentHashMap<String, BdbTopicConfEntity>();
                        brokerIdTopicEntityMap.put(bdbEntity.getBrokerId(), brokerTopicMap);
                    }
                    brokerTopicMap.put(bdbEntity.getTopicName(), bdbEntity);
                    count++;
                    logger.debug(bdbEntity.toJsonString(sBuilder).toString());
                    sBuilder.delete(0, sBuilder.length());
                }
                logger.debug("[Load topic config] load broker topic record finished!");
            } else {
                for (BdbTopicConfEntity bdbEntity : cursor) {
                    if (bdbEntity == null) {
                        logger.warn("[BDB Error] Found Null data while loading from topicConfIndex!");
                        continue;
                    }
                    ConcurrentHashMap<String/* topicName */, BdbTopicConfEntity> brokerTopicMap =
                            brokerIdTopicEntityMap.get(bdbEntity.getBrokerId());
                    if (brokerTopicMap == null) {
                        brokerTopicMap =
                                new ConcurrentHashMap<String, BdbTopicConfEntity>();
                        brokerIdTopicEntityMap.put(bdbEntity.getBrokerId(), brokerTopicMap);
                    }
                    brokerTopicMap.put(bdbEntity.getTopicName(), bdbEntity);
                    count++;
                }
            }

I think we can make some condense about this.
@gosonzhang

How does TubeMQ support the use of the Java 7 environment?

Considering that the business environment using TubeMQ is java 7 and does not allow upgrades, it's a better support method to adjust the je version to a lower version than 7.3.7, such as 6.1.5.


考虑到使用TubeMQ的商业环境是Java 7,并且不允许升级情况,如果业务需要使用TubeMQ,将je版本调整为低于7.3.7(例如6.1.5)的版本是一种比较好的支持方法。

Remove redundant exception information log print and amend LOG level bug

Currently ,there are some redundant exception information print like :

catch (Exception e) {
            e.printStackTrace();
            logger.info("[loadTopicConfUnits error] ", e);
            throw e;
        }

And, some LOG level error like :

catch (Throwable t) {
            logger.info("Dispatcher start failed!", t);
            throw new ServletException(t);
        }

[question] String concatenation style

Notice there are lots of string concatenations following style

throw new RuntimeException(new StringBuilder(512)
                    .append("[Data Repair] store path is not existed, path is ")
                    .append(storePath).toString());

which can be transferred to

throw new RuntimeException("[Data Repair] store path is not existed, path is " + storePath);

I don't know the reason that we adopt the first style but it seems counter-intuitive.

CC @gosonzhang

unseemly log print

I found some code abount log printing like :

logger.debug(strBuffer
      .append("[Partition occupied], curr consumerId: ")
      .append(consumerId).append(", returned message : ")
      .append(responseB2C.getErrMsg()).toString());

I think it's not a good way to ouput log because code like responseB2C.getErrMsg() will execute first even logger level is above debug(INFO,WARN etc.)

tubemq-server模块和tubemq-example模块下缺少打印到控制台的日志配置

Motivation
系统日志框架使用的log4j,tubemq-server模块和tubemq-example模块下都没有log4j配置,开发调试时没有打印到控制台的日志非常不方便。当然这个不影响打包后的程序日志

(optional) Design
在tubemq-server模块和tubemq-example模块下新增log4j.properties的配置文件,配置日志打印到控制台
(optional) Example snippet
如:

log4j.rootLogger = info,stdout
        
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n

It's need to install 2.5.0 version of protoc, otherwise mvn package will fail

According to docs\tubemq_user_guide.md, if direct to execute mvn clean package -Dmaven.test.skip, it will report following error:

Failed to execute goal com.github.igor-petruk.protobuf:protobuf-maven-plugin:0.6.3:run (default) on project tubemq-core: Cannot execute 'protoc'

So we need first to install protobuf, version is 2.5.0, the project's protobuf-java version is 2.5.0, if installed version is not match 2.5.0, maybe be occur following error:

Protobuf installation version does not match Protobuf library version

The document is better to write this.

consumer接收消息时导致CPU100%

系统:Windows10
运行环境:jdk8
开发工具:IDEA2019.1.3X64
初步定位到FetchTaskWorker 空转导致CPU 100% ,在Producer发送消息时,consumer接收消息后必现

   private class FetchTaskWorker implements Runnable {
        @Override
        public void run() {
            StringBuilder sBuilder = new StringBuilder(256);
            final Long curThreadId = Thread.currentThread().getId();
            fetchWorkerStatusMap.put(curThreadId, 0);
            while (!isShutdown()) {
                PartitionSelectResult partSelectResult = null;
                fetchWorkerStatusMap.put(curThreadId, 0);
                try {
                    if (isShutdown()) {
                        break;
                    }
                    fetchWorkerStatusMap.put(curThreadId, 1);
                    MessageFetchManager.this.pushConsumer.allowConsumeWait();
                    partSelectResult = MessageFetchManager.this.pushConsumer.getBaseConsumer().pushSelectPartition();
                    if (partSelectResult == null) {
                        continue;
                    }
                    Partition partition = partSelectResult.getPartition();
                    long usedToken = partSelectResult.getUsedToken();
                    boolean isLastConsumed = partSelectResult.isLastPackConsumed();
                    if (isShutdown()) {
                        MessageFetchManager.this.pushConsumer
                                .getBaseConsumer()
                                .pushReqReleasePartiton(partition.getPartitionKey(), usedToken, isLastConsumed);
                        partSelectResult = null;
                        break;
                    }
                    if (MessageFetchManager.this.pushConsumer.isConsumePaused()) {
                        boolean result = partSelectResult.isLastPackConsumed();
                        if (result) {
                            result =
                                    MessageFetchManager.this.pushConsumer
                                            .getBaseConsumer().flushLastRequest(partition);
                        }
                        MessageFetchManager.this.pushConsumer
                                .getBaseConsumer().pushReqReleasePartiton(partition.getPartitionKey(),
                                usedToken, result);
                        partSelectResult = null;
                        continue;
                    }
                } catch (Throwable e) {
                    if (partSelectResult != null) {
                        MessageFetchManager.this.pushConsumer
                                .getBaseConsumer()
                                .pushReqReleasePartiton(partSelectResult.getPartition().getPartitionKey(),
                                        partSelectResult.getUsedToken(), false);
                    }
                    sBuilder.delete(0, sBuilder.length());
                    logger.warn(sBuilder.append("Thread {} has been interrupted 3.")
                            .append(Thread.currentThread().getName()).toString());
                    sBuilder.delete(0, sBuilder.length());
                }
                fetchWorkerStatusMap.put(curThreadId, 2);
                MessageFetchManager.this.pushConsumer.processRequest(partSelectResult, sBuilder);
            }
            fetchWorkerStatusMap.remove(curThreadId);
        }
    }

image

Downgrade minimum jdk version to jdk7

ref #73

After an investigation we notice that je 7.3.7 doesn't require jdk8 so that for being compatible with jdk7 I propose

  1. configure maven-compiler-plugin in tubemq-server using jdk7
  2. downgrade travis environment to use openjdk7
  3. correspondingly update documentation

Align string connection processing method

Handling partially inconsistent string concatenation processing codes: Most of the string concatenation processing in TubeMQ uses the StringBuilder.append() method to concatenate strings, avoiding the use of the "+" operator, but some code uses both StringBuilder.append() Use the "+" operator,for example in BaseMessageConsumer.java :

                    if (!consumeSubInfo.isSubscribedTopicContain(partitionKeyItems[1].trim())) {
                        throw new TubeClientException(new StringBuilder(256)
                                .append("Parameter error: not included in subcribed topic list: "
                                        + "partOffsetMap's key is ")
                                .append(entry.getKey()).append(", subscribed topics are ")
                                .append(consumeSubInfo.getSubscribedTopics().toString()).toString());
                    }

RPC problem

I found some confusing code in NettyClient#call.

if (channel1 == null) {
            logger.error(new StringBuilder(256)
                    .append(this.addressInfo.getHostPortStr())
                    .append("'s channel is null").toString());
        } else {
            getChannel().write(pack);
        }
        if (callback == null) {
            try {
                return future.get(timeout, timeUnit);
            } catch (TimeoutException e) {
                requests.remove(request.getSerialNo());
                throw e;
            }
        } else {
            timeouts.put(request.getSerialNo(),
                    timer.newTimeout(new TimeoutTask(request.getSerialNo()), timeout, timeUnit));
        }

when channel is null, it'll continue run the following code. It seems meaningless since
client can't send request when channel is null. I think maybe throw a RuntimeExcetion indicate channel is null is a better way.

Another problem here, currently, when send message asynchronously, it will build a Timeout after write data to channel. Since build a timeout may cause RuntimeException, it will trigger callback twice in this situaitons.

源码中找不到类

com.tencent.tubemq.corebase.protobuf.generated.ClientBroker这个类找不到,麻烦解决下

Replace sun.misc.BASE64Encoder with java.util.Base64

Currently, we use internal class sun.misc.BASE64Encoder inside com.tencent.tubemq.server.broker.BrokerServiceServer. This class cannot be accessed anymore since Java 11. Although we might not have a upgrade plan in the near future, we can safely do the replacement following the existing solution in JDK community.

[doc] maybe quickstart need more message

Thank you for your work about TubeMQ and open source,It is awsome

I have try to run
sh master.sh start

But i just got some error:

Unable to find resource 'macro.vm'

More detail

2019-10-02 04:12:59,555 - ResourceManager : unable to find resource 'macro.vm' in any resource loader.
2019-10-02 04:12:59,555 - Velocimacro : Velocimacro : Error using VM library : macro.vm
org.apache.velocity.exception.ResourceNotFoundException: Unable to find resource 'macro.vm'
        at org.apache.velocity.runtime.resource.ResourceManagerImpl.loadResource(ResourceManagerImpl.java:474)
        at org.apache.velocity.runtime.resource.ResourceManagerImpl.getResource(ResourceManagerImpl.java:352)
        at org.apache.velocity.runtime.RuntimeInstance.getTemplate(RuntimeInstance.java:1533)
        at org.apache.velocity.runtime.RuntimeInstance.getTemplate(RuntimeInstance.java:1514)
        at org.apache.velocity.runtime.VelocimacroFactory.initVelocimacro(VelocimacroFactory.java:202)
        at org.apache.velocity.runtime.RuntimeInstance.init(RuntimeInstance.java:274)
        at org.apache.velocity.runtime.RuntimeInstance.init(RuntimeInstance.java:678)
        at org.apache.velocity.app.VelocityEngine.init(VelocityEngine.java:105)
        at com.tencent.tubemq.server.master.web.simplemvc.VelocityTemplateEngine.init(VelocityTemplateEngine.java:50)
        at com.tencent.tubemq.server.master.web.simplemvc.RequestDispatcher.init(RequestDispatcher.java:70)
        at com.tencent.tubemq.server.master.web.simplemvc.WebFilter.init(WebFilter.java:84)
        at org.mortbay.jetty.servlet.FilterHolder.doStart(FilterHolder.java:97)
        at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:50)
        at org.mortbay.jetty.servlet.ServletHandler.initialize(ServletHandler.java:713)
        at org.mortbay.jetty.servlet.Context.startContext(Context.java:140)
        at org.mortbay.jetty.handler.ContextHandler.doStart(ContextHandler.java:518)
        at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:50)
        at org.mortbay.jetty.handler.HandlerWrapper.doStart(HandlerWrapper.java:130)
        at org.mortbay.jetty.Server.doStart(Server.java:224)
        at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:50)
        at com.tencent.tubemq.server.master.web.WebServer.start(WebServer.java:79)
        at com.tencent.tubemq.server.master.TMaster.<init>(TMaster.java:217)
        at com.tencent.tubemq.server.tools.MasterStartup.main(MasterStartup.java:32)

It would be great if quickstart document could be improved

Tubemq client throws an exception when stopping the consumer.

java.lang.InterruptedException: sleep Interrupted
at java.lang.Thread.sleep(Native Method)
at com.tencent.tubemq.corebase.utils.ThreadUtils.sleep(ThreadUtils.java:128)
at com.tencent.tubemq.client.consumer.RmtDataCache.pushSelect(RmtDataCache.java:241)
at com.tencent.tubemq.client.consumer.BaseMessageConsumer.pushSelectPartition(BaseMessageConsumer.java:713)
at com.tencent.tubemq.client.consumer.MessageFetchManager$FetchTaskWorker.run(MessageFetchManager.java:180)
at java.lang.Thread.run(Thread.java:745)

Webui page title display error

The topic list、topic detail and other multiple pages title display error, as shown in the following figure:

TIM截图20190917165505

According to source code, tow places not set page title:

  • layout/default.vmlayout/tubeweb.vm only judge two pages:
#if($page == "brokerList")
    #set($title="Broker列表")
#elseif($page == "brokerDetail")
    #set($title="Broker详情")
#end
  • execute() method of some Action implementation classes not set page param, like TopicDetail#execute():
public void execute(RequestContext context) {
    // now, this method is empty, no following line code
    context.put("page", "topicDetail");
}

tubme master startup infinite blocked if the machine node IP changed

Problem description
When I work in wired network, I config the hostName of master.ini to the wired network IP, then I switch network to wireless network, the IP is changed, then I reconfig the hostName to wireless network IP , start tubemq master, It will infinite blocked, the log only output util following line:

(main) [INFO - com.tencent.tubemq.server.master.bdbstore.DefaultBdbStoreService.initEnvConfig(DefaultBdbStoreService.java:996)] ADD HELP HOST

// It's will blocked, no more output

(optional) Reproducer snippet
Analysis and debug the source code, find that, if machine ip is changed, RepUtils.ExceptionAwareCountDownLatch#awaitOrException() will bloked:

public boolean awaitOrException(long timeout, TimeUnit unit)
	throws InterruptedException,
		   DatabaseException {
        // blocked
	boolean done = super.await(timeout, unit);
	...
}

Final, track the source code to RepNode#run():

public void run() {
	...
	if (nameIdPair.hasNullId() || !nodeType.isElectable()) {
		queryGroupForMembership();
	} else {
		// here blocked
		elections.initiateElection(group, electionQuorumPolicy);
		...
	}
	...
}

Next Elections#initiateElection():

public synchronized void initiateElection(RepGroupImpl newGroup, QuorumPolicy quorumPolicy, int maxRetries) {
	RetryPredicate retryPredicate =
            new RetryPredicate(repNode, maxRetries, countDownLatch);
        electionThread = new ElectionThread(quorumPolicy, retryPredicate,
                                            envImpl,
                                            (envImpl == null) ? null :
                                            envImpl.getName());
	electionThread.start();
	try {
		// here blocked
		/* Wait until we hear of some "new" election result */
		countDownLatch.await();
		...
	} 
}

Next Elections.ElectionThread#run():

public void run() {
    ...
	winningProposal =
                    proposer.issueProposal(quorumPolicy, retryPredicate);
	...
}

Next Proposer#issueProposal():

public WinningProposal issueProposal(QuorumPolicy quorumPolicy, RetryPredicate retryPredicate) {
	while (retryPredicate.retry()) {
		try {
			final Proposal proposal = nextProposal();
			// Keep retrying
			final Phase1Result result1 = phase1(quorumPolicy, proposal);
			if (result1 == null) {
				continue;
			}
			...
		}
	}
}

Note than the phase1(quorumPolicy, proposal) is keep retrying, because this method always return null.

Next Proposer#phase1():

private Phase1Result phase1(QuorumPolicy quorumPolicy, Proposal proposal) {
	...
	Phase1Result result = tallyPhase1Results(proposal, compService);
	// always false
	if (haveQuorum(quorumPolicy, result.promisories.size())) {
		return result;
	}
	phase1NoQuorum.increment();
	
	// always return null
	return null;
}

Next Proposer#tallyPhase1Results():

private Phase1Result tallyPhase1Results(Proposal currentProposal, final FutureTrackingCompService<MessageExchange> compService) {
	...
	new Utils.WithFutureExceptionHandler<MessageExchange>
                (compService, 2 * elections.getProtocol().getReadTimeout(),
                 TimeUnit.MILLISECONDS, logger, elections.getRepImpl(), null) {
	...
}

Focus on MessageExchange, this is a task:

public void run() {
	messageExchange();
}

Next TextProtocol.MessageExchange#messageExchange():

public void messageExchange() {

	DataChannel dataChannel = null;
	BufferedReader in = null;
	PrintWriter out = null;
	try {
		dataChannel =
                       // when in wireless network use  the IP of wired network, the connection will fail
                      // will throw java.net.ConnectException: Connection refused: no further information
			channelFactory.connect(
				target,
				new ConnectOptions().
				setTcpNoDelay(true).
				setOpenTimeout(openTimeoutMs).
				setReadTimeout(readTimeoutMs).
				setBlocking(true).
				setReuseAddr(true));
		...
	} catch (java.net.SocketTimeoutException e){
		this.exception = e;
	} catch (SocketException e) {
		this.exception = e;
	} catch (IOException e) {
		this.exception = e;
	} catch (TextProtocol.InvalidMessageException ime) {
		...
		this.exception = ime;
	} catch (ServiceConnectFailedException e) {
		this.exception = e;
	} catch (Exception e) {
		...
	} finally {
		Utils.cleanup(logger, repImpl, formatter, dataChannel, in, out);
	}
}

Here connection fail, throw java.net.ConnectException: Connection refused: no further information, It catch exception, no any error messages.

Although I reconfig the hostName to wireless network IP, but the target still use the wired network IP, I guess it may use the meta of bdbEnvHome.

(optional) Suggestions for an imporvement
We should introduce some mechanisms for inspection.In addition I feel the method of
sleepycat(Berkeley DB) lib seems unreasonable.

TubeMQ consumers configure the wrong standby masterIP and set it to the first,consumers will throw exceptions.

TubeMQ consumers configure the wrong standby masterIP and set it to the first,consumers will throw exceptions. And then,consumers re-register successfully after 5min.

The reason for this problem is because consumers don‘t poll connection list if the connection times out.

[ERROR] [BaseMessageConsumer] Register to master failed.
java.util.concurrent.TimeoutException
at com.tencent.tubemq.corerpc.client.CallFuture.get(CallFuture.java:139)
at com.tencent.tubemq.corerpc.netty.NettyClient.call(NettyClient.java:157)
at com.tencent.tubemq.corerpc.RpcServiceFailoverInvoker.callMethod(RpcServiceFailoverInvoker.java:69)
at com.tencent.tubemq.corerpc.AbstractServiceInvoker.invoke(AbstractServiceInvoker.java:57)
at com.sun.proxy.$Proxy0.consumerRegisterC2M(Unknown Source)
at com.tencent.tubemq.client.consumer.BaseMessageConsumer.startMasterAndBrokerThreads(BaseMessageConsumer.java:563)
at com.tencent.tubemq.client.consumer.BaseMessageConsumer.completeSubscribe(BaseMessageConsumer.java:306)
at com.tencent.tubemq.client.consumer.SimplePushMessageConsumer.completeSubscribe(SimplePushMessageConsumer.java:76)

Improvement `BdbGroupAdmin` class

BdbGroupAdmin is used to remove node in replication group.
Currently, BdbGroupAdmin does't handle the exception and missing the necessary message about the remove process. I think we should:

  1. print the node information before and after remove node
  2. catch and handler the exception separately, then print some readable information

What do you think @gosonzhang ?

Standard commit format

Currently commits of TubeMQ don't have a standard format. A standard format helps search/filter commits in log, understand the purpose of a commit or a pull request and so on.

Here are several alternatives coming from other project.

1). Study from Spark & Flink, [TUBEMQ-<issue-number>][<component>] .... Concerns here would be what issue tracker we use(for now it seems we just use GitHub issues) and what components we split into.
2) Study from AngularJS. It is well-known and due to the content is too long to inline I just link to the guidelines page.
3) Study from Pravega, Issue <issue-no>: .... Details are here.

Any insight would be helpful :-)

qryPriorityId value is inconsistent with the definition relationship

In the flow control rule setting, the interface document prompts qryPriorityId to be a composite structure, the type is A0B, and the default value of the field is 301. However, if the url does not carry this field, the default value of the interface is 0.

{"result":true,"errCode":0,"errMsg":"OK","data":[{"type":"BdbGroupFlowCtrlEntity","groupName":"test1","statusId":1,"ssdTranslateId":-2,"ruleCnt":1,"needSSDProc":true,"serialId":1568964894444,"qryPriorityId":0,"flowCtrlInfo":[{"type":3,"rule":[{"normFreqInMs":0,"filterFreqInMs":1000,"minDataFilterFreqInMs":5000}]}], "attributes":"qryPriorityId=0", "createUser":"lenanli","createDate":"20190920153454"}],"count":1}
- - - - - - -

流控规则设置里,接口文档里提示qryPriorityId该字段值为一个复合结构,类型为A0B,字段缺省值为301,但是url里如果真的没携带这个字段,接口显示默认值是0

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.