JMS-使用消息队列优化网站性能

news/2024/5/21 0:35:30/文章来源:https://blog.csdn.net/weixin_33713503/article/details/91717997

为什么80%的码农都做不了架构师?>>>   hot3.png

在当今互联网和电商盛行的情况下,网站的性能受到了极大地挑战。大数据,高并发成为大型网站的标志。无论淘宝的双11优惠,还是小米抢购,它们都有一个共同的特点,那就是在短时间内,突然涌入超出平时数倍的用户。

如果每个用户从请求,到订单处理,再到响应返回均在一个请求中同步处理的话,用户的响应时间将会随着并发量的提高越来越久,直到最后服务器崩溃。在这种情况下,可以使用JMS消息队列,异步处理订单。用户发出请求,服务器接收请求以后,向消息队列中发送一个消息,就立刻返回“订单正处理”的消息给用户。而订单处理服务器可以不停的从消息队列中取出消息,按照自己的节奏进行处理。这就像生产者-消费者模式一样。通过这种异步的处理方式,用户响应时间得到缩减,服务器的压力也可以被时间分担,从而避过洪峰期。

在之前的文章JavaMail发送google email中,我使用的是同步方式发送email,可以一个用户的响应有多慢。今天我将使用JMS的方式,改进邮件发送系统。

JMS

首先还是要简单的介绍下JMS(Java Messaging Service)。太基础的就不再唠叨了,这里只列出JMS的两种消息模式:

  1. PTP模式

    PTP模式中,消息是Queue的形式从一端到另一端。无论client2是否连接,运行中,JMS的可靠性使得Msg都不会丢失。当client2恢复运行时,Queue会继续传输。Queue的两端可以有多个clients,但是每一个消息,只能被一个consumer client消费。所以,对于消费客户端们而言,也属于争抢式消费。

    163604_ESiO_254689.png

  2. Pub/Sub模式

    在发布订阅的模式中,则是以topic,subscription,client的方式。所有的订阅者均可受到消息,一个消息会被重复的发送给不同的消费者。

    163957_C1ZR_254689.png

    一个topic下面可以挂很多的subscription,但是这些subscription只有4种类型,这4中类型如下图:

    165309_mM6J_254689.png

    Subscription:只能有一个client,当client断开连接,subscription则自动销毁。

    Durable Subscription:只能有一个client,当client断开连接后,Message会被存在subscription中,一旦client重新连接,则继续发送消息。

    Shared Subscription:可以有多个client同时挂在一个subscription上,这样可以有多个client并行的处理此Subscription下的消息。记住,消息只能被其中一个client所消费,不能被多个client同时消费。

    Shared Durable Subscription:区别在durable上,即client断线,subscription会继续存在。

PTP适合单一消息类型,单一消费者类型。而Pub/Sub适合多种类消息,和多种消费者类型。

此外,消息可以是可持久化的,也可以是非持久化的。持久化的消息将被写入硬盘,当MQ server重启后,消息不会丢失。

消息的消费方式也存在两种模式:

  1. JMS client API调用。此种方式的缺点在于,需要自己维护多线程。

  2. MDB(Message Driven Bean)。使用EJB的方式,可以由EJB容器帮忙管理多线程。其中MDB是多实例的,每个消息过来都是一个新的线程。

JMS服务器

JMS是针对java来讲的,一般,称为MQ server。MQ Server不只针对Java,还针对C,C++,PHP,C#.... 非常多的平台。当前最火的是Apache ActiveMQ,也有使用JBoss Messaging的。但本文将使用Oracle的Glassfish Open MQ。

Open MQ是Oracle Glassfish下的一款MQ server,它是第一个实现了JMS2.0标准的MQ server。它可以单独使用,搭建集群,也可以内嵌到Glassfish中使用。在Glassfish4中,OpenMQ已经集成在Glassfish4中。Glassfish4可以使用内嵌的OpenMQ来满足小型网站的异步消息处理,也可以使用外部的OpemMQ集群来满足大型网站的异步消息处理。

有人会很纠结,ActiveMQ,OpenMQ到底哪一个好?其实我觉得每一款软件都有各自的特点,它们均能支撑起一个大型网站的架构,问题在于你如何使用它们。Glassfish是一个缩小型的WebLogic,轻巧易用。OpenMQ支持JMS2.0,易集成于Glassfish,又为Oracle支持的开源项目,其能力一样强悍。唯一的缺点是,集成于Glassfish中的OpenMQ不支持C客户端。

