某马2024SpringCloud微服务开发与实战 bug记录与微服务知识拆解(MybatisPlus、Docker、MQ、ES、Redis)第三章

CSDN 2024-08-18 13:07:06 阅读 80

你好,我是Qiuner. 为帮助别人少走弯路和记录自己编程学习过程而写博客

这是我的 github https://github.com/Qiuner ⭐️

gitee https://gitee.com/Qiuner 🌹

如果本篇文章帮到了你 不妨点个赞吧~ 我会很高兴的 😄 (^ ~ ^)

想看更多 那就点个关注吧 我会尽力带来有趣的内容 😎

这篇中规中举,有不少bug记录与方便您复制的代码,相信一定能节省学习时间同时达到更好的效果本博客要与原文档搭配使用 day03-微服务01 - 飞书云文档 (feishu.cn)本来这个系列博客应该五月份出完,但有各种事情。所幸都安然度过 也不敢再标题写全网最快了 只写全网最全 😎

本篇文章的重点是 作业 trade客户端拆分与相应OpenFeign编写思路,您一看就能明白 我比老师讲的更详细 看完不会找我 就是这么自信 😎

封面颜色是 槐花黄绿

2024最新SpringCloud微服务开发与实战,java黑马商城项目微服务实战开发(涵盖MybatisPlus、Docker、MQ、ES、Redis高级等)Day 3

文章目录

2024最新SpringCloud微服务开发与实战,java黑马商城项目微服务实战开发(涵盖MybatisPlus、Docker、MQ、ES、Redis高级等)Day 3win 11 VMware workstations b不可恢复的错误(vcpu-2)CentOS7显示异常 显示为bash-4.2#数据库连接异常处理项目实际生产环境与使用环境的不同设计用户登录报错单体架构认识项目中使用到的jmeter微服务拆分原则

拆分案例 拆分商品服务在微服务项目中新建一个模块时 你需要做些什么启动类方面配置文件方面

拆分案例 拆分购物车服务 与IDEA自动导包设置远程调用Spring不推荐使用@Autowired注解Nacos注册中心报错NMI watchdog: BUG: soft lockup - CPU#1 stuck for 22s! [containerd:1062]

服务注册依赖导入报错问题 [ERROR] 'dependencies.dependency.groupId' for com.heima':hm-service:jar with value 'com.heima'' does not match a valid id pattern. @ line 33, column 22OpenFeignOpenFeign引入四步走第一步:在pom文件中新增这些东西第二步:添加开关第三步:写客户端与实际代码第四步:使用

OpenFeign优化OpenFeign使用优化优化方式一:优化方式二:

OpenFeign日志第一步:写一个返回日志级别方法第二步:使用这个日志级别

作业:trade客户端拆分思路一:分析二:定位代码三:开始创建client1 商品id获取2 购物车清空3 扣减缓存3.1 最终结果

四:非拆分配置

win 11 VMware workstations b不可恢复的错误(vcpu-2)

image-20240616085118733

找一个新版的VM进行下载这个问题就能解决,博主之前是16pro

image-20240519171509675

这里按照视频及文档操作即可 ‌‍‬‬‌⁠‌‌‍‍‌‍‌‌⁠⁠‬‍‍‍day03-微服务01 - 飞书云文档 (feishu.cn)

<code>alias rm='rm -i'code>

alias cp='cp -i'code>

alias mv='mv -i'code>

alias dps='docker ps --format "table { {.ID}}\t{ {.Image}}\t{ {.Ports}}\t{ {.Status}}\t{ {.Names}}"'code>

alias dis='docker images'code>

# Source global definitions

if [ -f /etc/bashrc ]; then

. /etc/bashrc

fi

官方文档的这个是错的,写错了一部分的内容

CentOS7显示异常 显示为bash-4.2#

image-20240522155232377

输入一行

<code>source /root/.bashrc

就能实现命令符的变化

数据库连接异常处理

在这里 可能会看见以下报错注意 您可在这一步前确认自己的mysql服务是否已启动(是否能连上本地的数据库)

image-20240527150206696

解决方式

先看能不能ping通

