package org.zbus.client; import java.io.IOException; import java.util.HashMap; import java.util.Map; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import org.zbus.common.logging.Logger; import org.zbus.common.logging.LoggerFactory; import org.zbus.common.protocol.MessageMode; import org.zbus.common.protocol.Proto; import org.zbus.common.remoting.Message; import org.zbus.common.remoting.RemotingClient; import org.zbus.common.remoting.callback.MessageCallback; public class Consumer{ private static final Logger log = LoggerFactory.getLogger(Consumer.class); private final Broker broker; private RemotingClient client; //消费者拥有一个物理链接 private final String mq; //队列唯一性标识 private String accessToken = ""; //访问控制码 private String registerToken = ""; //注册认证码 private final int mode; //为发布订阅者的主题,当Consumer的模式为发布订阅时候起作用 private String topic = null; public Consumer(Broker broker, String mq, MessageMode... mode){ this.broker = broker; this.mq = mq; if(mode.length == 0){ this.mode = MessageMode.intValue(MessageMode.MQ); } else { this.mode = MessageMode.intValue(mode); } } public Consumer(MqConfig config){ this.broker = config.getBroker(); this.mq = config.getMq(); this.accessToken = config.getAccessToken(); this.registerToken = config.getRegisterToken(); this.mode = config.getMode(); this.topic = config.getTopic(); } private ClientHint myClientHint(){ ClientHint hint = new ClientHint(); hint.setMq(this.mq); return hint; } public Message recv(int timeout) throws IOException{ if(this.client == null){ this.client = broker.getClient(myClientHint()); } Message req = new Message(); req.setCommand(Proto.Consume); req.setMq(mq); req.setToken(accessToken); if(MessageMode.isEnabled(this.mode, MessageMode.PubSub)){ if(this.topic != null){ req.setTopic(this.topic); } } Message res = null; try{ res = client.invokeSync(req, timeout); if(res != null && res.isStatus404()){ if(!this.createMQ()){ throw new IllegalStateException("register error"); } return recv(timeout); } } catch(IOException e){ log.error(e.getMessage(), e); try{ broker.closeClient(client); client = broker.getClient(myClientHint()); } catch(IOException ex){ log.error(e.getMessage(), e); } } return res; } protected ScheduledExecutorService executorService = null; private MessageCallback callback; public void onMessage(MessageCallback cb) throws IOException{ this.callback = cb; if(executorService == null){ executorService = Executors.newSingleThreadScheduledExecutor(); } else { return; } executorService.submit(new Runnable() { @Override public void run() { for(;;){ try { Message msg = recv(10000); if(msg == null){ continue; } callback.onMessage(msg, client.getSession()); } catch (IOException e) { // } } } }); } public void reply(Message msg) throws IOException{ if(msg.getStatus() != null){ msg.setReplyCode(msg.getStatus()); } msg.setCommand(Proto.Produce); msg.setAck(false); client.getSession().write(msg); } public boolean createMQ() throws IOException{ Map<String, String> params = new HashMap<String, String>(); params.put("mqName", mq); params.put("accessToken", accessToken); params.put("mqMode", "" + this.mode); Message req = Proto.buildSubCommandMessage(Proto.Admin, Proto.AdminCreateMQ, params); req.setToken(this.registerToken); Message res = client.invokeSync(req); if(res == null) return false; return res.isStatus200(); } public String getAccessToken() { return accessToken; } public void setAccessToken(String accessToken) { this.accessToken = accessToken; } public String getRegisterToken() { return registerToken; } public void setRegisterToken(String registerToken) { this.registerToken = registerToken; } public String getTopic() { return topic; } public void setTopic(String topic) { if(!MessageMode.isEnabled(this.mode, MessageMode.PubSub)){ throw new IllegalStateException("topic support for none-PubSub mode"); } this.topic = topic; } }