【Spring Cloud】微服务的简单搭建

文章目录

  • 🍃前言
  • 🎄开发环境安装
  • 🌳服务拆分的原则
    • 🚩单一职责原则
    • 🚩服务自治
    • 🚩单向依赖
  • 🍀搭建案例介绍
  • 🌴数据准备
  • 🎋工程搭建
    • 🚩构建父子工程
      • 🎈创建父工程
      • 🎈创建⼦项目-订单服务与商品服务
      • 🎈完善订单服务
      • 🎈完善商品服务
    • 🚩远程调用
      • 🎈调用需求
      • 🎈实现
      • 🎈测试
  • 🌲项目存在问题
  • ⭕总结

🍃前言

Spring Cloud 提供了⼀些可以让开发⼈员快速构建分布式服务的⼯具,⽐如配置管理, 服务发现,,熔断,智能路由等。他们可以在任何分布式环境中很好的⼯作。

简单来说,Spring Cloud 就是分布式微服务架构的⼀站式解决⽅案,是微服务架构落地的多种技术的集合

既然Spring Cloud是用来解决微服务所带来的问题。那我们接下来就先搭建一个简单的微服务。

本篇内容主要非为以下两点

  1. 开发环境安装
  2. 项⽬搭建

🎄开发环境安装

首先 JDK 版本的选择方面

我们选择 JDK17 ,选择 JDK17 的原因,是因为Spring Cloud 是基于 SpringBoot 进⾏开发的, SpringBoot 3.X以下的版本, Spring官⽅已不再进⾏维护(还可以继续使⽤), SpringBoot 3.X的版本, 使⽤的JDK版本基本为JDK17. 鉴于JDK21是 2023.09⽉发布的, 很多功能还没有在⽣产环境验证, 所以选择使⽤JDK17。

数据库方面,我们选择MySQL

🌳服务拆分的原则

微服务应用开发的第一步, 就是服务拆分.拆分后才能进行"各自开发”

微服务的拆分原则主要为以下三个原则:

  1. 单⼀职责原则

  2. 服务⾃治

  3. 单向依赖

🚩单一职责原则

单⼀职责原则原本是⾯向对象设计中的⼀个基本原则,它指的是⼀个类应该专注于单⼀功能。不要存在多于⼀个导致类变更的原因

在微服务架构中,⼀个微服务也应该只负责⼀个功能或业务领域,每个服务应该有清晰的定义和边界,只关注⾃⼰的特定业务领域

以电商平台为例,拆分为以下服务
在这里插入图片描述

🚩服务自治

服务⾃治是指每个微服务都应该具备⾼度⾃治的能⼒,即每个服务要能做到独⽴开发,独⽴测试,独⽴构建,独⽴部署,独⽴运⾏.

以上⾯的电商系统为例,每⼀个微服务应该有⾃⼰的存储,配置,在进⾏开发,构建,部署,运⾏和测试时,并不需要过多关注其他微服务的状态和数据

在这里插入图片描述

🚩单向依赖

微服务之间需要做到单向依赖, 严禁循环依赖, 双向依赖
循环依赖:A -> B -> C ->A
双向依赖: A -> B, B -> A

在这里插入图片描述

🍀搭建案例介绍

⼀个完整的电商系统是庞⼤的,搭建微服务困难较大,这里我们实现一的简单的微服务,其中的一部分,以订单列表为例:

大致可拆分为以下两个服务:

  1. 订单服务: 提供订单ID, 获取订单详细信息

  2. 商品服务: 根据商品ID, 返回商品详细信息

在这里插入图片描述

🌴数据准备

-- 建cloud_order库
create database if not exists cloud_order charset utf8mb4;
-- 订单表
DROP TABLE IF EXISTS order_detail;
CREATE TABLE order_detail (
	`id` INT NOT NULL AUTO_INCREMENT COMMENT '订单id',
	`user_id` BIGINT ( 20 ) NOT NULL COMMENT '⽤⼾ID',
	`product_id` BIGINT ( 20 ) NULL COMMENT '产品id',
	`num` INT ( 10 ) NULL DEFAULT 0 COMMENT '下单数量',
	`price` BIGINT ( 20 ) NOT NULL COMMENT '实付款',
	`delete_flag` TINYINT ( 4 ) NULL DEFAULT 0,
	`create_time` DATETIME DEFAULT now(),
	`update_time` DATETIME DEFAULT now(),
PRIMARY KEY ( id )) ENGINE = INNODB DEFAULT CHARACTER
SET = utf8mb4 COMMENT = '订单表';
-- 数据初始化
insert into order_detail (user_id,product_id,num,price)
values
(2001, 1001,1,99), (2002, 1002,1,30), (2001, 1003,1,40),
(2003, 1004,3,58), (2004, 1005,7,85), (2005, 1006,7,94);