接下来,我将使用JMS消息队列来优化邮件发送系统。

小型网站的邮件发送系统

必备软件

Glassfish4,版本4是必须的,因为4中集成了OpenMQ,我们可以直接在Glassfish4中使用本地JMS服务。针对大型网站的远程JMS服务,我们将在下一篇文章中实现。

改造方案

本文将尝试两种改造方案:

  1. JMS client API + threadPool,自己在后台启动线程监听,并管理多线程。

  2. MDB, EJB容器进行Message监听,并帮助管理多线程。

应该使用多少线程?线程的数量与CPU的数量和IO阻塞时间有关系。如果线程没有任何IO阻塞,那么,线程数量应该和CPU数量相同。因为多余的线程需要等待CPU。如果存在IO阻塞,则需要多余CPU数量的线程,一个线程阻塞在IO上的时候,CPU不至于空闲,可以去执行其它线程。仔细推导,可以能通过IO阻塞时间跟运行时间的比例,可以计算出所需线程的数量

显然,方案二是最明智的做法。家下来,开始实现方案二。

配置JMS Resources

打开Glassfish管理页面http://localhost:4848 

  1. 配置JMS ConnectionFactory。可以使用glassfish默认的。

    230457_nz6g_254689.png

  2. 配置Destination Resources. 展开Resources->JMS Resources->Destination Resources. 创建一个Queue resource。

    231037_ZcGZ_254689.png

配置Java Mail Session

请在上一篇文章中http://my.oschina.net/xpbug/blog/263974#OSC_h2_3 找到Gmail的配置方法。

创建一个Web项目

创建一个名为sample的web项目。

创建MDB

创建接收JMS消息的MDB,我们使用简单的text message。email地址在message体中。MDB会向地址中发送一个简单邮件。

package com.mycompany;import java.util.logging.Level;
import java.util.logging.Logger;
import javax.ejb.ActivationConfigProperty;
import javax.ejb.MessageDriven;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.mail.Address;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;/**** @author none2*/
@MessageDriven(activationConfig = {@ActivationConfigProperty(propertyName = "destinationLookup", propertyValue = "jms/myQueue"),@ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue")
})
public class EmailMessageBean implements MessageListener {private final Session mySession;public EmailMessageBean() throws NamingException {Context initCtx = new InitialContext();mySession = (Session) initCtx.lookup("mail/mySession");}@Overridepublic void onMessage(Message message) {    try {String address = message.getBody(String.class);javax.mail.Message mail = new MimeMessage(mySession);mail.setFrom(new InternetAddress("joey.zhangpeng@gmail.com"));Address toAddress = new InternetAddress(address);mail.addRecipient(javax.mail.Message.RecipientType.TO, toAddress);mail.setSubject("Hello");mail.setText("A notification.");Transport.send(mail);} catch (MessagingException | JMSException ex) {Logger.getLogger(EmailMessageBean.class.getName()).log(Level.SEVERE, null, ex);}}
}

index.html

创建网站的默认页面

<html><head><title>TODO supply a title</title><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"></head><body><form method="post" action="/sample/NotifyServlet">Email:<input name="email" value=""/><input type="submit" value="Buy" name="submit"/>            </form></body>
</html>

创建NotifyServlet

在servlet中,使用jms client,发送jms消息到queue中。

package com.mycompany;import java.io.IOException;
import java.io.PrintWriter;
import javax.annotation.Resource;
import javax.jms.ConnectionFactory;
import javax.jms.JMSContext;
import javax.jms.Queue;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;/**** @author none2*/
@WebServlet(name = "NotifyServlet", urlPatterns = {"/NotifyServlet"})
public class NotifyServlet extends HttpServlet {@Resource(lookup = "java:comp/DefaultJMSConnectionFactory")private ConnectionFactory connectionFactory;@Resource(lookup = "jms/myQueue")private Queue queue;@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {String email = request.getParameter("email");try (JMSContext context = connectionFactory.createContext();) {context.createProducer().send(queue, email);}response.setContentType("text/html;charset=UTF-8");try (PrintWriter out = response.getWriter()) {/* TODO output your page here. You may use following sample code. */out.println("<!DOCTYPE html>");out.println("<html>");out.println("<head>");out.println("<title>Servlet NotifyServlet</title>");            out.println("</head>");out.println("<body>");out.println("<h1>You have send a notification to " + email + "</h1>");out.println("</body>");out.println("</html>");}}
}

