1.1 单体应用架构
将项目所有模块(功能)打成jar或者war,然后部署一个进程
优点:
1:部署简单:由于是完整的结构体,可以直接部署在一个服务器上即可。
2:技术单一:项目不需要复杂的技术栈,往往一套熟悉的技术栈就可以完成开发
缺点:
1:系统启动慢,一个进程包含了所有的业务逻辑,涉及到的启动模块过多,导致系统的启动、重启时间周期过长;
2:系统错误隔离性差、可用性差、任何一个模块的错误均可能造成整个系统的宕机。
3:可伸缩性差:系统的扩容只能只对这个应用进行扩容,无法结合业务模块的特点进行伸缩。
4.线上问题修复周期长:任何一个线上问题修复需要对整个应用系统进行全面升级。
5:跨语言程度差
6:不利于安全管理,所有开发人员都拥有全量代码
小型项目适合单体应用架构:比如:OA办公系统。管理类的项目 仓库管理系统。
1.2 微服务应用
微服务架构论文:Microserviceshttps://martinfowler.com/articles/microservices.html
简单来说,微服务架构风格[1]是一种将一个单一应用程序开发为一组小型服务的方法,每个服务运行在自己的进程中,服务间通信采用轻量级通信机制(通常用HTTP资源API)。这些服务围绕业务能力构建并且可通过全自动部署机制独立部署。这些服务共用一个最小型的集中式的管理,服务可用不同的语言开发,使用不同的数据存储技术。
解读微服务特点:
1:微服务是一种项目架构思想(风格)
2:微服务架构是一系列小服务的组合(组件化与多服务)
3:任何一个微服务,都是一个独立的进程(独立开发、独立维护、独立部署)
4:轻量级通信http协议(跨语言,跨平台)
5:服务粒度(围绕业务功能拆分)
6:去中心化管理(去中心化“地治理技术、去中心化地管理数据”)
1.3微服务架构的优势
1.易于开发和维护
一个微服务只关注一个特点的业务功能,所以它的业务清晰,代码量较少。开发和维护单个微服务相对比较简单,整个应用是由若干个微服务构建而成,所以整个应用也会维持在可控状态;
2.单个微服务启动较快
单个微服务代码量较少,所以启动会比较快;
3.局部修改容易部署
单体应用只要由修改,就要重新部署整个应用,微服务解决了这样的问题。一般来说,对某个微服务进行修改,只需要重新部署这个服务即可;
4.技术栈不受限
在微服务中,我们可以结合项目业务及团队的特点,合理地选择技术栈
5.按需伸缩
某个服务访问量大,只需要对这个服务进行扩展
1.4 微服务架构的缺点(挑战)
1、服务太多,导致服务间的依赖错综复杂,运维难度大
2、微服务放大了分布式架构的系列问题
- 分布式事务(seata)
- 分布式锁怎么处理(redisson)
- 服务注册与发现(nacos)
- 依赖服务不稳定(sentinel)导致服务雪崩怎么办?
3、运维复杂度徒增,部署数量多、监控进程多导致整体运维复杂度提升。
1.5 SpringCloud与微服务关系
- Springcloud为微服务思想提供了完美的解决方案
- Springcloud是一些列框架的集合体(服务的注册于发现【注册中心】、服务间远程调用、服务降级、服务熔断、服务限流、分布式事务等)
一般我们说springcloud 其实指的是Springcloud-netflix,Springcloud并不是造轮子,只是把Netflix公司的组件做二次开发
1.6SpringBoot和SpringCloud关系
- SpringBoot专注于快速方法的开发单个个体微服务。
- SpringCloud是关注全局的微服务协调、整理、治理的框架,它将SpringBoot开发的单体整合并管理起来。
- SpringBoot可以离开SpringCloud独立使用开发项目,但是SpringCloud离不开SpringBoot,属于依赖关系
2.创建微服务工程
2.1创建一个父工程
(1)依赖
<?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>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.12.RELEASE</version>
</parent>
<groupId>com.aaa</groupId>
<artifactId>qy163-parent</artifactId>
<version>1.0-SNAPSHOT</version>
<!--父工程那么它的打包方式必须为pom打包-->
<packaging>pom</packaging>
<!--定义版本号-->
<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>
<!--管理了cloud版本-->
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--alibaba的版本-->
<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>
2.2 公共模块
(1)依赖
<?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">
<parent>
<artifactId>qy163-parent</artifactId>
<groupId>com.aaa</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>qy163-common</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</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>
(2)product实体类
@Data
@TableName(value = "shop_product")
public class product {
@TableId(value = "pid",type = IdType.AUTO)
private Integer pid;
private String pname;
private BigDecimal pprice;
private Integer stock;
}
(3)order实体类
@Data
@TableName(value = "shop_order")
public class Order {
@TableId(value = "oid",type = IdType.AUTO)
private Integer oid;
private Integer uid;
private String username;
private Integer pid;
private String pname;
private Integer pprice;
private Integer number;
}
2.3 product商品微服务
(1)依赖
<?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">
<parent>
<artifactId>qy163-parent</artifactId>
<groupId>com.aaa</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>qy163-product</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>com.aaa</groupId>
<artifactId>qy163-common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.3.1</version>
</dependency>
</dependencies>
</project>
(2)配置文件
#端口号
server.port=8080
#配置数据库信息
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/springcloud_product
spring.datasource.username=root
spring.datasource.password=wang134246
#日志文件
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
(3)主启动类
@SpringBootApplication
@MapperScan(basePackages = "com.wyl.dao")
public class ProductApp {
public static void main(String[] args) {
SpringApplication.run(ProductApp.class,args);
}
}
(4)dao层
@Mapper
public interface ProductDao extends BaseMapper<Product> {
}
(5)service层
@Service
public class ProductServiceImpl implements ProductService {
@Autowired
private ProductDao productDao;
@Override
public Product getById(Integer pid) {
return productDao.selectById(pid);
}
}
(6)controller层
@RestController
@RequestMapping("product")
public class ProductController {
@Autowired
private ProductService productService;
@GetMapping("getById/{pid}")
public Product getById(@PathVariable Integer pid){
return productService.getById(pid);
}
}
(7)访问页面
2.4 order订单微服务
(1)依赖
<?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">
<parent>
<artifactId>qy163-parent</artifactId>
<groupId>com.aaa</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>qy163-order</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>com.aaa</groupId>
<artifactId>qy163-common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.3.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
</project>
(2)配置
#端口号
server.port=8081
#数据库信息
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/springcloud_order
spring.datasource.username=root
spring.datasource.password=wang134246
#日志
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
(3)启动类
package com.wyl;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
/**
* @program: qy163
* @description:
* @author: 王永亮
* @create: 2023-05-12 21:08
**/
@SpringBootApplication
@MapperScan(basePackages = "com.wyl.dao")
public class OrderApp {
public static void main(String[] args) {
SpringApplication.run(OrderApp.class,args);
}
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
(4)dao层
@Mapper
public interface OrderDao extends BaseMapper<Order> {
}
(5)service层
@Service
public class OrderServiceImpl implements OrderService {
@Autowired
private OrderDao orderDao;
@Override
public Integer save(Order order) {
return orderDao.insert(order);
}
}
(6)controller层
package com.wyl.controller;
import com.wyl.pojo.Order;
import com.wyl.pojo.Product;
import com.wyl.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
/**
* @program: qy163
* @description:
* @author: 王永亮
* @create: 2023-05-12 21:05
**/
@RestController
@RequestMapping("order")
public class OrderController {
@Autowired
private OrderService orderService;
@Autowired
private RestTemplate restTemplate;
@GetMapping("save")
public String save(Integer pid,Integer num){
System.out.println(pid + "" + num);
Order order = new Order();
order.setUid(1);
order.setUsername("wyl");
order.setNumber(num);
Product product = restTemplate.getForObject("http://localhost:8080/product/getById/" + pid, Product.class);
if (product == null){
return "下单失败";
}
order.setPid(product.getPid());
order.setPname(product.getPname());
order.setPprice(product.getPprice());
Integer save = orderService.save(order);
return save > 0 ? "下单成功" : "下单失败";
}
}
(7)访问浏览器