-- 建cloud_product库
create database if not exists cloud_product charset utf8mb4;
-- 产品表
DROP TABLE IF EXISTS product_detail;
CREATE TABLE product_detail (
	`id` INT NOT NULL AUTO_INCREMENT COMMENT '产品id',
	`product_name` varchar ( 128 ) NULL COMMENT '产品名称',
	`product_price` BIGINT ( 20 ) NOT NULL COMMENT '产品价格',
	`state` TINYINT ( 4 ) NULL DEFAULT 0 COMMENT '产品状态 0-有效 1-下架',
	`create_time` DATETIME DEFAULT now(),
	`update_time` DATETIME DEFAULT now(),
PRIMARY KEY ( id )) ENGINE = INNODB DEFAULT CHARACTER
SET = utf8mb4 COMMENT = '产品表';
-- 数据初始化
insert into product_detail (id, product_name,product_price,state)
values
(1001,"T恤", 101, 0), (1002, "短袖",30, 0), (1003, "短裤",44, 0),
(1004, "卫⾐",58, 0), (1005, "⻢甲",98, 0),(1006,"⽻绒服", 101, 0),
(1007, "冲锋⾐",30, 0), (1008, "袜⼦",44, 0), (1009, "鞋⼦",58, 0),
(10010, "⽑⾐",98, 0)

🎋工程搭建

🚩构建父子工程

🎈创建父工程

  1. 创建⼀个空的Maven项⽬,删除所有代码,只保留pom.xml

在这里插入图片描述

目录结构如下:

在这里插入图片描述

  1. 完善pom⽂件

使⽤properties来进⾏版本号的统⼀管理,使⽤dependencyManagement来管理依赖,声明⽗⼯程的打包⽅式为pom

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>spring_cloud</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>
    <modules>
        <module>order-service</module>
        <module>product-service</module>
    </modules>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.1.6</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <java.version>17</java.version>
        <mybatis.version>3.0.3</mybatis.version>
        <mysql.version>8.0.33</mysql.version>
        <spring-cloud.version>2022.0.3</spring-cloud.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
    </dependencies>
    <dependencyManagement>
    <dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-dependencies</artifactId>
        <version>${spring-cloud.version}</version>
        <type>pom</type>
        <scope>import</scope>
    </dependency>
    <dependency>
        <groupId>org.mybatis.spring.boot</groupId>
        <artifactId>mybatis-spring-boot-starter</artifactId>
        <version>${mybatis.version}</version>
    </dependency>
    <dependency>
        <groupId>com.mysql</groupId>
        <artifactId>mysql-connector-j</artifactId>
        <version>${mysql.version}</version>
    </dependency>
    <dependency>
        <groupId>org.mybatis.spring.boot</groupId>
        <artifactId>mybatis-spring-boot-starter-test</artifactId>
        <version>${mybatis.version}</version>
        <scope>test</scope>
    </dependency>
    </dependencies>
    </dependencyManagement>

</project>

这里有两个标签,DependencyManagement 和 Dependencies,作用如下

dependencies :将所依赖的jar直接加到项⽬中。⼦项⽬也会继承该依赖. dependencyManagement:只是声明依赖,并不实现Jar包引⼊。如果⼦项⽬需要⽤到相关依赖,需要显式声明。如果⼦项⽬没有指定具体版本,会从⽗项⽬中读取version。如果⼦项⽬中指定了版本号,就会使⽤⼦项⽬中指定的jar版本。此外⽗⼯程的打包⽅式应该是pom,不是jar,这⾥需要⼿动使⽤packaging 来声明

这里需要注意的时,由于后续使用的Spring Cloud 是基于SpringBoot搭建的,所以Spring Cloud 版本与SpringBoot版本有关
在这里插入图片描述

这里使用的咱们项⽬中使⽤的SpringBoot 版本为 3.1.6, 对应的Spring Cloud版本应该为2022.0.x。各位也可以根据自己的版本进行选择。

🎈创建⼦项目-订单服务与商品服务

以下为订单服务的创建过程,商品服务与之一样,名字不同罢了

在这里插入图片描述
在这里插入图片描述

声明项⽬依赖和项⽬构建插件

<properties>
    <maven.compiler.source>17</maven.compiler.source>
    <maven.compiler.target>17</maven.compiler.target>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
    <dependency>
        <groupId>com.mysql</groupId>
        <artifactId>mysql-connector-j</artifactId>
    </dependency>
    <!--mybatis-->
    <dependency>
        <groupId>org.mybatis.spring.boot</groupId>
        <artifactId>mybatis-spring-boot-starter</artifactId>
    </dependency>