image-20240527150246477

如果能ping通而连接不了,那可能是docker服务没有启动先查看全部容器,然后使用docker start mysql即可

image-20240527150335300

image-20240527150350988

image-20240527150451273

再次连接发现成功连接上

项目实际生产环境与使用环境的不同设计

在这里插入图片描述

image-20240527164456736

通过这种方式就可以设置启动项目的方式

image-20240526153728832

一个未登入导致权限不足的bug,这个是正常的

image-20240526153823535

这里老师使用黑框框启动 但其实可以不用 点击也行 以下命令会关闭所有的nginx进程

<code> taskkill /f /t /im nginx.exe

image-20240527164953709

用户登录报错

image-20240527165645092

将JDK改为11即可

image-20240527165940809

image-20240527165944066

单体架构认识

image-20240527172132665

项目中使用到的jmeter

这里要用到jmeter进行测试 推荐看博主的另一篇文章

软件测试之 性能测试 性能测试基础指标 Loadrunner、Jmeter等工具-CSDN博客

如果不想看 那我简单地做个介绍

image-20240527171311801

image-20240527172358434

image-20240527172808918

image-20240527203643564

image-20240527203659497

https://spring.io/projects/spring-cloud 这是SpringCloud的官网 可以在这里看到很多组件

image-20240527205027094

P40这里做的非常好 从一个商城项目的视角来切入项目 教你怎么读别人的代码

image-20240527214256281

微服务拆分原则

image-20240527214515089

image-20240527214723279

image-20240527215105138

拆分案例 拆分商品服务

下面是修改的配置文件

作者名我改成了Qiuner,你可以改成你自己喜欢的名称

<code>server:

port: 8081

spring:

application:

name: item-service

profiles:

active: dev

datasource:

url: jdbc:mysql://${hm.db.host}:3306/hm-item?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai

driver-class-name: com.mysql.cj.jdbc.Driver

username: root

password: ${hm.db.pw}

mybatis-plus:

configuration:

default-enum-type-handler: com.baomidou.mybatisplus.core.handlers.MybatisEnumTypeHandler

global-config:

db-config:

update-strategy: not_null

id-type: auto

logging:

level:

com.hmall: debug

pattern:

dateformat: HH:mm:ss:SSS

file:

path: "logs/${spring.application.name}"

knife4j:

enable: true

openapi:

title: 黑马商城商品管理接口文档

description: "黑马商城商品管理接口文档"

email: zhanghuyi@itcast.cn

concat: Qiuner

url: https://www.itcast.cn

version: v1.0.0

group:

default:

group-name: default

api-rule: package

api-rule-resources:

- com.hmall.item.controller

这里的拷贝案例直接看视频吧,用文字表达出来比较长微服务01-08.微服务拆分-拆分商品服务_哔哩哔哩_bilibili

视频里的 服务拆分思路我认为是值得学习的,先复制domain层的东西(vo、dto)什么的

然后复制mapper、Service、control

image-20240531113247112

这里服务配置完后就可以运行了 运行起来时记得访问下8081(拆分出来的子模块)端口号后面加上/doc.html 来访问接口文档

在微服务项目中新建一个模块时 你需要做些什么

启动类方面

image-20240529105836498

image-20240529110112340

修改成这样 那么启动类就配置完毕了

配置文件方面

image-20240529215203289

