MQ与ES简单实战

文章目录


对于大多数人来说,mq只是听说,知晓一点,但不知道该如何使用的,以下一个简单的mq实战例子
mq的好处有:解耦和,异步处理,流量消峰
mq服务配置

@Configuration
public class MQConfig {

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

配置当前RabbitTemplate

@Component
public class MQProducerAckConfig implements RabbitTemplate.ReturnCallback,RabbitTemplate.ConfirmCallback {

    //  我们发送消息使用的是 private RabbitTemplate rabbitTemplate; 对象
    //  如果不做设置的话 当前的rabbitTemplate 与当前的配置类没有任何关系!
    @Autowired
    private RabbitTemplate rabbitTemplate;

    //  设置 表示修饰一个非静态的void方法,在服务器加载Servlet的时候运行。并且只执行一次!
    @PostConstruct
    public void init(){
        rabbitTemplate.setReturnCallback(this);
        rabbitTemplate.setConfirmCallback(this);
    }

    /**
     * 表示消息是否正确发送到了交换机上
     * @param correlationData   消息的载体
     * @param ack   判断是否发送到交换机上
     * @param cause 原因
     */
    @Override
    public void confirm(CorrelationData correlationData, boolean ack, String cause) {
        if(ack){
            System.out.println("消息发送成功!");
        }else {
            System.out.println("消息发送失败!"+cause);
        }
    }

    /**
     * 消息如果没有正确发送到队列中,则会走这个方法!如果消息被正常处理,则这个方法不会走!
     * @param message
     * @param replyCode
     * @param replyText
     * @param exchange
     * @param routingKey
     */
    @Override
    public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) {
        System.out.println("消息主体: " + new String(message.getBody()));
        System.out.println("应答码: " + replyCode);
        System.out.println("描述:" + replyText);
        System.out.println("消息使用的交换器 exchange : " + exchange);
        System.out.println("消息使用的路由键 routing : " + routingKey);
    }
}

设置当前RabbitMQ的Service

@Service
public class RabbitService {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    //发送消息的方法
    //exchange交换机
    //routingKey路由
    //message消息
    public boolean sendMessage(String exchange,String routingKey,Object message) {
        rabbitTemplate.convertAndSend(exchange,routingKey,message);
        return true;
    }

}

以下一个发送者服务加上mq的配置信息

spring:
	rabbitmq:
    	host: 192.168.159.134
    	port: 5672
    	username: guest
    	password: guest
    	publisher-confirm-type: CORRELATED  #发布确认模式,消息是否被成功发送到交换机
    	publisher-returns: true
    	listener:
      		simple:
        		prefetch: 1
        		concurrency: 3
        		acknowledge-mode: manual   #消费端手动确认
//商品上下架
    @Override
    public void publish(Long skuId, Integer status) {
        if(status == 1) { //上架
            SkuInfo skuInfo = baseMapper.selectById(skuId);
            skuInfo.setPublishStatus(status);
            baseMapper.updateById(skuInfo);
            //整合mq把数据同步到es里面
            rabbitService.sendMessage(MqConst.EXCHANGE_GOODS_DIRECT,
                                      MqConst.ROUTING_GOODS_UPPER,
                                      skuId);
        } else { //下架
            SkuInfo skuInfo = baseMapper.selectById(skuId);
            skuInfo.setPublishStatus(status);
            baseMapper.updateById(skuInfo);
            //整合mq把数据同步到es里面
            rabbitService.sendMessage(MqConst.EXCHANGE_GOODS_DIRECT,
                                      MqConst.ROUTING_GOODS_LOWER,
                                      skuId);
        }
    }

一个简单的上架下架问题
选择商品上架下架发送mq消息到其他服务中,让其他服务接收

接收端

spring:
	rabbitmq:
    	host: 192.168.159.134
    	port: 5672
    	username: guest
    	password: guest
    	publisher-confirm-type: CORRELATED  #发布确认模式,消息是否被成功发送到交换机
    	publisher-returns: true
    	listener:
      		simple:
        		prefetch: 1
        		concurrency: 3
        		acknowledge-mode: manual   #消费端手动确认

同样如此配置信息

@Component
public class SkuReceiver {

    @Autowired
    private SkuService skuService;

    //商品上架
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value = MqConst.QUEUE_GOODS_UPPER,durable = "true"),
            exchange = @Exchange(value = MqConst.EXCHANGE_GOODS_DIRECT),
            key = {MqConst.ROUTING_GOODS_UPPER}
    ))
    public void upperSku(Long skuId, Message message, Channel channel) throws IOException {
        if(skuId != null) {
            //调用方法商品上架
            skuService.upperSku(skuId);
        }
        channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
    }

    //商品下架
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value = MqConst.QUEUE_GOODS_LOWER,durable = "true"),
            exchange = @Exchange(value = MqConst.EXCHANGE_GOODS_DIRECT),
            key = {MqConst.ROUTING_GOODS_LOWER}
    ))
    public void lowerSku(Long skuId,Message message,Channel channel) throws IOException {
        if(skuId != null) {
            skuService.lowerSku(skuId);
        }
        channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
    }

}

使用监听器监听mq对应的消息队列,路由,路由键是否匹配,如果匹配则成功接收消息
如果消息没有接收成功,则是手动确认没有收到。

设置ES配置

spring:
	elasticsearch:
    	rest:
      		uris: http://192.168.159.134:9200

设置ES接口,可以使用该接口设置ES的简单增删改查

public interface SkuRepository extends ElasticsearchRepository<SkuEs,Long> {}
//上架
    @Override
    public void upperSku(Long skuId) {
        //1 通过远程调用 ,根据skuid获取相关信息
        SkuInfo skuInfo = productFeignClient.getSkuInfo(skuId);
        if(skuInfo == null) {
            return;
        }
        Category category = productFeignClient.getCategory(skuInfo.getCategoryId());
        //2 获取数据封装SkuEs对象
        SkuEs skuEs = new SkuEs();
        //封装分类
        if(category != null) {
            skuEs.setCategoryId(category.getId());
            skuEs.setCategoryName(category.getName());
        }
        //封装sku信息部分
        skuEs.setId(skuInfo.getId());
        skuEs.setKeyword(skuInfo.getSkuName()+","+skuEs.getCategoryName());
        skuEs.setWareId(skuInfo.getWareId());
        skuEs.setIsNewPerson(skuInfo.getIsNewPerson());
        skuEs.setImgUrl(skuInfo.getImgUrl());
        skuEs.setTitle(skuInfo.getSkuName());
        if(skuInfo.getSkuType() == SkuType.COMMON.getCode()) {//普通商品
            skuEs.setSkuType(0);
            skuEs.setPrice(skuInfo.getPrice().doubleValue());
            skuEs.setStock(skuInfo.getStock());
            skuEs.setSale(skuInfo.getSale());
            skuEs.setPerLimit(skuInfo.getPerLimit());
        }
        //3 调用方法添加ES
        skuRepository.save(skuEs);
    }

    //下架
    @Override
    public void lowerSku(Long skuId) {
        skuRepository.deleteById(skuId);
    }

使用上架方法从Kibana查看ES数据是否加入成功

POST /skues/_search
{
  "query": {
    "match_all": {}
  }
}
{
  "took" : 11,
  "timed_out" : false,
  "_shards" : {
    "total" : 3,
    "successful" : 3,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 1,
      "relation" : "eq"
    },
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "skues",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 1.0,
        "_source" : {
          "_class" : "com.atguigu.ssyx.model.search.SkuEs",
          "id" : 1,
          "keyword" : "西红柿,新鲜蔬菜",
          "skuType" : 0,
          "isNewPerson" : 0,
          "categoryId" : 1,
          "categoryName" : "新鲜蔬菜",
          "imgUrl" : "http://47.93.148.192:9000/gmall/20210817/微信图片_2021081711240720.jpg",
          "title" : "西红柿",
          "price" : 2.2,
          "stock" : 100,
          "perLimit" : 5,
          "sale" : 0,
          "wareId" : 1,
          "hotScore" : 0
        }
      }
    ]
  }
}

成功插入数据,一个简单的MQ+ES实战

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值