0704~springboot整合ES&RabbitMQ

主要做课程上线功能:

 点击课程上架,操作步骤: 整合ES与RabbitMQ

1.把选中的id传入后台,修改上线状态;

2.把修改状态的对象存入ES索引库;

3.通过rabbitMQ给用户推送营销消息;

 1.把选中的id传入后台,修改上线状态;第一步昨天已总结;

2.把修改状态的对象存入ES索引库;

思路:

1.单独建立一个微服务用来做es查询保存操作,导入依赖,配置yml;

2.编写一个接口,交给spring管理,继承ElasticsearchRepository接口,泛型写doc文档实体类和Long;

 3.编写controller,注入自己编写的接口CourseRepository,调用方法;

4.编写feign,把接口暴露给课程服务使用;

5.课程微服务直接es微服务的feign接口使用 即可;

注意:doc文档实体类上加注解

@Document(indexName= "hrm", type = "course") indexname为es索引库名,type为es索引表,类似于mysql的建库建表;

 1.单独建立一个微服务用来做es查询保存操作,导入依赖,配置yml;

<!--ES的包-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
spring:
  data:
    elasticsearch:
      cluster-name: elasticsearch #集群名称
      cluster-nodes: 127.0.0.1:9300 #9200是图形界面端,9300代码你的端口
  application:
    name: service-es #服务名
  #配置数据库链接信息

2.编写一个接口,交给spring管理,继承ElasticsearchRepository接口,泛型写doc文档实体类和Long;

@Component
public interface CourseRepository extends ElasticsearchRepository<CourseDoc,Long> {
}

 3.编写controller,注入自己编写的接口CourseRepository,调用方法;

 

@RestController
@RequestMapping("/es")
public class CourseEsController {

    @Autowired
    private CourseRepository courseRepository;