这里配置文件可以看我的另一篇文章: 微服务配置文件详解 对配置文件做了个大致的介绍,通俗易懂(还没写 之后写了会放链接的

拆分案例 拆分购物车服务 与IDEA自动导包设置

和之前一样的 就是视频中的idea配置了自动导入包可以尝试自己进行服务拆分

image-20240531204445263

如果此处运行起来报 500 的错 先检查自己docker服务有没有启动起来 然后看自己是不是写hm-cart 像博主就写card了

远程调用

image-20240531205451245

<code> @Bean

public RestTemplate restTemplate() {

return new RestTemplate();

}

private void handleCartItems(List<CartVO> vos) {

// TODO 1.获取商品id

Set<Long> itemIds = vos.stream().map(CartVO::getItemId).collect(Collectors.toSet());

// 2.查询商品 原代码

// List<ItemDTO> items = itemService.queryItemByIds(itemIds);

// 这里查询商品不再从本地数据库中查询 而是发送请求 让远程服务器接受来查询

// 使用RestTemplate发送请求

ResponseEntity<List<ItemDTO>> response= restTemplate.exchange(

"http://localhost:8081/items?ids={ids}",

HttpMethod.GET,

null,

new ParameterizedTypeReference<List<ItemDTO>>() {

},

Map.of("ids",CollUtils.join(itemIds,","))

);

// 解析响应

if (!response.getStatusCode().is2xxSuccessful()){

// 查询失败

return;

}

//这里做转换

List<ItemDTO> items =response.getBody();

if (CollUtils.isEmpty(items)) {

return;

}

// 3.转为 id 到 item的map

Map<Long, ItemDTO> itemMap = items.stream().collect(Collectors.toMap(ItemDTO::getId, Function.identity()));

// 4.写入vo

for (CartVO v : vos) {

ItemDTO item = itemMap.get(v.getItemId());

if (item == null) {

continue;

}

v.setNewPrice(item.getPrice());

v.setStatus(item.getStatus());

v.setStock(item.getStock());

}

}

image-20240531220357395

要点就是看服务有没有启动、使用了什么配置文件的数据库进行运行

Spring不推荐使用@Autowired注解

image-20240617085722366

这里有很多原因,比如依赖注入顺序,使用构造函数能保证在对象创建时已经被注入,而使用字段注入未必还有对象不可变性、依赖倒装原则,减少反射等等

image-20240617090409482

使用构造函数会出现成员变量很多构造函数需要写很多的情况使用RequiredArgsConstructor 注解 加上 final来进行保证初始化

image-20240601102250438

Nacos注册中心

image-20240601102426342

面临可以有多台服务器提供服务,这个时候服务地址不知道要填什么。填一个定死,出故障了那整个业务就崩溃了

image-20240601102757726

image-20240617095131369

图中 当 8083没有进行心跳续约的时候,注册中心就会剔除掉原本有三个服务提供者,8081,8082,8083

image-20240601102842793

报错NMI watchdog: BUG: soft lockup - CPU#1 stuck for 22s! [containerd:1062]

看看你虚拟机分配的配置是不是不够,博主就是虚拟机配置不够,然后跑不起来(老师弄得8G是够的,博主没开那么大而已)

http://192.168.197.130:8848/nacos

将项目ip地址换成你自己的

image-20240617100622205

看到这个页面就是部署成功了

服务注册

image-20240617101840194

image-20240617102415860

这里的discoveryClient是一个顶级接口,所有的服务注册中心都实现了这个接口

instances.get这里是选择负载均衡算法

依赖导入报错问题 [ERROR] ‘dependencies.dependency.groupId’ for com.heima’:hm-service:jar with value ‘com.heima’’ does not match a valid id pattern. @ line 33, column 22

image-20240617162204418

解决方案很简单,这是没有在本地找到项目依赖,将要关联的弄到本地就可以了

image-20240617162301444

image-20240617162359758

运行 成功解决

<code> mvn clean install

OpenFeign

image-20240617111401551

image-20240617111449451

原本想要在两个服务中调取请求需要做上面这么多事

image-20240617111822191

image-20240617143823185

现在只需要这几行代码

OpenFeign引入四步走

第一步:在pom文件中新增这些东西

<code> <!--openFeign-->

<dependency>

<groupId>org.springframework.cloud</groupId>

<artifactId>spring-cloud-starter-openfeign</artifactId>

</dependency>

<!--负载均衡器-->

<dependency>

<groupId>org.springframework.cloud</groupId>

<artifactId>spring-cloud-starter-loadbalancer</artifactId>

</dependency>

第二步:添加开关

image-20240617112354917

第三步:写客户端与实际代码

image-20240617112652887

第四步:使用

image-20240617113037384

OpenFeign优化

原本没有连接池 现在使用链接池,毫无疑问,使用链接池对性能的优化是巨大的

image-20240617144736688

image-20240617144804715

day03-微服务01 - 飞书云文档 (feishu.cn)

OpenFeign使用优化

优化方式一:

image-20240617152648526

优化方式二:

image-20240617152759279

image-20240617152252831

需要在启动类的@Endble注解上加上扫描地址

OpenFeign日志

image-20240617153239213

image-20240617153429116

第一步:写一个返回日志级别方法

image-20240617153814867

第二步:使用这个日志级别

image-20240617154033462

image-20240617154317887

上面标志表示 成功了

image-20240617154237811

作业:trade客户端拆分思路

一:分析

原本cart-service需要item-service的购物车中数据,所以创建了item的openfeign客户端,而trade需要商品id(item),清理购物车库存(cart)这两个的数据,所以需要这两个的客户端

二:定位代码

在这里插入图片描述

经过如上图以后的分析,就能明确到底要做什么

三:开始创建client

1 商品id获取

<code>@FeignClient("item-service")

public interface ItemClient {

@GetMapping("/items")

List<ItemDTO> queryItemByIds(@RequestParam("ids") Collection<Long> ids);

}

类部分

@FeignClient("item-service"):定义一个 Feign 客户端,服务名称为 item-service,这个名称应该与服务注册中心(如 Nacos)中的服务名称一致。

public interface ItemClient:声明一个接口,表示这个接口将包含远程服务的 API 方法。

方法部分

@GetMapping("/items"):定义一个 GET 请求,映射到 item-service 服务的 /items 端点。

List<ItemDTO> queryItemByIds(@RequestParam("ids") Collection<Long> ids);

方法名称 queryItemByIds 表示查询多个商品 ID 的信息。参数 @RequestParam("ids") Collection<Long> ids:使用 @RequestParam 注解表示这是一个查询参数,参数名称为 ids,类型是 Collection<Long>。返回类型 List<ItemDTO>:方法返回一个 ItemDTO 对象的列表。

这里可以看出,需求是一样的,因此直接用

image-20240617215346510

2 购物车清空

一:阅读原本购物车代码

image-20240617220327926

发现有一个批量删除的代码,那我们就用这个了

本方法没有返回值,所以得出的client代码如下

<code>package com.hmall.api.client;

import org.springframework.cloud.openfeign.FeignClient;

import org.springframework.web.bind.annotation.GetMapping;

import org.springframework.web.bind.annotation.RequestParam;

import java.util.Collection;

@FeignClient("cart-service")

public interface CartClient {

@GetMapping("/carts")

void deleteCartItemByIds(@RequestParam("ids") Collection<Long> ids);

}

cartClient.deleteCartItemByIds(itemIds);

3 扣减缓存

image-20240617221307285

发现扣减缓存代码

3.1 最终结果

在这里插入图片描述

CartClient

<code>package com.hmall.api.client;

import org.springframework.cloud.openfeign.FeignClient;

import org.springframework.web.bind.annotation.GetMapping;

import org.springframework.web.bind.annotation.RequestParam;

import java.util.Collection;

@FeignClient("cart-service")

public interface CartClient {

@GetMapping("/carts")

void deleteCartItemByIds(@RequestParam("ids") Collection<Long> ids);

}

ItemClient

package com.hmall.api.client;

import com.hmall.api.dto.ItemDTO;

import com.hmall.api.dto.OrderDetailDTO;

import org.springframework.cloud.openfeign.FeignClient;

import org.springframework.web.bind.annotation.GetMapping;

import org.springframework.web.bind.annotation.PutMapping;

import org.springframework.web.bind.annotation.RequestBody;

import org.springframework.web.bind.annotation.RequestParam;

import java.util.Collection;

import java.util.List;

@FeignClient("item-service")

public interface ItemClient {

@GetMapping("/items")

List<ItemDTO> queryItemByIds(@RequestParam("ids") Collection<Long> ids);

@PutMapping("/items/stock/deduct")

void deductStock(@RequestBody List<OrderDetailDTO> items);

}

四:非拆分配置

image-20240617222858112

image-20240617222909108

分别是扫描和,和依赖使用其他都一样了,相信你能知道怎么使用



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。