- 依据业务需求,需要有一个消息生产将消息按照key配置规则发送给指定的消息消费者消费,并且消费者客户端把自身的消息作为消息提供者发送给另一个消息消费者。三个服务,第一服务负责把数据发送给多个客户端,第二服务负责消费第一个服务发送的数据,并把自己采集的数据发送给第三个客户端,第三个服务负责把客户端发送回来的数据进行处理。
服务一和服务二之间使用消息分区的方式,服务二和服务三采用消息分组的方式,消息分区保证上线以后A消费者不会消费B消费者的数据。消息分组可以保证在一个服务三处理不过数据的情况下部署多个服务。 - 引入rabbitmq依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-stream-rabbit</artifactId>
<version>2.1.0.RELEASE</version>
</dependency>
服务一消息生产者配置
rabbitmq:
port: 5672
username: guest
password: guest
host: ip
virtual-host: /
cloud:
stream:
bindings:
receiptclient:
destination: receipt-analysis
#application/octet-stream
content-type: text/plain
group: consum-receipt
import org.springframework.cloud.stream.annotation.Output;
import org.springframework.messaging.MessageChannel;
import org.springframework.stereotype.Service;
@Service
public interface ISendMessage {
String ccpOutput = "senddeclare";
@Output(ISendMessage.ccpOutput)
MessageChannel sendData();
}
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.stream.annotation.EnableBinding;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.stereotype.Component;
@Component
@EnableBinding(ISendMessage.class)
public class MessageSender {
@Autowired
ISendMessage sendMessageClient;
public void sendMsg(String context, String fileName, String clientId)
throws Exception {
sendMessageClient.sendData()
.send(MessageBuilder.withPayload(context)
.setHeader("fileName", fileName)
.setHeader("clientId", clientId).build());
}
}
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.stream.annotation.EnableBinding;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.stereotype.Component;
@Component
@EnableBinding(ISendMessage.class)
public class MessageSender {
@Autowired
ISendMessage sendMessageClient;
public void sendMsg(String context, String fileName, String clientId)
throws Exception {
sendMessageClient.sendData()
.send(MessageBuilder.withPayload(context)
.setHeader("fileName", fileName)
.setHeader("clientId", clientId).build());
}
}
服务二 即是消息消费者也是消息生产者
rabbitmq:
port: 5672
username: declare
password: declare
host: ip
virtual-host: /
# application/octet-stream
cloud:
stream:
bindings:
sendreceipt:
destination: receipt-analysis
content-type: text/plain
declareclient:
consumer:
partitioned: true
destination: declarecenter
content-type: text/plain
group: consumGroup
instance-count: 1000
instance-index: 28
消费消息类
import org.springframework.cloud.stream.annotation.Input;
import org.springframework.cloud.stream.annotation.Output;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.SubscribableChannel;
import org.springframework.stereotype.Service;
@Service
public interface IMessageClient {
String ccpInput = "declareclient";
String ccpOutput = "sendreceipt";
@Output(IMessageClient.ccpOutput)
MessageChannel sendMessage();
@Input(IMessageClient.ccpInput)
SubscribableChannel receiveMessage();
}
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.stream.annotation.EnableBinding;
import org.springframework.cloud.stream.annotation.StreamListener;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.messaging.handler.annotation.Payload;
import lombok.extern.log4j.Log4j2;
@Log4j2
@ComponentScan("")
@EnableBinding(IMessageClient.class)
class StreamListen {
@Autowired
private ProcessDecDataSend processDecDataSend;
@StreamListener(IMessageClient.ccpInput)
public void stream(@Payload byte[] data, @Header String fileName,
@Header String clientId, @Header String businessType,
@Header int partitionKey) {
if (data.length > 0 && StringUtils.isNotEmpty(fileName)
&& StringUtils.isNotEmpty(clientId)) {
DecParameter decParameter = new DecParameter();
decParameter.setBusinessType(businessType);
decParameter.setClientId(clientId);
decParameter.setFileName(fileName);
decParameter.setPartitionKey(partitionKey);
InputStream ips = new ByteArrayInputStream(data);
log.info("Rabbitmq receives new messages:"
+ decParameter.toString());
processDecDataSend.sendDecData(ips, decParameter);
}
}
}
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.stream.annotation.EnableBinding;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.stereotype.Component;
import lombok.extern.log4j.Log4j2;
import java.io.File;
@Log4j2
@EnableBinding(IMessageClient.class)
@ComponentScan("")
public class MessageSender {
@Autowired
private TaskParameter taskParameter;
@Autowired
private IMessageClient sendMessageClient;
@Autowired
private BackupLocalFiles backupLocalFiles;
public void sendMsg(byte[] bytes, String fileName, String businessType,
String corpCode) throws Exception {
sendMessageClient.sendMessage().send(MessageBuilder.withPayload(bytes)
.setHeader("fileName", fileName).setHeader("corpCode", corpCode)
.setHeader("businessType", businessType).build());
String filePath = "C:/ReceiptFile/" + BackupLocalFiles.dateFormateStr() + "/" + businessType + "/" + fileName;
if(hasFile()){
filePath = "D:/ReceiptFile/" + BackupLocalFiles.dateFormateStr() + "/" + businessType + "/" + fileName;
}
backupLocalFiles.backFile(bytes, filePath);
}
private static boolean hasFile(){
File file=new File("D:/");
return file.isDirectory();
}
}
服务三 分组方式消费消息
rabbitmq:
port: 5672
username: guest
password: guest
host: ip
virtual-host: /
cloud:
stream:
bindings:
receiptclient:
destination: receipt-analysis
#application/octet-stream
content-type: text/plain
group: consum-receipt
import org.springframework.cloud.stream.annotation.Input;
import org.springframework.messaging.SubscribableChannel;
public interface ISendMessageClient {
String ccpInput = "receiptclient";
@Input(ISendMessageClient.ccpInput)
SubscribableChannel input();
}
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.stream.annotation.EnableBinding;
import org.springframework.cloud.stream.annotation.StreamListener;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.stereotype.Component;
@Component
@EnableBinding(ISendMessageClient.class)
class StreamListen {
@Autowired
private ReceiptServer receiptServer;
@Autowired
private FailMessageLogMapper failMessageLogMapper;
@Autowired
private XmlTool xmlTool;
private Logger logger = LoggerFactory.getLogger(StreamListen.class);
@StreamListener(ISendMessageClient.ccpInput)
public void stream(@Payload byte[] data, @Header String fileName,
@Header String businessType, @Header String corpCode) {
String dateString = xmlTool.createDateString();
String filePath = "/data/receipt/" + corpCode + "/" + dateString + "/"
+ businessType + "/" + fileName;
try {
String xmlContext = fileToString(data);
if (businessType.equals("inv")||businessType.equals("sas")
||businessType.equals("npts"))
xmlContext = null;
saveFailMessageLog(businessType, fileName, filePath, corpCode,
xmlContext);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
receiptServer.startDeclare(data, fileName, businessType, corpCode);
}
public void saveFailMessageLog(String businessType, String fileName,
String filePath, String corpCode, String fileContent) {
FailMessageLogExample failMessageLogEx = new FailMessageLogExample();
failMessageLogEx.createCriteria().andFileNameEqualTo(fileName);
List<FailMessageLog> logs = failMessageLogMapper
.selectByExample(failMessageLogEx);
if (logs.size() == 0) {
FailMessageLog failMessageLog = new FailMessageLog();
failMessageLog.setDataType("back");
failMessageLog.setBusinessType(businessType);
failMessageLog.setFileName(fileName);
failMessageLog.setFilePath(filePath);
failMessageLog.setCorpCode(corpCode);
failMessageLog.setFileContent(fileContent);
failMessageLogMapper.insertSelective(failMessageLog);
}
}
private String fileToString(byte[] fileByte) throws IOException {
InputStream is = new ByteArrayInputStream(fileByte);
String line = null;
StringBuffer sb = new StringBuffer();
InputStreamReader isr = new InputStreamReader(is, "UTF-8");
// 使用 BufferedReader 进行读取
BufferedReader bufferedReader = new BufferedReader(isr);
while (null != (line = bufferedReader.readLine())) {
// logger.info(line);
sb.append(line);
}
bufferedReader.close();
isr.close();
is.close();
return sb.toString();
}
}