最后,进行项目打包并部署。访问http://localhost:8080/sample/ 来测试一下。

后续,使用远程MQ server增加伸缩性

转载于:https://my.oschina.net/xpbug/blog/264475

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_769556.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

PHP识别电脑还是手机访问网站

为什么80%的码农都做不了架构师&#xff1f;>>> <?php function isMobile(){ $useragentisset($_SERVER[HTTP_USER_AGENT]) ? $_SERVER[HTTP_USER_AGENT] : ; $useragent_commentsblockpreg_match(|\(.*?\)|,$useragent,$matches)>0?$matches[0]:; …

网站首页轮番图的后台管理

如下图&#xff0c;很多CMS的首页都会有实时更新的轮番图的需求&#xff1a; 最近在做一个CMS的过程中&#xff0c;就遇到了这样的需求。 之前曾经做过一个校园网站的项目&#xff08;自己做着玩玩&#xff09;&#xff0c;但前台的轮番图是写死在页面上的&#xff0c;即&#…

Https网站中请求Http内容

Https网站中请求Http内容Https网站中无法请求Http资源&#xff08;静态资源、接口等&#xff09;分析解决方法Https网站中无法请求Http资源&#xff08;静态资源、接口等&#xff09; 今天遇到个问题&#xff1a;Mixed Content: The page at ‘https://*****’ was loaded over…

Windows server 2012配置WebDeploy发布网站

以前都是使用win2008r2服务器&#xff0c;最近更新了操作系统到WINDOWS 2012,发现以前的做法已经不适用了。 win2008r2配置WebDeploy&#xff1a; https://www.cnblogs.com/xcsn/p/7067841.html 下面直接进入主题 一、下载安装 1.下载web平台组件 2.安装 先安装WEB DEPLOY 3.5&…

网站日志分析诊断及其作用

相信大家都知道网站日志是什么东西&#xff0c;可是做SEO的有多少人会去关注分析网站日志呢&#xff0c;又有多少SEOer能看懂网站日志呢&#xff1f;今天就给大家讲解下在网站SEO优化中&#xff0c;怎样利用网站日志的诊断和分析来提高网站关键词的排名。 首先我们仙说下网站日…

设计师升职加薪必须知道的10个设计网站

设计行业经过几年的发展&#xff0c;已经进入到了相对成熟的时期。这无疑会对设计师有更高的要求和挑战。随着AI的发展&#xff0c;设计甚至从有形的设计&#xff0c;转变为无形的设计。这就需要你对设计有更深刻的理解&#xff0c;理解设计的本质是沟通&#xff0c;设计源于人…

阿里云--域名,主机,备案都配置好了,就是不能访问网站的解决方案

异常处理汇总 ~ 修正果带着你的Net飞奔吧&#xff01;http://www.cnblogs.com/dunitian/p/4599258.html 1.解析问题&#xff1a;参考这个文章&#xff1a;http://www.cnblogs.com/dunitian/p/4977261.html 2.主机设置问题&#xff1a; 主机管理 http://cp.aliyun.com/ 主机里面…

网站跳转劫持漏洞的发现与修复建议

2019独角兽企业重金招聘Python工程师标准>>> 网站渗透测试是指在没有获得网站源代码以及服务器的情况下&#xff0c;模拟入侵者的攻击手法对网站进行漏洞检测&#xff0c;以及渗透测试&#xff0c;可以很好的对网站安全进行全面的安全检测&#xff0c;把安全做到最大…

大型网站技术架构(一)大型网站架构演化

2019独角兽企业重金招聘Python工程师标准>>> 看完了有一本书&#xff0c;就应该有所收获&#xff0c;有所总结&#xff0c;最近把《大型网站技术架构》一书给看完了&#xff0c;给人的印象实在深刻&#xff0c;再加上之前也搞过书本上讲的反向代理和负载均衡以及ses…

大型网站技术架构(六)网站的伸缩性架构

2019独角兽企业重金招聘Python工程师标准>>> 网站系统的伸缩性架构最重要的技术手段就是使用服务器集群功能&#xff0c;通过不断地向集群中添加服务器来增强整个集群的处理能力。“伸”即网站的规模和服务器的规模总是在不断扩大。 1、网站架构的伸缩性设计 网站的…

大型网站技术架构-发展过程

2019独角兽企业重金招聘Python工程师标准>>> 网站都是从小网站一步一步发展为大型网站的&#xff0c;而这之中的挑战主要来自于庞大的用户、安全环境恶劣、高并发的访问和海量的数据&#xff0c;任何简单的业务处理&#xff0c;一旦需要处理数以 P 计的数据和面对数…

Python一课一练(建立第一个个人网站)

2019独角兽企业重金招聘Python工程师标准>>> 使用Python来上手建站比较简单 安装lpthw.web框架&#xff0c;使用pip来安装&#xff0c;在powershell输入"pip install lpthw.web"还记得我们的工程结构吗&#xff1f;不过这次在"skeleton"目录下增…

云主机如何选带宽-- 1M带宽有多快--建站必考虑因素

对于很多新手来说&#xff0c;在选购服务器的时候可能会有些疑问&#xff0c;我应该买多大的带宽&#xff0c;或者是我买了1M的带宽怎么最快的传输速度只有120kB左右&#xff0c;有以上疑惑的朋友不着急&#xff0c;接下来我就带大家分析看看。 一、在分析之前我们要搞清楚几…

wordpress网站压测--Ubuntu下Apache2 的调优(待续)

最近我在对自己建的一个用wordpress搭建的网站使用进行压测。 设备 2核2G突发性实例&#xff08;20%基准CPU计算性能 &#xff09; 带宽2M 工具 1、 压测工具 Jmeter 环境 1、Unbuntu16.04 2、Apache2.4.18 3、wordpress 5.3.2 4、php7.0 5、MySQL 5.6.29 压力测…

iis6服务器网站批量迁移,使用MS Web Deploy工具从IIS 6.0迁移大量应用到IIS 7.0

情人节&#xff0c;虽然一个人过&#xff0c;可是也不想加班&#xff0c;刚找到这篇文章就到点下班了&#xff0c;明天再测试行不行这里给大家介绍一下WebDeploy这个IIS的迁移工具。Windows server 2008r2在web服务上做了很大的提升&#xff0c;Windows server 2008的IIS7从核心…

MapReduce编程案例之电商网站日志的行为分析

目录一、需求分析二、程序编写一、需求分析 1.网站数据分析的四个指标&#xff1a; PV&#xff1a;PageView ,浏览量 用户每打开一个网页就会被记录1次浏览量&#xff0c;多次打开同一个页面浏览量累计加一 UV&#xff1a;Unique Visitor 独立访客数 同一用户多次访问&#x…

基于Sqoop+Hive+MySQL网站日志分析项目实战

目录一、需求分析及数据准备&#xff08;1&#xff09;需求分析&#xff08;2&#xff09;实施分案&#xff08;3&#xff09;准备数据二、pvuv数据分析三、导出结果四、企业优化方案五、编写自动加载数据脚本六、编写自动调度数据分析七、运行测试一、需求分析及数据准备 &am…

基于Spark SQL对新闻网站项目案例分析

目录一、需求分析二、数据准备&#xff08;1&#xff09;数据格式&#xff08;2&#xff09;基于Java开发离线数据生成器&#xff08;3&#xff09;基于业务数据创建hive表三、数据模型&#xff08;1&#xff09;需求一&#xff1a;对网站的pv分析&#xff08;2&#xff09;需求…

实现基于LNMP的电子商务网站

实现基于LNMP的电子商务网站&#xff1a;1. yum方式安装mariadb、 mariadb-server、 php-mysql、 php、 php-fpm2.下载小米商城源码&#xff0c; 解压缩到/data/web目录&#xff0c; 修改权限为nobody3.修改nginx配置&#xff0c; 把nginx.conf.default模板复制为配置文件进行修…

各大网站和app是如何实现黑白页面效果?

今天是2020年4月4日&#xff0c;在此期间&#xff0c;全国和驻外使领馆下半旗志哀&#xff0c;全国停止公共娱乐活动。4月4日10时起&#xff0c;全国人民默哀3分钟&#xff0c;汽车、火车、舰船鸣笛&#xff0c;防空警报鸣响。 很多软件网站都变成了黑白色&#xff0c;比如b站.…