在企业中,分布式的消息队列需要实现的问题:

  1、不同的业务系统分别处理同一个消息(订阅发布),同一个业务系统负载处理同一类消息(队列模式)

  2、消息的一致性问题,在互联网公司中一般不要求强一致性,一般要求高性能,所以只需要每次轮询消息日志或消息存储文件,重新发送未一致的问题。(公司中出现过存储文件在集群数据库上的情况,然后由于读写分离,出现了消息重复发送的故障)

  3、消息重复发送问题也称为消息的幂等性:解决重复问题可以让消费者在接受到消息后查看日志或文件是否消息已经被修改状态或删除。(公司的故障中,由于读写分离,所以消息状态还没来得及被更改,重复性检测就已经检测完了数据库中文件,导致的重复性问题仍然没被解决)

  4、基于消息机制建立服务总线,主业务在接受消息后通知服务总线,服务总线通知旁支服务,而不是旁支服务长时间询问主服务。

一、jms:java message service java消息服务,他不是一种协议,而是一个api,用来服务于消息中间件的api;

二、消息中间件:为了异步可靠的在两个系统结构之间(泛指两个,可以多个)进行消息传输,令项目服务化,解耦性强。例如:我们有个登录系统,如果用户登录成功返回给用户成功提示之前会调用积分增加服务,日志服务等,这样一旦其中一个服务失效可能就会延迟用户获得登陆成功提示的时间,降低用户体验,所以我们可以异步将用户登录信息传输到附加服务中,只返回用户关心的登录信息。

三、常用的消息中间件:ActiveMQ、RabbitMQ、Kafka

四、以下为active利用jdk自带的jms实现,结合spring的请点击:

结构如下:

  pom.xml文件:

<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <groupId>com.zxc.jms</groupId>
<artifactId>jms</artifactId>
<version>1.0-SNAPSHOT</version> <dependencies>
<dependency>
<groupId>javax.jms</groupId>
<artifactId>javax.jms-api</artifactId>
<version>2.0.1</version>
</dependency> <dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-core</artifactId>
<version>5.7.0</version>
</dependency> <!-- https://mvnrepository.com/artifact/log4j/log4j -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.2</version>
</dependency> <!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-log4j12 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.2</version>
</dependency> </dependencies> </project>

log4j.properties:(用的是slf4j日志)如果是idea注意一定要放在resource下,如果用的是eclipse要放在src下

### 设置###
log4j.rootLogger = debug,stdout,D,E ### 输出信息到控制抬 ###
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 ### 输出DEBUG 级别以上的日志到=E://logs/error.log ###
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
log4j.appender.D.File = D://logs/log.log
log4j.appender.D.Append = true
log4j.appender.D.Threshold = DEBUG
log4j.appender.D.layout = org.apache.log4j.PatternLayout
log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n ### 输出ERROR 级别以上的日志到=E://logs/error.log ###
log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
log4j.appender.E.File =D://logs/error.log
log4j.appender.E.Append = true
log4j.appender.E.Threshold = ERROR
log4j.appender.E.layout = org.apache.log4j.PatternLayout
log4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n

ActiveMQ分为两种类型:

  第一种队列模式:点对点模式,一个消息生产者生产的消息存入消息队列中,然后可以有多个消费者的多个连接,这些连接基本平均分配这些消息。

  第二种订阅发布模式:一定要订阅者(就是消费者)先要订阅队列,然后发布者发布消息存入队列,订阅者全部接受所有队列消息,不会均分。

第一种的队列模式:

  appProducer:

package com.zxc.jms.queue;

import javax.jms.*;

import org.apache.activemq.ActiveMQConnectionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory; public class appProducer { private static String url = "tcp://localhost:61616";
private static String queuename = "queue-test";
private static Logger logger = LoggerFactory.getLogger(appProducer.class); public static void main(String[] args) throws JMSException {
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(url);
Connection connection = connectionFactory.createConnection();
connection.start();
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
Destination destination = session.createQueue(queuename);
MessageProducer producer = session.createProducer(destination);
for (int i = 1; i <= 10000; i++) {
TextMessage message = session.createTextMessage("生产者发出第" + i + "消息");
producer.send(message);
logger.info("生产者发出的第{}条数据", i);
}
connection.close();
}
}

  

  appConsumer:

  

package com.zxc.jms.queue;

import javax.jms.*;

import org.apache.activemq.ActiveMQConnectionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory; public class appConsumer {
private static String url = "tcp://localhost:61616";
private static String queuename = "queue-test";
private static Logger logger = LoggerFactory.getLogger(appProducer.class); public static void main(String[] args) throws JMSException {
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(url);
Connection connection = connectionFactory.createConnection();
connection.start();
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
Destination destination = session.createQueue(queuename);
MessageConsumer consumer = session.createConsumer(destination);
consumer.setMessageListener(new MessageListener() {
@Override
public void onMessage(Message message) {
TextMessage textMessage = (TextMessage) message;
logger.info("接受者接到消息"); }
});
}
}

第二种:订阅发布模式

  appProducer:

package com.zxc.topic;

import javax.jms.*;

import org.apache.activemq.ActiveMQConnectionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory; public class appProducer {
private static final String url = "tcp://localhost:61616";
private static final String topicName = "topic-test";
private static final Logger logger = LoggerFactory.getLogger(appProducer.class); public static void main(String[] args) throws JMSException, InterruptedException {
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(url);
Connection connection = connectionFactory.createConnection();
connection.start();
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
Topic topic = session.createTopic(topicName);
MessageProducer producer = session.createProducer(topic);
for (int i = 0; i <= 100; i++) {
TextMessage message = session.createTextMessage("消息"+i);
producer.send(message);
logger.info("生产者广播第{}条消息",i);
Thread.sleep(2000);
}
connection.close();
}
}

  appConsumer:

  

