更新时间:2020/9/13 23:32,更新到了rabbitmq集群
更新时间:2020/9/22 21:12,更新到了服务调用
更新时间:2020/9/17 21:31,更新到了微服务架构
本文主要对springcloud进行学习与记录,本文会持续更新,不断地扩充
本文仅为记录学习轨迹,如有侵权,联系删除
目前在学校实训用的基本都是单体应用·,简单理解就是把web工程的所有模块(web层,service层,dao层)全部打包放到一个web容器中运行,这样就构成了一个单体应用。
这种架构适用于一些小型应用,可以进行快速开发,但缺点就是耦合度太高,而且在高并发的情况下容易崩。
为了解决上面的问题,就有了垂直架构,这种架构在一定程度上对上面的架构进行了解耦,将一些功能独立了出来。
不同的模块可以用不同的技术,但是也有问题,像是模块的独立就会导致很多重复性的代码,做一些没用的重复性工作,而且这个拆分还不是彻底的拆分,像对于某一个模块全部功能集中到一个工程,对于大型项目不利于开发、拓展、维护。而且还有模块之间的数据交流问题等。
之后又产生了SOA架构,SOA(Service-Oriented Architecture),即面向服务架构,通过将核心业务逻辑抽离成通用的服务组件进行分布式部署、组合和使用,一个服务组件通常以独立形式的进程运行。
重点是将核心业务逻辑抽离成通用的服务组件进行分布式部署、组合和使用。这种方式可以抽取公共功能作为通用服务组件,用来提高开发效率,同时解决上面说到的代码重复问题,对不同服务进行集群化部署可以缓解系统压力。还可以再一次降低耦合度。但缺点也是有的,即抽取服务的粒度较大,服务提供方和调用方的接口耦合度较高。
终于到微服务架构了,微服务架构可以说是在SOA架构的基础上又一次改进,强调业务的彻底组件化和服务化,对业务系统进行更细粒度的逻辑拆分成多个独立开发运行的小应用。
它拆分的颗粒更小了,强调原子化拆分,遵循单一原则。微服务之间采用Restful等轻量协议传输。缺点则是因为拆分颗粒更细了,所以微服务也就更多了,这就导致了对这些微服务的难管理,同时部署的难度也提升了。
常见的两种是Dubbo 和 Spring Cloud,Dubbo没了解过,这里重点学习Spring Cloud微服务框架,所以到这里就很明白了,Spring Cloud是用来实现微服务架构的一种方式,应该是一种实现。
简介
Spring Cloud 是一套完整的微服务解决方案,基于 Spring Boot 框架,准确的说,它不是一个框架,而是一个大的容器,它只是将各家公司开发的比较成熟、经得起实际考验的服务框架组合起来,通过Spring Boot风格进行再封装屏蔽掉了复杂的配置和实现原理,最终给开发者留出了一套简单易懂、易部署和易维护的分布式系统开发工具包。可以简单的理解为springcloud就是一个springboot风格的容器。
优缺点
优点 | 缺点 |
---|---|
集大成者,Spring Cloud 包含了微服务架构的方方面面。 | 项目结构复杂,每一个组件或者每一个服务都需要创建一个项目。 |
约定优于配置,基于注解,没有配置文件。 | 部署门槛高,项目部署需要配合 Docker 等容器技术进行集群部署 |
轻量级组件,Spring Cloud 整合的组件大多比较轻量级,且都是各自领域的佼佼者。 | / |
开发简便,Spring Cloud 对各个组件进行了大量的封装,从而简化了开发。 | / |
开发灵活,Spring Cloud 的组件都是解耦的,开发人员可以灵活按需选择组件。 | / |
首先先看一下,如果不用Eureka等服务注册工具的情况下,如何做到一个服务调用另一个服务,下面给出一个消费者模块调用支付模块的例子
注意:工程采用聚合工程的形式,具体怎么创建可以参考一下本人的另一篇博客:https://blog.csdn.net/qq_40298902/article/details/108475819
模块的创建
首先是父工程的创建,可以用spring的方式创建,也可以直接用maven的方式创建,这里采用maven的方式创建
创建完之后把src目录删掉,然后修改pom文件如下,下面的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>springboot_cloud01</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<!--统一管理jar包版本-->
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<junit.version>4.12</junit.version>
<lombok.version>1.18.10</lombok.version>
<log4j.version>1.2.17</log4j.version>
<mysql.version>8.0.18</mysql.version>
<druid.version>1.1.21</druid.version>
<mybatis.spring.boot.version>2.1.1</mybatis.spring.boot.version>
</properties>
<!--依赖管理-->
<dependencyManagement>
<dependencies>
<!--spring boot 2.2.2-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.2.2.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--spring cloud Hoxton.SR1-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Hoxton.SR1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--spring cloud 阿里巴巴-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.1.0.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
<scope>runtime</scope>
</dependency>
<!-- druid-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>${druid.version}</version>
</dependency>
<!--mybatis-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>${mybatis.spring.boot.version}</version>
</dependency>
<!--junit-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
</dependency>
<!--log4j-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
<optional>true</optional>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<fork>true</fork><!--必须添加这个配置-->
<addResources>true</addResources>
</configuration>
</plugin>
</plugins>
</build>
</project>
接下来创建支付子模块
创建完之后,父模块的pom那里会生成module标签,里面就配置有子模块的名称,在支付子模块的pom中引入springboot依赖以及一些常见的依赖,下面给出本人的依赖配置
<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>springboot_cloud01artifactId>
<groupId>org.examplegroupId>
<version>1.0-SNAPSHOTversion>
parent>
<modelVersion>4.0.0modelVersion>
<artifactId>cloud-provider-payment8001artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-actuatorartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<optional>trueoptional>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>druidartifactId>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<scope>runtimescope>
dependency>
<dependency>
<groupId>org.mybatis.spring.bootgroupId>
<artifactId>mybatis-spring-boot-starterartifactId>
dependency>
dependencies>
project>
之后消费者模块的创建也是这样类似的创建
服务调用
下面要实现从消费者模块调用支付模块,这里需要RestTemplate这项技术,详细用法可以自行百度,在使用前就必须先配置它,创建配置类进行配置
/**
* @ClassName : ApplicationContextConfig
* @Description :
* @Author : CJH
* @Date: 2020-09-22 15:35
*/
@Configuration
public class ApplicationContextConfig {
@Bean
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
}
使用RestTemplate向支付模块发送请求
/**
* @ClassName : OrderController
* @Description :
* @Author : CJH
* @Date: 2020-09-22 15:36
*/
@RestController
@SpringBootApplication
public class OrderController {
public static final String URL = "http://localhost:8001/payment";
@Resource
private RestTemplate restTemplate;
@PostMapping("/consumer/payment")
public PageResult<Payment> save(@RequestBody Payment payment){
PageResult pageResult = restTemplate.postForObject(URL, payment, PageResult.class);
return pageResult;
}
@GetMapping("/consumer/payment/{id}")
public PageResult<Payment> get(@PathVariable Long id){
PageResult pageResult = restTemplate.getForObject(URL + "/" + id, PageResult.class);
return pageResult;
}
}
由于消费者模块调用支付模块,向支付模块发送save请求,因为支付模块中接收的支付实体类Payment,所以在消费者模块中也要先创建跟支付模块一样的实体类,同时还得有统一返回结果实体类接收支付模块的返回消息,这个跟支付模块一样,所以又得创建跟支付模块一样的统一返回结果实体类,具体如下
测试结果,运行两个模块,直接访问支付模块和通过消费者模块调用支付模块(访问消费者模块)
可以看到消费者模块调用了支付模块
项目重构
上面已经实现了最基础的服务调用,一个模块即一个服务。但是也看到了很多不足,例如代码冗余,这个时候就需要项目重构,新建一个公共模块,把所有的共用的代码全部丢在公共模块,包括一些共用的工具类等。
新建公共子模块,修改pom文件,因为要把共用的实体类放到这个包下,需要用到lombok,同时为了方便,这边自己引入了hutool工具类,按实际情况引入即可
<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>springboot_cloud01artifactId>
<groupId>org.examplegroupId>
<version>1.0-SNAPSHOTversion>
parent>
<modelVersion>4.0.0modelVersion>
<artifactId>cloud-api-commonsartifactId>
<dependencies>
<dependency>
<groupId>cn.hutoolgroupId>
<artifactId>hutool-allartifactId>
<version>5.4.3version>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<version>${lombok.version}version>
<optional>trueoptional>
dependency>
dependencies>
project>
然后运行maven打包,建议在打包前先clen一下,再将打包后的jar坐标引入消费者模块和支付模块,实现共用
删除消费者模块和支付者模块的重复代码,即上面提到的entiy和bean包下的实体类和统一返回结果实体类,这些都已经放到了公共包下,并且在消费者模块和支付模块引入公共包的坐标,两个包都要引入,下面只展示其中之一