当前位置: 首页 > news >正文

黑马商城项目(三)微服务

一、单体架构

 测试高并发软件

二、微服务

 三、SpringCloud

四、微服务拆分

黑马商城模块:

服务拆分原则:

拆分服务:

独立project:

maven聚合:

拆分案例:

远程调用:

package com.hmall.cart.config;import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;@org.springframework.context.annotation.Configuration
public class Configuration {@Beanpublic RestTemplate restTemplate(){return new RestTemplate();}
}
@Service
@RequiredArgsConstructor  //自动生成必备参数的构造函数
public class CartServiceImpl extends ServiceImpl<CartMapper, Cart> implements ICartService {/*private final IItemService itemService;*/// @Autowired  Spring不建议使用@Autowiredprivate final RestTemplate restTemplate;/*Spring建议使用构造函数注入*/
/*    public CartServiceImpl(RestTemplate restTemplate){this.restTemplate=restTemplate;}*/
}
 private void handleCartItems(List<CartVO> vos) {// 1.获取商品idSet<Long> itemIds = vos.stream().map(CartVO::getItemId).collect(Collectors.toSet());// 2.查询商品//List<ItemDTO> items = itemService.queryItemByIds(itemIds);//2.1 利用RestTemplate发送http请求,得到http响应ResponseEntity<List<ItemDTO>> response = restTemplate.exchange("http://localhost:8081/items?ids={ids}",HttpMethod.GET,null,new ParameterizedTypeReference<List<ItemDTO>>() {}, //利用反射拿到这个对象上的泛型Map.of("ids", CollUtil.join(itemIds, ",")));//2.2解析响应if(!response.getStatusCode().is2xxSuccessful()){//查询失败 直接结束return;}List<ItemDTO> items = response.getBody();if (CollUtils.isEmpty(items)) {return;}// 3.转为 id 到 item的mapMap<Long, ItemDTO> itemMap = items.stream().collect(Collectors.toMap(ItemDTO::getId, Function.identity()));// 4.写入vofor (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());}}

逻辑:

五、服务治理

上文提到的远程调用带来的问题:

注册中心:

Nacos注册中心:

docker run -d \
--name nacos \
--env-file ./nacos/custom.env \
-p 8848:8848 \
-p 9848:9848 \
-p 9849:9849 \
--restart=always \
nacos/nacos-server:v2.1.0-slim

服务注册:

多实例部署:

服务发现:

六、OpenFeign

快速入门:

———————————————————————————————————————————

———————————————————————————————————————————

请求路径参数通过SpringMVC注解@GetMapping以及@RequestParam完成替代

请求参数通过调用该接口方法时传递的参数完成替代

返回值类型通过该接口定义的抽象方法的返回值类型完成替代

从而实现整体替代,简化代码

package com.hmall.cart.client;import com.hmall.cart.domain.dto.ItemDTO;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
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);
}
    private final ItemClient itemClient;    //自动注入private void handleCartItems(List<CartVO> vos) {// 1.获取商品idSet<Long> itemIds = vos.stream().map(CartVO::getItemId).collect(Collectors.toSet());// 2.查询商品//2.1 根据服务名称获取服务的实例列表/*   List<ServiceInstance> instances = discoveryClient.getInstances("item-service");if(CollUtil.isEmpty(instances)){//判断为空 直接结束return;}//2.2 手写负载均衡,从实例列表中挑选一个实例ServiceInstance instance = instances.get(RandomUtil.randomInt(0, instances.size()));URI uri = instance.getUri(); //主机地址 http://localhost:8081//List<ItemDTO> items = itemService.queryItemByIds(itemIds);//2.3 利用RestTemplate发送http请求,得到http响应ResponseEntity<List<ItemDTO>> response = restTemplate.exchange(uri+"/items?ids={ids}",HttpMethod.GET,null,new ParameterizedTypeReference<List<ItemDTO>>() {}, //利用反射拿到这个对象上的泛型Map.of("ids", CollUtil.join(itemIds, ",")));//2.4解析响应if(!response.getStatusCode().is2xxSuccessful()){//查询失败 直接结束return;}List<ItemDTO> items = response.getBody();*/List<ItemDTO> items = itemClient.queryItemByIds(itemIds);if (CollUtils.isEmpty(items)) {return;}// 3.转为 id 到 item的mapMap<Long, ItemDTO> itemMap = items.stream().collect(Collectors.toMap(ItemDTO::getId, Function.identity()));// 4.写入vofor (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());}}

底层原理:

代码中通过 itemClient 对象来调用接口方法时,实际上它是一个动态代理对象。

动态代理对象底层逻辑都是由 InvocationHandler 实现

这里的 FeignInvocationHandler  ReflectiveFeign 的一个内部类,实现了 InvocationHandler 接口,   InvocationHandler 接口中的 invoke 方法就是起到了代理的作用 : 所有的被代理对象中的所有业务(方法) 都会通过 invoke 方法实现代理,除了一些基本方法(比如 equals, hashCode ,toString

InvocationHandler 接口的实现类 FeignInvocationHandler 中重写对应 invoke  从而实现代理的方法如下:

最后调用对应的方法发送请求(Client

 

连接池:

OpenFeign底层发送请求使用的是 Client

OpenFeign整合并使用连接池步骤:

最佳实践:

拆分的最佳方式:

方法一:

方法二: 

按照第二种方法实践:

日志输出:

七、服务拆分作业

相关文章:

  • Flutter 常用命令
  • 集成学习基础应用实践
  • [王阳明代数讲义]晏殊几何匹配知识图谱初步
  • 顺序表和链表,时间和空间复杂度--数据结构初阶(1)(C/C++)
  • 第一节:Vben Admin 最新 v5.0初体验
  • 视频监控EasyCVR视频汇聚平台接入海康监控摄像头如何配置http监听功能?
  • 华清远见STM32F103智能小车重磅上线!循迹避障红外遥控WiFi远程控制,0基础小白从入门到单片机软硬件项目实战!
  • 【hadoop】master一键启动hadoop集群(高可用)
  • 电力行业在保障用电安全方面正积极采用先进的物联网技术
  • 量子通信应用:量子安全物联网(三)协议融合
  • FlinkCDC初始化时报错“IllegalArgumentException: Unexpected input: “异常定位与原理分析
  • 【2025“华中杯”大学生数学建模挑战赛】C题:就业状态分析与预测 详细解题思路
  • el-input 限制只能输入负数、正数或2位小数的数值
  • 详解JVM的底层原理
  • JVM 什么是逃逸分析?它有哪些优化手段?
  • 前端根据后端返回的excel二进制文件流进行导出下载
  • 内存编码手册:整数与浮点数的二进制世界
  • OSCP - Proving Grounds - DriftingBlues6
  • 鸿蒙智行多款重磅新品发布,开启智慧出行新篇章
  • 【DVWA 靶场通关】 File Inclusion(文件包含漏洞)
  • 深圳南澳码头工程环评将再次举行听证会,项目与珊瑚最近距离仅80米
  • 美联储主席:供应冲击或更频繁,将重新评估货币政策方法中的通胀和就业因素
  • 湃书单|澎湃新闻编辑们在读的14本书:后工作时代
  • 女孩患异食癖爱吃头发,一年后腹痛入院体内惊现“头发巨石”
  • 占地57亩的“潮汕豪宅”面临强制拆除:曾被实施没收,8年间举行5次听证会
  • 体坛联播|博洛尼亚时隔51年再夺意杯,皇马逆转马洛卡