• 1024_day03_消息中间件RabbitMQ


    1.RabbitMQ作用:处理高并发

    rabbitmq在一条TCP上建立成百上千个信道来达到多个线程处理,这个TCP被多个线程共享,每个线程对应一个信道,信道在rabbit都有唯一的ID ,保证了信道私有性,对应上唯一的线程使用。

    (1)可靠性(Reliability) RabbitMQ 使用一些机制来保证可靠性,如持久化、传输确认、发布确认。

    (2)灵活的路由(Flexible Routing)在消息进入队列之前,通过 Exchange 来路由消息的。对于典型的路由功能,RabbitMQ 已经提供了一些内置的 Exchange 来实现。针对更复杂的路由功能,可以将多个 Exchange 绑定在一起,也通过插件机制实现自己的 Exchange 。

    (3)消息集群(Clustering) 多个 RabbitMQ 服务器可以组成一个集群,形成一个逻辑 Broker 。

    (4)高可用(Highly Available Queues) 队列可以在集群中的机器上进行镜像,使得在部分节点出问题的情况下队列仍然可用】

    2.架构图

     

     Exchange:生产者将消息发送到Exchange(交换器),由Exchange将消息路由到一个 或多个Queue中(或者丢弃)。Exchange并不存储消息。RabbitMQ中的Exchange有 direct、fanout、topic、headers四种类型,每种类型对应不同的路由规则。(你的消息想要发给哪一个队列进行处理,或者设定某个规则发给符合规则的队列)

    Queue:(队列)是RabbitMQ的内部对象,用于存储消息。消息消费者就是通过订阅 队列来获取消息的,RabbitMQ中的消息都只能存储在Queue中,生产者生产消息并最终 投递到Queue中,消费者可以从Queue中获取消息并消费。多个消费者可以订阅同一个 Queue,这时Queue中的消息会被平均分摊给多个消费者进行处理,而不是每个消费者 都收到所有的消息并处理。

    3.直接模式

    我们需要将消息发给唯一一个节点时使用这种模式,这是最简单的一种形式。

    (1)一般情况可以使用rabbitMQ自带的Exchange:”"(该Exchange的名字为空字符串,下 文称其为default Exchange)。

    4.分列模式

    当我们需要将消息一次发给多个队列时,需要使用这种模式。如下图

    (1)可以理解为路由表的模式

    (2)这种模式不需要RouteKey

    (3)这种模式需要提前将Exchange与Queue进行绑定,一个Exchange可以绑定多个 Queue,一个Queue可以同多个Exchange进行绑定。

    (4)如果接受到消息的Exchange没有与任何Queue绑定,则消息会被抛弃。

     5.主题模式

    任何发送到Topic Exchange的消息都会被转发到所有关心RouteKey中指定话题的Queue 上(将消息转发到符合Exchange设定规则的队列上)

     

     测试代码:"good.log"为条件

     @Test
        public void testSendTopic() {
    
            rabbitTemplate.convertAndSend("rabbitTopic","good.log","主题模式");
        }

    6.springBoot 通过 消息中间件RabbitMQ和阿里云短信服务发送短信验证码

    (1)配置application.yaml 并注册好阿里云短信服务

    server:
      port: 9009
    spring:
      application:
        name: tensquare_sms
      rabbitmq:
        host: 101.200.72.*
    aliyun:
      sms:
        accessKeyId: ************************
        accessKeySecret: *****************
        template_code: SMS_**************
        sign_name: 十次方服务

    (2)导入坐标

            <dependency>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-starter-amqp</artifactId>
           </dependency>        

    (3)用户从注册后将生成的验证码和手机号放入到消息队列中

    @Autowired
        private RabbitTemplate rabbitTemplate;
    
        /**
         * 发送验证码
         *
         * @return
         */
        public void sendSms(String mobile) {
            //lang3 工具类
            String checkCode = RandomStringUtils.randomNumeric(6);
    
            //在缓存中放一份
            redisTemplate.opsForValue().set("mobile_" + mobile, checkCode, 10, TimeUnit.MINUTES);
    
            //在消息队列中放一份
            HashMap<String, String> map = new HashMap<>();
            map.put("mobile", mobile);
            map.put("checkCode", checkCode);
            rabbitTemplate.convertAndSend("sms", map);
    
        }

    消息队列

    (3)创建消息队列监听器,监听到sms的消息队列后,发送短信

    @Component
    @RabbitListener(queues = "sms")
    public class SmsListener {
        @Autowired
        private SmsUtil smsUtil;
    
        @Value("${aliyun.sms.template_code}")
        private String template_code;
    
        @Value("${aliyun.sms.sign_name}")
        private String sign_name;
    
        @RabbitHandler
        public void excuteSms(Map<String, String> map) {
            String mobile = map.get("mobile");
            String checkcode = map.get("checkCode");
    
            try {
                SendSmsResponse sendSmsResponse = smsUtil.sendSms(mobile, template_code, sign_name, "{"ckeckcode":"" + checkcode + ""}");
                System.out.println(sendSmsResponse);
            } catch (ClientException e) {
                e.printStackTrace();
            }
    
        }
    }

    (4)阿里云短信utils

    坐标

    <!--阿里云短信业务-->
            <dependency>
                <groupId>com.aliyun</groupId>
                <artifactId>aliyun-java-sdk-core</artifactId>
                <version>4.0.6</version>
                <!-- 注:如提示报错,先升级基础包版,无法解决可联系技术支持 -->
            </dependency>
            <dependency>
                <groupId>com.aliyun</groupId>
                <artifactId>aliyun-java-sdk-dysmsapi</artifactId>
                <version>1.1.0</version>
            </dependency>

    utils

    /**
     * 短信工具类
     * @author Administrator
     *
     */
    @Component
    public class SmsUtil {
    
        //产品名称:云通信短信API产品,开发者无需替换
        static final String product = "Dysmsapi";
        //产品域名,开发者无需替换
        static final String domain = "dysmsapi.aliyuncs.com";
    
        //拿到配置文件中的所有配置 以key value
        @Autowired
        private Environment env;
    
        // TODO 此处需要替换成开发者自己的AK(在阿里云访问控制台寻找)
    
        /**
         * 发送短信
         * @param mobile 手机号
         * @param template_code 模板号
         * @param sign_name 签名
         * @param param 参数
         * @return
         * @throws ClientException
         */
        public SendSmsResponse sendSms(String mobile,String template_code,String sign_name,String param) throws ClientException {
            String accessKeyId =env.getProperty("aliyun.sms.accessKeyId");
            String accessKeySecret = env.getProperty("aliyun.sms.accessKeySecret");
            //可自助调整超时时间
            System.setProperty("sun.net.client.defaultConnectTimeout", "10000");
            System.setProperty("sun.net.client.defaultReadTimeout", "10000");
            //初始化acsClient,暂不支持region化
            IClientProfile profile = DefaultProfile.getProfile("cn-hangzhou", accessKeyId, accessKeySecret);
            DefaultProfile.addEndpoint("cn-hangzhou", "cn-hangzhou", product, domain);
            IAcsClient acsClient = new DefaultAcsClient(profile);
            //组装请求对象-具体描述见控制台-文档部分内容
            SendSmsRequest request = new SendSmsRequest();
            //必填:待发送手机号
            request.setPhoneNumbers(mobile);
            //必填:短信签名-可在短信控制台中找到
            request.setSignName(sign_name);
            //必填:短信模板-可在短信控制台中找到
            request.setTemplateCode(template_code);
            //可选:模板中的变量替换JSON串,如模板内容为"亲爱的${name},您的验证码为${code}"时,此处的值为
            request.setTemplateParam(param);
            //选填-上行短信扩展码(无特殊需求用户请忽略此字段)
            //request.setSmsUpExtendCode("90997");
            //可选:outId为提供给业务方扩展字段,最终在短信回执消息中将此值带回给调用者
            request.setOutId("yourOutId");
            //hint 此处可能会抛出异常,注意catch
            SendSmsResponse sendSmsResponse = acsClient.getAcsResponse(request);
            return sendSmsResponse;
        }
    
        public  QuerySendDetailsResponse querySendDetails(String mobile,String bizId) throws ClientException {
            String accessKeyId =env.getProperty("accessKeyId");
            String accessKeySecret = env.getProperty("accessKeySecret");
            //可自助调整超时时间
            System.setProperty("sun.net.client.defaultConnectTimeout", "10000");
            System.setProperty("sun.net.client.defaultReadTimeout", "10000");
            //初始化acsClient,暂不支持region化
            IClientProfile profile = DefaultProfile.getProfile("cn-hangzhou", accessKeyId, accessKeySecret);
            DefaultProfile.addEndpoint("cn-hangzhou", "cn-hangzhou", product, domain);
            IAcsClient acsClient = new DefaultAcsClient(profile);
            //组装请求对象
            QuerySendDetailsRequest request = new QuerySendDetailsRequest();
            //必填-号码
            request.setPhoneNumber(mobile);
            //可选-流水号
            request.setBizId(bizId);
            //必填-发送日期 支持30天内记录查询,格式yyyyMMdd
            SimpleDateFormat ft = new SimpleDateFormat("yyyyMMdd");
            request.setSendDate(ft.format(new Date()));
            //必填-页大小
            request.setPageSize(10L);
            //必填-当前页码从1开始计数
            request.setCurrentPage(1L);
            //hint 此处可能会抛出异常,注意catch
            QuerySendDetailsResponse querySendDetailsResponse = acsClient.getAcsResponse(request);
            return querySendDetailsResponse;
        }
    }

    (1)

    (1)

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

  • 相关阅读:
    Ubuntu部分命令的使用简介
    向Ubuntu的Dash中添加图标
    Ubuntu下实现gedit支持nesC语法高亮
    zoj 1453 Surround the Trees(凸包求周长)
    fzu 1015 土地划分(判断线段相交+求出交点+找规律)
    zoj 1648 判断线段是否相交
    hdu 1086(计算几何入门题——计算线段交点个数)
    zoj 1081 判断点在多边形内
    判点在直线上,三角形内
    poj 1269 Intersecting Lines(判相交交点与平行)
  • 原文地址:https://www.cnblogs.com/asndxj/p/12346859.html
Copyright © 2020-2023  润新知