    @PostMapping("/course")
    public JSONResult CourseEs(@RequestBody List<CourseDoc>docList){
        courseRepository.saveAll(docList);
        return JSONResult.success();
    }

4.编写feign,把接口暴露给课程服务使用;

 

@FeignClient(value = "service-es",fallbackFactory = FallbackFactoryCourse.class)
public interface CourseFeign {
    @PostMapping("/es/course")
    public JSONResult CourseEs(@RequestBody List<CourseDoc> docList);

5.课程微服务直接es微服务的feign接口使用 即可;

5.1创建一个list来存放前端选中的数据;

5.2.通过前端选中的id找出课程对象与课程市场对象,用BeanUtils.copyProperties(起始数据,目标数据)方法给doc文档类赋值;

5.3返回list即可;

@Override
public JSONResult onLineCourse(CourseQuery query) {
    //上下线
    //思路
    //1.通过前端传过来的id拿到对象;
    //2.拿到对象给对象设置状态;
    //3.修改返回即可;
    //4.把上线的课程存入es索引库
    //5.通过rabbitMQ发送消息给用户
    Long[] ids = query.getIds();
    List<CourseDoc> list = new ArrayList<>();
    CourseDoc courseDoc = new CourseDoc();
    for (Long id : ids) {
        Course course = courseMapper.selectById(id);
        if(course.getStatus()!=0){
            throw new MyException("当前课程已经上线啦~");
        }
        course.setStatus(1);
        courseMapper.updateById(course);
        CourseMarket courseMarket = courseMarketMapper.selectById(course.getId());
        System.out.println(courseMarket);
        BeanUtils.copyProperties(courseMarket,courseDoc);
        BeanUtils.copyProperties(course,courseDoc);
        list.add(courseDoc);
        courseFeign.CourseEs(list);
    }

3.通过rabbitMQ给用户推送营销消息;

springboot整合RabbitMQ思路:

1.导入依赖,添加yml配置;

<!--spirngboot集成rabbitmq-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
#RabbitMQ相关 放在第二层
rabbitmq:
  host: 127.0.0.1
  port: 5672
  username: guest
  password: guest
  virtualHost: /
  publisher-confirms: true #消息发送到交换机后的回调
  publisher-returns: true  #消息由交换机发到队列失败后的回调
  template:
    mandatory: true # 必须设置成true 消息路由失败通知监听者,而不是将消息丢弃

2.rabbitmq配置类,配置队列名与交换机机名,还有队列 与交换机的绑定; 以及初始化RabbitAdmin对象

@Component
public class ConfigRabbitMQ {


    //创建交换机
    @Bean
    public Exchange getExchange(){
        return ExchangeBuilder.topicExchange("课程交换机名").build();
    }
    //创建队列
    @Bean
    public Queue getQueue(){
        return new Queue("课程队列名",true,false,false);
    }
    //绑定交换机与队列
    @Bean
    public Binding getBinding(){
        return BindingBuilder.bind(getQueue()).to(getExchange()).with("课程路由键").noargs();
    }

    //初始化RabbitAdmin对象
    @Bean
    public RabbitAdmin rabbitAdmin(ConnectionFactory connectionFactory) {
        RabbitAdmin rabbitAdmin = new RabbitAdmin(connectionFactory);
        // 只有设置为 true,spring 才会加载 RabbitAdmin 这个类
        rabbitAdmin.setAutoStartup(true);

        //下面设置目的:项目启动时,就创建交换机和队列
        //创建交换机
        rabbitAdmin.declareExchange(getExchange());
        //创建对列
        rabbitAdmin.declareQueue(getQueue());

        return rabbitAdmin;
    }
}

 第二个配置类,配置rabbitmq的序列化配置,以及两个回调函数(confirms,returns);

/**
 * @description: 做序列化
 */
@Configuration
public class RabbitMQConverterConfig implements RabbitListenerConfigurer{

    //以下配置RabbitMQ消息服务
    @Autowired
    public ConnectionFactory connectionFactory;

    @Bean
    public DefaultMessageHandlerMethodFactory myHandlerMethodFactory() {
        DefaultMessageHandlerMethodFactory factory = new DefaultMessageHandlerMethodFactory();
        // 这里的转换器设置实现了 通过 @Payload 注解 自动反序列化message body
        factory.setMessageConverter(new MappingJackson2MessageConverter());
        return factory;
    }

    @Override
    public void configureRabbitListeners(RabbitListenerEndpointRegistrar registrar) {
        registrar.setMessageHandlerMethodFactory(myHandlerMethodFactory());
    }

    @Bean
    public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory() {
        SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
        factory.setConnectionFactory(connectionFactory);
        factory.setConcurrentConsumers(3);
        factory.setMaxConcurrentConsumers(10);
        //设置手动签收
        factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
        return factory;
    }

    @Bean
    public MessageConverter jsonMessageConverter() {
        return new Jackson2JsonMessageConverter();
    }

    @Bean
    public RabbitTemplate rabbitTemplate() {
        RabbitTemplate template = new RabbitTemplate(connectionFactory);
        // 这里的转换器设置实现了发送消息时自动序列化消息对象为message body
        template.setMessageConverter(jsonMessageConverter());
        template.setMandatory(true);
        return template;
    }
}

3.使用RabbitTemplate发送队列消息;

 

rabbitTemplate.convertAndSend("课程交换机名","课程路由键","这是新上线的队列");

 高频面试题;如何保持RabbitMQ消息不丢失?

1、需要设置Confirm和Return回调方法进行处理

2、然后搞一张消息发送的记录表,里面包含如下字段:交换机名称、routingkey、消息内容、消息状态、重试次数等字段

3、发送消息的时候,将状态置为发送中,重试次数给个默认值(可以从配置表中取),如果Confirm回调里的ack是false,那么我们就需要将状态更新为发送失败,否则更新为发送成功(0:发送中;1:生产者到交换机失败;2:交换机到队列失败;3:成功)

4、Return回调方法只要被触发,说明消息肯定发送失败了,直接将状态改为发送失败

5、搞一个定时任务,定时去扫描该表的所有状态为发送失败的记录,重试次数大于0的消息,重新进行消息发送,每发送一次,重试次数字段减一,直到0为止

6、当重试次数等于0时,说明发送了很多次还是失败,此时需要发短信或邮件告知运维人员,进行人工干预了

 原理理解图:

 

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
【资源说明】 1、该资源包括项目的全部源码,下载可以直接使用! 2、本项目适合作为计算机、数学、电子信息等专业的课程设计、期末大作业和毕设项目,作为参考资料学习借鉴。 3、本资源作为“参考资料”如果需要实现其他功能,需要能看懂代码,并且热爱钻研,自行调试。 基于springcloud+Netty+MQ+mysql的分布式即时聊天系统源码+数据库+项目说明.zip # KT-Chat 分布式即时聊天系统 **技术选型**:JavaSpringCloud、Nacos、Sentinel、Netty、MySQL、Redis、RocketMQ 等 **项目描述**:项目基于 SpringCloud Gateway + Nacos + Sentinel + OpenFeign 作为分布式系统架构,基于 Netty 实现高性能网络通信。主要功能有:一对一聊天以及群组聊天、好友管理、群组管理等。 项目独立完成,包括需求分析、设计、开发实现。 关于我在项目中使用 MySQL 读写分离的总结:[MySQL主从延迟的解决方案](https://blog.csdn.net/KIMTOU/article/details/125033199) ## 用例分析 用户能够在聊天系统上进行网络通信,与好友进行实时一对一聊天,与群组成员进行群聊。用户用例图如下所示: 1. 用户登录:登录系统 2. 聊天:包含与好友进行一对一聊天,与群组成员进行群聊。 3. 群聊管理:新建群聊、加入群聊、退出群聊。 4. 好友管理:显示好友列表,添加、删除好友。 5. 在线离线状态显示:查看好友的在线、离线状态。 6. 聊天记录管理:将聊天记录存入数据库,能够显示、删除存储的聊天记录。 <img src="https://cdn.tojintao.cn/Chat原理图.png" alt="img" style="zoom:67%;" /> ## 系统设计 #### 系统总体设计 分布式即时聊天系统分为用户信息子系统、长连接管理子系统、聊天信息子系统共三个子系统,API 网关负责将请求路由至各个子系统。 * 用户信息子系统包含权限校验模块、用户登录模块、好友管理模块,其中好友管理模块包括好友列表、添加好友、删除好友功能; * 长连接管理子系统包含在线状态管理模块、聊天主模块、消息推送模块,其中聊天主模块包括一对一聊天和群聊功能; * 聊天信息子系统包含群聊管理模块、聊天记录管理模块,其中群聊管理模块包括新建群聊、加入群聊、退出群聊功能。 <img src="https://cdn.tojintao.cn/KT-Chat系统结构图.png" style="zoom:67%;" /> #### 系统架构设计 ![](https://cdn.tojintao.cn/KT-Chat系统架构设计.png) 项目基于 Nacos 作为注册中心,将各个服务注册进 Nacos,包括 Netty 服务端;使用 SpringCloud Gateway 作为服务网关,是所有请求的统一入口;限流组件使用 Sentinel;基于 Netty 进行通信、维护长连接;RocketMQ 作为消息队列,处理聊天消息的异步入库以及解决分布式 Netty 节点问题; Zookeeper 用于分布式 id 的生成;Redis 用于记录用户在线状态以及记录 Netty 节点的元数据;MySQL 对数据进行持久化。 ## 运行截图 #### 一对一聊天 ![](https://cdn.tojintao.cn/聊天测试1.PNG) #### 群聊 ![](https://cdn.tojintao.cn/群聊测试1.PNG) ## 启动说明 1. 启动本项目时,需提前启动 Nacos、RocketMQ、MySQL、Redis、ElasticSearch、Sentinal 实例。 2. conntector 与 connector-2 这两个模块并不一样,connector-2 使用了 Dubbo 进行消息转发(实验阶段),而 connector 使用 Feign 进行 HTTP 调用转发消息。启动 connector 就行了。 3. 每个服务都允许运行多个实例。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值