目录
[1.3 微服务架构的优势](#1.3 微服务架构的优势)
[1.5. SpringCloud与微服务关系](#1.5. SpringCloud与微服务关系)
[2. 创建微服务工程](#2. 创建微服务工程)
[2.2 创建公共模块](#2.2 创建公共模块)
1.微服务架构
1.1.单体应用架构
将项目所有模块(功能)打成jar或者war,然后部署一个进程
优点:
1:部署简单:由于是完整的结构体,可以直接部署在一个服务器上即可。
2:技术单一:项目不需要复杂的技术栈,往往一套熟悉的技术栈就可以完成开发。
缺点:
1:系统启动慢,一个进程包含了所有的业务逻辑,涉及到的启动模块过多,导致系统的启动、重启时间周期过长;
2:系统错误隔离性差、可用性差,任何一个模块的错误均可能造成整个系统的宕机;
3:可伸缩性差:系统的扩容只能只对这个应用进行扩容,无法结合业务模块的特点进行伸缩。
4: 线上问题修复周期长:任何一个线上问题修复需要对整个应用系统进行全面升级。
5: 跨语言程度差
6: 不利于安全管理,所有开发人员都拥有全量代码。
小型项目适合单体应用架构. 比如:OA办公系统。管理类的项目 仓库管理系统。
1.2.微服务应用
简单来说,微服务架构风格[1]是一种将一个单一应用程序开发为一组小型服务的方法,每个服务运行在自己的进程中,服务间通信采用轻量级通信机制(通常用HTTP资源API)。这些服务围绕业务能力构建并且可通过全自动部署机制独立部署。这些服务共用一个最小型的集中式的管理,服务可用不同的语言开发,使用不同的数据存储技术。
- > 一个项目被拆分若干个项目
- > 每个项目可以独立运行
- > 每个项目可以使用不同的语言开发
- > 每个项目可以拥有独立的数据库
- > 项目与项目之间可以通信[http协议]
解读微服务特点:
- 微服务是一种==项目架构思想==(风格)
- 微服务架构是一系列小服务的组合(组件化与多服务)
- 任何一个微服务,都是一个独立的进程(独立开发、独立维护、独立部署)
- 轻量级通信http协议(跨语言,跨平台)
- 服务粒度(围绕业务功能拆分---模块拆分【系统管理服务】【日志服务】【焦虑测试】【抑郁测试系统】)
1.3 微服务架构的优势
1.易于开发和维护
一个微服务只关注一个特定的业务功能,所以它的业务清晰、代码量较少。开发和维护单个微服务相对比较简单,整个应用是由若干个微服务构建而成,所以整个应用也会维持在可控状态;
⒉.单个微服务启动较快
单个微服务代码量较少,所以启动会比较快;
3.局部修改容易部署
单体应用只要有修改,就要重新部署整个应用,微服务解决了这样的问题。一般来说,对某个微服务进行修改,只需要重新部署这个服务即可;
4.技术栈不受限
在微服务中,我们可以结合项目业务及团队的特点,合理地选择技术栈
5.按需伸缩
焦虑系统访问量大,只需要对焦虑系统进行扩展
1.4.微服务架构的缺点(挑战)
1、服务太多,导致服务间的依赖错综复杂,运维难度大
2、微服务放大了分布式架构的系列问题
分布式事务(seata)
分布式锁怎么处理(redisson) ,
服务注册与发现(nacos) .
依赖服务不稳定(sentinel)导致服务雪崩怎么办?
3、运维复杂度陡增,部署数量多、监控进程多导致整体运维复杂度提升。
如何解决上面的挑战----springcloud
1.5. SpringCloud与微服务关系
Springcloud为微服务思想提供了完美的解决方案
Springcloud是一些列框架的集合体(不同的框架解决微服务面临的不同的挑战)
springcloud提供了两款模式:第一种netflix公司 第二款:alibaba-阿里巴巴。
1.6.SpringBoot和SpringCloud关系
- SpringBoot专注于快速方便的开发单个个体微服务。
- SpringCloud是关注全局的微服务协调、整理、治理的框架,它将SpringBoot开发的单体整合并管理起来。
- SpringBoot可以离开SpringCloud独立使用开发项目,但是SpringCloud离不开SpringBoot,属于依赖关系。
2. 创建微服务工程
技术栈: mysql+mybatis[mp]+springboot+springcloud alibaba
2.1.数据库
订单数据库:
sqlSET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; -- ---------------------------- -- Table structure for shop_order -- ---------------------------- DROP TABLE IF EXISTS `shop_order`; CREATE TABLE `shop_order` ( `oid` bigint(0) NOT NULL AUTO_INCREMENT COMMENT '订单id', `uid` int(0) NULL DEFAULT NULL COMMENT '用户id', `username` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '用户名', `pid` bigint(0) NULL DEFAULT NULL COMMENT '商品id', `pname` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '商品名称', `pprice` decimal(10, 2) NULL DEFAULT NULL COMMENT '商品价格', `number` int(0) NULL DEFAULT NULL COMMENT '购买数量', PRIMARY KEY (`oid`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 44956 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic; -- ---------------------------- -- Records of shop_order -- ---------------------------- SET FOREIGN_KEY_CHECKS = 1;
商品数据库:
sqlSET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; -- ---------------------------- -- Table structure for shop_product -- ---------------------------- DROP TABLE IF EXISTS `shop_product`; CREATE TABLE `shop_product` ( `pid` bigint(0) NOT NULL AUTO_INCREMENT COMMENT '商品id', `pname` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '商品名', `pprice` decimal(10, 2) NULL DEFAULT NULL COMMENT '商品价格', `stock` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '商品库存', PRIMARY KEY (`pid`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic; -- ---------------------------- -- Records of shop_product -- ---------------------------- INSERT INTO `shop_product` VALUES (1, '华为手机', 1999.00, '100'); INSERT INTO `shop_product` VALUES (2, 'vivo手机', 2999.00, '100'); INSERT INTO `shop_product` VALUES (3, '小米', 2222.00, '1000'); SET FOREIGN_KEY_CHECKS = 1;
2.2.搭建父工程
创建maven工程作为父工程
引入依赖
XML<?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>com.aaa</groupId> <artifactId>springcloud-2</artifactId> <version>1.0-SNAPSHOT</version> <packaging>pom</packaging> <!--继承springboot父工程--> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.3.2.RELEASE</version> </parent> <!--定义版本号--> <properties> <java.version>1.8</java.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF- 8</project.reporting.outputEncoding> <spring-cloud.version>Hoxton.SR8</spring-cloud.version> <spring-cloud-alibaba.version>2.2.3.RELEASE</spring-cloud-alibaba.version> </properties> <!--dependencyManagement: 它只负责jar的管理 不负责jar的下载 子类使用该类型的jar包时,直接引用而无需写版本--> <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>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-dependencies</artifactId> <version>${spring-cloud-alibaba.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> </project>
springboot 和 springcloud 以及springcloud alibaba他们的版本必须匹配
2.2 创建公共模块
创建maven工程作为公共模块
引入依赖
XML<?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> <parent> <groupId>com.aaa</groupId> <artifactId>springcloud-2</artifactId> <version>1.0-SNAPSHOT</version> </parent> <artifactId>common</artifactId> <properties> <maven.compiler.source>8</maven.compiler.source> <maven.compiler.target>8</maven.compiler.target> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.5.1</version> </dependency> </dependencies> </project>
创建相应的实体类
java@Data @TableName(value = "shop_product") public class Product implements Serializable { //商品 @TableId(value = "pid",type = IdType.AUTO) private Long pid; private String pname; private BigDecimal pprice; private Integer stock; }
java@Data @TableName("shop_order") public class Order implements Serializable { //订单 @TableId(value = "oid",type = IdType.AUTO) private Long oid; private Long uid; private String username; private Long pid; private String pname; private BigDecimal pprice; private Integer number; }
2.3.商品系统
创建maven工程作为商品系统
引入依赖
XML<dependencies> <!--公共模块引入--> <dependency> <groupId>com.aaa</groupId> <artifactId>common</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> </dependencies>
创建配置文件
java#端口号8001~8008 server.port=8001 #数据源 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.url=jdbc:mysql:///springcloud-product?serverTimezone=Asia/Shanghai spring.datasource.password=123456789 spring.datasource.username=root #mpd的日志 mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
创建主启动类
java@SpringBootApplication @MapperScan(basePackages = "com.aaa.product.dao") public class ProductApp { public static void main(String[] args) { SpringApplication.run(ProductApp.class,args); } }
创建dao接口
javapublic interface ProductDao extends BaseMapper<Product> { }
创建service层及实现类
javapublic interface ProductService { /** * 根据商品id查询商品信息 * @param pid 商品id * @return 商品信息 */ public Product findById(Long pid); }
java@Service public class ProductServiceImpl implements ProductService { @Autowired private ProductDao productDao; @Override public Product findById(Long pid) { return productDao.selectById(pid); } }
创建controller层
java@RestController @RequestMapping("product") public class ProductController { @Autowired private ProductService productService; @GetMapping("getById/{id}") public Product getById(@PathVariable Long id) { Product product = productService.findById(id); return product; } }
测试
2.4.订单微服务
创建maven工程作为订单系统
引入依赖
XML<dependencies> <!--公共模块引入--> <dependency> <groupId>com.aaa</groupId> <artifactId>common</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> </dependencies>
创建配置文件
java#端口号9001~9008 server.port=9001 #数据源 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.url=jdbc:mysql:///springcloud-order?serverTimezone=Asia/Shanghai&characterEncoding=utf-8 spring.datasource.password=123456789 spring.datasource.username=root #mpd的日志 mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
创建主启动类
java@SpringBootApplication @MapperScan(basePackages = "com.aaa.order.dao") public class OrderApp { public static void main(String[] args) { SpringApplication.run(OrderApp.class,args); } }
创建dao接口
javapublic interface OrderDao extends BaseMapper<Order> { }
创建service层及实现类
javapublic interface OrderService { //添加订单 public Order save(Order order); }
java@Service public class OrderServiceImpl implements OrderService { @Autowired private OrderDao orderDao; @Override public Order save(Order order) { int insert = orderDao.insert(order); if (insert > 0){ return order; }else { throw new RuntimeException("订单添加失败~~~~~~~"); } } }
主启动类中加入RestTemplate
创建controller层
java@RestController @RequestMapping("order") public class OrderController { @Autowired private OrderService orderService; @Autowired private RestTemplate restTemplate; @GetMapping("insert") public String insert(Long pid, Integer num) { //创建一个订单对象 Order order = new Order(); order.setUid(1L); order.setUsername("安卓手机"); order.setNumber(num); //商品信息---调用商品微服务的接口。---如何调用商品微服务的接口?--远程调用。[1]借助rabbitmq [2]http远程调用【在java端模拟浏览器调用】。 //spring封装了http远程调用 RestTemplate.默认该类没有交于spring容器管理. 创建一个配置类 写一个方法@Bean注解 /** * String url, 远程调用的服务器的地址 * Class<T> responseType, 远程调用的接口返回类型的反射类 * Object... uriVariables: 远程接口需要传递的参数。 */ Product product = restTemplate.getForObject("http://localhost:8001/product/getById/" + pid, Product.class); order.setPid(product.getPid()); order.setPname(product.getPname()); order.setPprice(product.getPprice()); int i = orderService.save(order); return i > 0 ? "下单成功" : "下单失败"; } }
测试
隐藏不想展示的文件:
项目结构: