Sleuth
产生链路跟踪日志A --> B --> CA的id会被当做整条链路的id
默认只有10%的日志会发到Zipkin
A, USFHSAJFGVDMJ, USFHSAJFGVDMJ ,trueB, USFHSAJFGVDMJ ,FGRJEGNTHYJN5 ,falseC, USFHSAJFGVDMJ ,GJREG98GEWU87 ,false
使用Sleuth
添加Sleuth依赖修改2,3,4,6,有自动配置类<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-sleuth</artifactId></dependency>
链路日志发送到Zipkin处理
两种方式
1.直接连接,向Zipkin提交日志
2.通过消息服务转发日志
解耦、流量削峰
通过消息服务实现步骤
1. 添加Zipkin client依赖至2.3.4.6
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-zipkin</artifactId></dependency>
2. 在06项目添加rabiitmq依赖
(2.3.4已经加过了)
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId></dependency>
3. 四个模块中,配置发送方式
rabbit(还有activemq、kafka、web发送方式)在config目录修改,再推送到远程仓库06
02.03.04
5.下载jar文件
6. 启动zipkin服务器
在jar包地址cmdjava -jar z.jar --zipkin.collector.rabbitmq.uri=amqp://admin:admin@192.168.64.140:5672
访问http://localhost:3001/order-service/u56uy454y
Rabbitmq 订单流量削峰案例
1.导入商城项目
2.修改pom.xml拖拽到idea 把springboot版本改成2.3.2RELEASE
3.右键pom.xml编辑器
4.导入sql脚本
5.yml配置查看
订单发送到rabbitmq
添加 rabbitmq依赖连接配置
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId></dependency>
server:port: 80spring:datasource:type: com.alibaba.druid.pool.DruidDataSourcedriver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://127.0.0.1:3306/pd_store?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8username: rootpassword: rootrabbitmq:host: 192.168.64.140port: 5672username: adminpassword: adminvirtual-host: /mybatis:mapperLocations: classpath:com.pd.mapper/*.xmllogging:level:cn.tedu.ssm.mapper: debugresources: # 指定静态资源的路径static-locations: classpath:/cache-period: 0
在启动类(或者自定义自动配置类)中设置队列的参数:orderQueue,true,false,false
package com.pd;import org.mybatis.spring.annotation.MapperScan;import org.springframework.amqp.core.Queue;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.context.annotation.Bean;@SpringBootApplication@MapperScan("com.pd.mapper")public class RunPdAPP{public static void main(String[] args) {SpringApplication.run(RunPdAPP.class, args);}//新建SpringQueue实例 用来封装队列的参数//rabbitmq的自动配置类会自动发现这个queue实例 根据参数创建队列@Beanpublic Queue orderQueue(){//持久 非独占 不自动删除return new Queue("orderQueue",true,false,false);}}
修改OrderserviceImpl
注入对象:AmqpTemplate 用来封装消息发送的API工具
发送消息
订单的消费者
1.rabbitmq基础配置,准备队列参数
2.新建消费者类:OrderConsumer
3.用注解配置接收消息
4.收到的订单通过原来的业务代码,存储到数据库
package com.pd.service.impl;import java.util.ArrayList;import java.util.Date;import java.util.List;import java.util.Random;import org.springframework.amqp.core.AmqpTemplate;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import com.pd.mapper.PdCartItemMapper;import com.pd.mapper.PdItemMapper;import com.pd.mapper.PdItemParamItemMapper;import com.pd.mapper.PdOrderItemMapper;import com.pd.mapper.PdOrderMapper;import com.pd.mapper.PdShippingMapper;import com.pd.pojo.PdCartItem;import com.pd.pojo.PdCartItemExample;import com.pd.pojo.PdItem;import com.pd.pojo.PdItemParamItem;import com.pd.pojo.PdItemParamItemExample;import com.pd.pojo.PdOrder;import com.pd.pojo.PdOrderExample;import com.pd.pojo.PdOrderItem;import com.pd.pojo.PdOrderItemExample;import com.pd.pojo.PdShipping;import com.pd.pojo.ItemVO;import com.pd.pojo.OrderVO;import com.pd.pojo.paramData.PdItemParamData;import com.pd.pojo.paramData.Params;import com.github.pagehelper.PageHelper;import com.github.pagehelper.PageInfo;import mon.utils.JsonUtils;import com.pd.service.OrderService;@Servicepublic class OrderServiceImpl implements OrderService {@AutowiredPdOrderMapper pdOrderMapper;@AutowiredPdCartItemMapper pdCartItemMapper;@AutowiredPdItemMapper pdItemMapper;@AutowiredPdItemParamItemMapper pdItemParamItemMapper;@AutowiredPdShippingMapper pdShippingMapper;@AutowiredPdOrderItemMapper pdOrderItemMapper;//@Autowired//private AmqpTemplate amqpTemplate;public String saveOrder(PdOrder pdOrder) throws Exception {//String orderId = generateId();//生成订单id//pdOrder.setOrderId(orderId);//订单id放入订单对象////转换并发送 先把数据转成byte数组在发送//amqpTemplate.convertAndSend("orderQueue",pdOrder);String orderId =pdOrder.getOrderId();PdShipping pdShipping = pdShippingMapper.selectByPrimaryKey(pdOrder.getAddId());pdOrder.setShippingName(pdShipping.getReceiverName());pdOrder.setShippingCode(pdShipping.getReceiverAddress());pdOrder.setStatus(1);//pdOrder.setPaymentType(1);pdOrder.setPostFee(10D);pdOrder.setCreateTime(new Date());double payment = 0;List<ItemVO> itemVOs = selectCartItemByUseridAndItemIds(pdOrder.getUserId(), pdOrder.getItemIdList());for (ItemVO itemVO : itemVOs) {PdOrderItem pdOrderItem = new PdOrderItem();String id = generateId();//String id="2";pdOrderItem.setId(id);pdOrderItem.setOrderId(orderId);pdOrderItem.setItemId("" + itemVO.getPdItem().getId());pdOrderItem.setTitle(itemVO.getPdItem().getTitle());pdOrderItem.setPrice(itemVO.getPdItem().getPrice());pdOrderItem.setNum(itemVO.getPdCartItem().getNum());payment = payment + itemVO.getPdCartItem().getNum() * itemVO.getPdItem().getPrice();pdOrderItemMapper.insert(pdOrderItem);}pdOrder.setPayment(payment);pdOrderMapper.insert(pdOrder);return orderId;}public synchronized String generateId() {Random random = new Random();int number = random.nextInt(9000000) + 1000000;return "" + System.currentTimeMillis() + number;}public List<ItemVO> selectCartItemByUseridAndItemIds(Long userId, List<Long> itemIds) throws Exception {PdCartItemExample cartItemExample = new PdCartItemExample();PdCartItemExample.Criteria criteria = cartItemExample.or();criteria.andUserIdEqualTo(userId);criteria.andItemIdIn(itemIds);criteria.andStatusEqualTo(1);List<PdCartItem> cartItems = pdCartItemMapper.selectByExample(cartItemExample);List<ItemVO> itemVOs = new ArrayList<>();for (PdCartItem pdCartItem : cartItems) {Long itemId = pdCartItem.getItemId();PdItem pdItem = pdItemMapper.selectByPrimaryKey(itemId);PdItemParamItemExample paramExample = new PdItemParamItemExample();PdItemParamItemExample.Criteria paramCriteria = paramExample.or();paramCriteria.andItemIdEqualTo(itemId);List<PdItemParamItem> items = pdItemParamItemMapper.selectByExampleWithBLOBs(paramExample);List<Params> paramsList = new ArrayList<>();if (items != null && items.size() >= 1) {PdItemParamItem item = items.get(0);String paramData = item.getParamData();List<PdItemParamData> list = JsonUtils.jsonToList(paramData, PdItemParamData.class);paramsList = list.get(0).getParams();}ItemVO itemVO = new ItemVO();itemVO.setPdCartItem(pdCartItem);itemVO.setPdItem(pdItem);itemVO.setParamsList(paramsList);itemVOs.add(itemVO);}return itemVOs;}public PdOrder selectById(String orderId) throws Exception {PdOrder pdOrder = pdOrderMapper.selectByPrimaryKey(orderId);return pdOrder;}public List<OrderVO> selectByUserIdAndStatus(Long userId, int status) throws Exception {//where user_id=14 and status!=9 order by create_time descPdOrderExample orderExample=new PdOrderExample();PdOrderExample.Criteria criteria=orderExample.or();criteria.andUserIdEqualTo(userId);criteria.andStatusNotEqualTo(9);//9閿熸枻鎷风ず閿熸枻鎷烽敓鏂ゆ嫹閿熺獤鎾呮嫹鍒犻敓鏂ゆ嫹if (status!=0){criteria.andStatusEqualTo(status);}orderExample.setOrderByClause("create_time desc");List<PdOrder> orders=pdOrderMapper.selectByExample(orderExample);List<OrderVO> orderVOs=new ArrayList<>();for (PdOrder pdOrder:orders){//from pd_order_item where order_id=30;PdOrderItemExample itemExample=new PdOrderItemExample();PdOrderItemExample.Criteria itemCriteria=itemExample.or();itemCriteria.andOrderIdEqualTo(pdOrder.getOrderId());List<PdOrderItem> orderItems=pdOrderItemMapper.selectByExample(itemExample);for (PdOrderItem pdOrderItem:orderItems){//3.3.1 example,criteriaPdItemParamItemExample example=new PdItemParamItemExample();PdItemParamItemExample.Criteria paramCriteria=example.or();long itemId=Long.parseLong(pdOrderItem.getItemId());paramCriteria.andItemIdEqualTo(itemId);List<PdItemParamItem> paramItemList=pdItemParamItemMapper.selectByExampleWithBLOBs(example);List<Params> paramsList=new ArrayList<>();if (paramItemList.size()>=1){//3.3.3 鍙杙aram_dataPdItemParamItem pdItemParamItem=paramItemList.get(0);String paramData=pdItemParamItem.getParamData();List<PdItemParamData> paramDataList=JsonUtils.jsonToList(paramData, PdItemParamData.class);paramsList=paramDataList.get(0).getParams();}pdOrderItem.setParamsList(paramsList);}OrderVO orderVO=new OrderVO();orderVO.setPdOrder(pdOrder);orderVO.setPdOrderItems(orderItems);orderVOs.add(orderVO);}return orderVOs;}public PdOrder findOrderByOrderid(String orderId) throws Exception {PdOrder pdOrder=pdOrderMapper.selectByPrimaryKey(orderId);return pdOrder;}@Overridepublic int updateOrderStatus(String orderId, int status) throws Exception {//update pd_order set status=8 where orderId=100PdOrder pdOrder=new PdOrder();pdOrder.setStatus(status);PdOrderExample example=new PdOrderExample();PdOrderExample.Criteria criteria=example.or();criteria.andOrderIdEqualTo(orderId);int row=pdOrderMapper.updateByExampleSelective(pdOrder, example); return row;}}
订单的流量削峰解释:购物系统产生的定展,不直接存储到数据库,而是发送到rabbitmq
后台消费者模块接收订单,再向数据库存储,短时间瞬间产生大量订单并发送存储,变成顺序存储
使用模式为简单模式,可以该称工作模式