</dependencies>
<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>

🎈完善订单服务

在这里插入图片描述

启动类:

@SpringBootApplication
public class OrderServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(OrderServiceApplication.class,args);
    }
}

配置文件:

server:
 port: 9998
spring:
 datasource:
  url: jdbc:mysql://127.0.0.1:3306/cloud_order?characterEncoding=utf8&useSSL=false
  username: 用户
  password: 密码
  driver-class-name: com.mysql.cj.jdbc.Driver
mybatis:
 configuration: # 配置打印 MyBatis⽇志
  log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  map-underscore-to-camel-case: true #配置驼峰⾃动转换

实体类:

@Data
public class OrderInfo {
    private int id;
    private int userId;
    private int productId;
    private int num;
    private long price;
    private boolean deleteFlag;
    private Date createTime;
    private Date update_time;
}

mapper:

@Mapper
public interface OrderMapper {
    @Select("select * from order_detail where id=#{id}")
    OrderInfo selectAll(int id);
}

service:

@Service
public class OrderService {
    @Autowired
    private OrderMapper orderMapper;
    public OrderInfo selectAll(Integer userid) {
        OrderInfo orderInfo = orderMapper.selectAll(userid);
        return orderInfo;
    }
}

controller:

@RestController
@RequestMapping("/order")
public class OrderController {
    @Autowired
    OrderService orderService;
    @RequestMapping("/{id}")
    public OrderInfo selectAll(@PathVariable("id") int id) {
        return orderService.selectAll(id);
    }
}

测试访问:http://127.0.0.1:9998/order/1

即可看到以下界面:
在这里插入图片描述

🎈完善商品服务

在这里插入图片描述
启动类:

@SpringBootApplication
public class ProductServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(ProductServiceApplication.class,args);
    }
}

配置文件:

server:
 port: 9999
spring:
 datasource:
  url: jdbc:mysql://127.0.0.1:3306/cloud_product?characterEncoding=utf8&useSSL=false
  username: 用户
  password: 密码
  driver-class-name: com.mysql.cj.jdbc.Driver
mybatis:
 configuration: # 配置打印 MyBatis⽇志
  log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  map-underscore-to-camel-case: true #配置驼峰⾃动转换

实体类:

@Data
public class ProductInfo {
    private int id;
    private String productName;
    private long productPrice;
    private boolean state;
    private Date createTime;
    private Date updateTime;
}

mapper

@Mapper
public interface ProductMapper {
    @Select("select * from product_detail where id=#{id}")
    ProductInfo selectById(int id);
}

service

@Service
public class ProductService {
    @Autowired
    ProductMapper productMapper;
    public ProductInfo selectById(int id) {
        return productMapper.selectById(id);
    }
}

controller

@RestController
@RequestMapping("/product")
public class ProductController {
    @Autowired
    ProductService productService;
    @RequestMapping("/{id}")
    public ProductInfo selectById(@PathVariable("id") int id) {
        ProductInfo productInfo = productService.selectById(id);
        return productInfo;
    }
}

测试:http://127.0.0.1:9999/product/1001
页面返回结果如下:
在这里插入图片描述

🚩远程调用

🎈调用需求

我们一般有如下需求:

根据订单查询订单信息时,根据订单⾥产品ID,获取产品的详细信息

在这里插入图片描述
意思是,我们希望访问订单页面时,也可以访问到商品服务。

🎈实现

实现思路:order-service服务向product-service服务发送⼀个http请求,把得到的返回结果,和订单结果融合在⼀起,返回给调⽤⽅。

实现⽅式:采⽤Spring提供的RestTemplate

首先因为我们需要返回商品的信息,所以这里我们需要对我们的实体类进行修改,修改如下:
在这里插入图片描述
在这里插入图片描述

其次,我们创建一个config文件,在其文件下进行以下配置:

@Configuration
public class OrderConfig {
    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

接下来,我们对我们原先的 service 类里面的代码进行修改,修改如下:

@Service
public class OrderService {
    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private RestTemplate restTemplate;
    public OrderInfo selectAll(Integer userid) {
        OrderInfo orderInfo = orderMapper.selectAll(userid);
        String url = "http://127.0.0.1:9999/product/" + orderInfo.getProductId();
        restTemplate.getForObject(url, ProductInfo.class);
        ProductInfo productInfo = restTemplate.getForObject(url,
                ProductInfo.class);
        orderInfo.setProductInfo(productInfo);
        return orderInfo;
    }
}

🎈测试

启动商品服务与订单服务;

访问:http://127.0.0.1:9998/order/1

则会出现以下界面:
在这里插入图片描述

🌲项目存在问题