package com.zxc.topic;

import javax.jms.*;

import org.apache.activemq.ActiveMQConnectionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory; public class appConsumer {
private static final String url = "tcp://localhost:61616";
private static final String topicName = "topic-test";
private static final Logger logger = LoggerFactory.getLogger(appProducer.class); public static void main(String[] args) throws JMSException {
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(url);
Connection connection = connectionFactory.createConnection();
connection.start();
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
Topic topic = session.createTopic(topicName);
MessageConsumer consumer = session.createConsumer(topic);
consumer.setMessageListener((message -> {
TextMessage textMessage = (TextMessage) message;
try {
logger.info("收到消息:{}",textMessage.getText());
} catch (JMSException e) {
e.printStackTrace();
}
}));
}
}

  

    

jms及active(jdk api)的实现的更多相关文章

  1. JDK API从下载到使用

    经常有人问我一些java常用类的使用方法,还有一些问某个常用类是干啥的.这些问题都是不会查询jdk api,对常用类的方法不熟悉等情况.于是,经过再三思考决定编写jdk api查询使用手册. ☆准备工 ...

  2. 所谓的规范以及JDK api文档的重要性

    所谓的规范,就是在jee api 文档里对应的接口. 可以从jdk文档和jee文档的目录结构,接口中获取对整个编程范围的把握

  3. JMS 之 Active MQ的安全机制

    一.认证 认证(Authentication):验证某个实体或者用户是否有权限访问受保护资源. MQ提供两种插件用于权限认证:(一).Simple authentication plug-in:直接把 ...

  4. Linux 下编译自己的 OpenJDK7 包括JVM和JDK API

    1.首先去 这里 http://download.java.net/openjdk/jdk7/ 下载OpenJDK7的源码zip包 2. 简要介绍下OpenJDK7中的目录 hotspot: 放有Op ...

  5. 学会使用JDK API

    api是字典,知识过了一遍之后,剩下的就是实践+百度+api了

  6. 为Eclipse/MyEclipse添加JDK API Document帮助文档

    1.下载 Java SE Development Kit 8 Documentation . 2.启动Eclipse,Window-Preference-Java-Installed JREs: 3. ...

  7. JMS 之 Active MQ 消息存储

    一.消息的存储方式 ActiveMQ支持JMS规范中的持久化消息与非持久化消息 持久化消息通常用于不管是否消费者在线,它们都会保证消息会被消费者消费.当消息被确认消费后,会从存储中删除 非持久化消息通 ...

  8. JMS 之 Active MQ 启动嵌入式Broke

    一.如何启动active MQ 服务 (一).使用命令启动 /bin 目录下 ./activemq start 默认使用conf/activemq.xml 配置文件 b.[root@localhost ...

  9. JMS 之 Active MQ 的spring整合

    一.与spring整合实现ptp的同步接收消息 pom.xml: <!-- https://mvnrepository.com/artifact/org.springframework/spri ...

随机推荐

  1. 拷贝构造函数(深拷贝vs浅拷贝)

    拷贝构造函数(深拷贝vs浅拷贝) 类对象之间的初始化是由类的拷贝构造函数完毕的.它是一种特殊的构造函数,它的作用是用一个已知的对象来初始化还有一个对象.假设在类中没有显式地声明一个拷贝构造函数.那么, ...

  2. 3D数学读书笔记——矩阵进阶

    本系列文章由birdlove1987编写,转载请注明出处. 文章链接:http://blog.csdn.net/zhurui_idea/article/details/25242725 最终要学习矩阵 ...

  3. Unity特殊目录和脚本编译顺序

     特殊目录和脚本编译顺序 大多数情况下,您能够选择不论什么你喜欢的目录在您的项目的名称.但unity储备一些名称以指示内容有一个特殊的用途.这些目录中有些会影响脚本编译的顺序.从根本上说,有四个单 ...

  4. 搭建简单的Habernate环境(一)

    一.开篇 下载Habernate所需要的jar包和mysql驱动. 二.建立java项目并且导入所需要的包 三.建立实体类和配置映射文件 user实体类 package testPackage; pu ...

  5. Oprofile分析(android oprofile性能分析)

    一.内核支持: make menuconfig 1.评测菜单中启用 Oprofile ,在 .config 文件中设置?CONFIG_PROFILING=y?和?CONFIG_OPROFILE=y 2 ...

  6. js从数组中取出n个不重复的数据

    /** * 首先,针对这个数组做一个去重处理,避免你在后面取数据的时候,因为取到相同的元素而又要多去取一次随机数 * 将获取到的不重复的数组,再到这里样本里面去取随机数 * 每取到一次,就将这个元素从 ...

  7. SwipeRefreshLayout的使用,下拉刷新

    1. <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android ...

  8. iOS11访问相册权限变更问题

    手机升到iOS 11后  发现之前正常的图片保存功能无法正常使用  会闪退 经测试发现应该是权限没有开启的原因  但是NSPhotoLibraryUsageDescription已经写入plist   ...

  9. 杭电 2639 Bone Collector II【01背包第k优解】

    解题思路:对于01背包的状态转移方程式f[v]=max(f[v],f[v-c[i]+w[i]]);其实01背包记录了每一个装法的背包值,但是在01背包中我们通常求的是最优解, 即为取的是f[v],f[ ...

  10. Imperative programming

    In computer science, imperative programming is a programming paradigm that uses statements that chan ...