  • 远程调⽤时,URL的IP和端⼝号是写死的,如果更换IP,需要修改代码 。调⽤⽅如何可以不依赖服务提供⽅的IP?
  • 多机部署,如何分摊压⼒?
  • 远程调⽤时,URL⾮常容易写错,⽽且复⽤性不⾼,如何优雅的实现远程调⽤
  • 所有的服务都可以调⽤该接,是否有⻛险?

  • 除此之外,微服务架构还⾯临很多问题,而Spring Cloud 来就是用来解决这些问题

具体如何解决,后续文章再进行一一介绍

⭕总结

关于《【Spring Cloud】微服务的简单搭建》就讲解到这儿,感谢大家的支持,欢迎各位留言交流以及批评指正,如果文章对您有帮助或者觉得作者写的还不错可以点一下关注,点赞,收藏支持一下!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/780729.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

关闭vue3中脑瘫的ESLine

在创建vue3的时候脑子一抽选了ESLine,然后这傻卵子ESLine老是给我报错 博主用的idea开发前端 ,纯粹是用不惯vscode 关闭idea中的ESLine,这个只是取消红色波浪线, 界面中的显示 第二步,在vue.config.js中添加 lintOnSave: false 到这里就ok了,其他的我试过了一点用没有

Google Java Style Guide深度解读:打造优雅的代码艺术

在软件工程的世界里&#xff0c;代码不仅仅是实现功能的工具&#xff0c;它也是团队之间沟通的桥梁&#xff0c;是软件质量和可维护性的直接反映。Google Java Style Guide作为一套广受认可的编码规范&#xff0c;不仅定义了代码的书写规则&#xff0c;更深刻地影响着Java开发者…

绿色金融相关数据合集(2007-2024年 具体看数据类型)

数据类型&#xff1a; 1.绿色债券数据&#xff1a;2014-2023 2.绿色信贷相关数据&#xff1a;2007-2022 3.全国各省及地级市绿色金融指数&#xff1a;1990-2022 4.碳排放权交易明细数据&#xff1a;2013-2024 5.绿色金融试点DID数据&#xff1a;2010-2023 数据来源&#…

python操作SQLite3数据库进行增删改查

python操作SQLite3数据库进行增删改查 1、创建SQLite3数据库 可以通过Navicat图形化软件来创建: 2、创建表 利用Navicat图形化软件来创建: 存储在 SQLite 数据库中的每个值(或是由数据库引擎所操作的值)都有一个以下的存储类型: NULL. 值是空值。 INTEGER. 值是有符…

Linux—网络设置

目录 一、ifconfig——查看网络配置 1、查看网络接口信息 1.1、查看所有网络接口 1.2、查看具体的网络接口 2、修改网络配置 3、添加网络接口 4、禁用/激活网卡 二、hostname——查看主机名称 1、查看主机名称 2、临时修改主机名称 3、永久修改主机名称 4、查看本…

【python】pyqt5大学生成绩信息管理系统-图形界面(源码+报告)【独一无二】

&#x1f449;博__主&#x1f448;&#xff1a;米码收割机 &#x1f449;技__能&#x1f448;&#xff1a;C/Python语言 &#x1f449;公众号&#x1f448;&#xff1a;测试开发自动化【获取源码商业合作】 &#x1f449;荣__誉&#x1f448;&#xff1a;阿里云博客专家博主、5…

基于支持向量机、孤立森林和LSTM自编码器的机械状态异常检测(MATLAB R2021B)

异常检测通常是根据已有的观测数据建立正常行为模型&#xff0c;从而将不同机制下产生的远离正常行为的数据划分为异常类&#xff0c;进而实现对异常状态的检测。常用的异常检测方法主要有&#xff1a;统计方法、信息度量方法、谱映射方法、聚类方法、近邻方法和分类方法等。 …

飞书 API 2-4:如何使用 API 将数据写入数据表

一、引入 上一篇创建好数据表之后&#xff0c;接下来就是写入数据和对数据的处理。 本文主要探讨数据的插入、更新和删除操作。所有的操作都是基于上一篇&#xff08;飞书 API 2-4&#xff09;创建的数据表进行操作。上面最终的数据表只有 2 个字段&#xff1a;序号和邮箱。序…

巴图自动化PN转Modbus RTU协议转换网关模块快速配置

工业领域中常用的通讯协议有&#xff1a;Profinet协议&#xff0c;Modbus协议&#xff0c;ModbusTCP协议&#xff0c;Profibus协议&#xff0c;Profibus DP协议&#xff0c;EtherCAT协议&#xff0c;EtherNET协议&#xff0c;CAN&#xff0c;CanOpen等&#xff0c;它们在自动化…

kubeadm快速部署k8s集群

文章目录 Kubernetes简介1、k8s集群环境2、linux实验环境初始化【所有节点】3、安装docker容器引擎【所有节点】4、安装cri-dockerd【所有节点】5、安装 kubeadm、kubelet、kubectl【所有节点】6、部署 k8s master 节点【master节点】7、加入k8s Node 节点【node节点】8、部署容…

【链表】【双指针】1、合并两个有序链表+2、分隔链表+3、删除链表的倒数第N个结点+4、链表的中间结点+5、合并两个链表

3道中等2道简单 数组和字符串打算告一段落&#xff0c;正好最近做的几乎都是双指针&#xff0c;所以今天做链表&#xff01; 1、合并两个有序链表&#xff08;难度&#xff1a;简单&#xff09; 该题对应力扣网址 AC代码 思路简单 /*** Definition for singly-linked list.…

昇思25天学习打卡营第12天|简单的深度学习ResNet50图像分类 - 构建ResNet50网络

ResNet主要解决深度卷积网络在深度加深时候的“退化”问题。在一般的卷积神经网络中&#xff0c;增大网络深度后带来的第一个问题就是梯度消失、爆炸&#xff0c;这个问题Szegedy提出BN层后被顺利解决。BN层能对各层的输出做归一化&#xff0c;这样梯度在反向层层传递后仍能保持…

P1392 取数

传送门&#xff1a;取数 如若你看完题解后&#xff0c;仍有问题&#xff0c;欢迎评论 首先说一下 我首先想到的思路 &#xff08; 20%通过率 &#xff09;&#xff1a;通过dfs , 将所有的情况放入priority_queue中&#xff08;greater<int>&#xff09;&#xff0c;维持…

计算两种人像之间的相似度

通过调研&#xff0c;目前存在几种能够计算两个人脸相似度的方法&#xff1a; 1.使用结构相似性计算人脸之间的相似度 结构准确性&#xff1a;生成的图片是否保留了原图足够多细节。 &#xff08;1&#xff09;结构准确性衡量指标&#xff1a;SSIM/MMSSIM SSIM&#xff08;结构…

纯前端低代码开发脚手架 - daelui/molecule

daelui/molecule低代码开发脚手架&#xff1a;分子组件开发、预览、打包 页面代码示例、大屏代码示例预览 可开发页面组件 可开发大屏组件 项目git地址&#xff1a;https://gitee.com/daelui/molecule 在线预览&#xff1a;http://www.daelui.com/daelui/molecule/app/index.…

STM32第十六课:WiFi模块的配置及应用

文章目录 需求一、WiFi模块概要二、配置流程1.配置通信串口&#xff0c;引脚和中断2.AT指令3.发送逻辑编写 三、需求实现代码总结 需求 完成WiFi模块的配置,使其最终能和服务器相互发送消息。 一、WiFi模块概要 本次使用的WiFi模块为ESP-12F模块&#xff08;安信可&#xf…

聚类分析方法(一)

目录 一、聚类分析原理&#xff08;一&#xff09;聚类分析概述&#xff08;二&#xff09;聚类的数学定义&#xff08;三&#xff09;簇的常见类型&#xff08;四&#xff09;聚类框架及性能要求&#xff08;五&#xff09;簇的距离 二、划分聚类算法&#xff08;一&#xff0…

车载测试之-CANoe创建仿真工程

在现代汽车工业中&#xff0c;车载测试是确保车辆电子系统可靠性和功能性的关键环节。而使用CANoe创建仿真工程&#xff0c;不仅能够模拟真实的车辆环境&#xff0c;还能大大提升测试效率和准确性。那么&#xff0c;CANoe是如何实现这些的呢&#xff1f; 车载测试中&#xff0…

PXIe-7976【K410T】

起售价 RMB 152,880.00 块RAM(BRAM): 28620 kbit 动态RAM(DRAM): 2 GB FPGA: Kintex-7 410T PXI背板链路: PCI-Express Gen2 x 8 FPGA片: 63550 DSP片: 1540

敏感词匹配DFA算法

算法简介与场景介绍 DFA算法&#xff0c;中文全称为确定性有穷自动机。它的基本思想是构建一个有穷自动机&#xff0c;当用户输入文本时&#xff0c;通过自动机的状态转换来快速匹配敏感词。具体特征是&#xff0c;有一个有效状态的集合和一些从一个状态通向另一个状态的边&am…