尚硅谷SpringCloud框架开发教程(SpringCloudAlibaba微服务分布式架构丨Spring Cloud)_哔哩哔哩_bilibili
https://www.bilibili.com/video/BV18E411x7eT/?spm_id_from=333.337.search-card.all.click
1. 微服务架构概述
微服务架构是一种架构模式,它提倡将单一应用程序划分成一组小的服务,服务之间互相协调、互相配合,为用户提供最终价值。每个服务运行在其独立的进程中,服务与服务间采用轻量级的通信机制互相协作(通常是基于HTTP协议的RESTful AP)。每个服务都围绕着具本业务进行构建,并且能够被独立的部署到生产环境、类生产环境等。另外,应当尽量避免统一的、集中式的服务管理机制,对具体的个服务而善应根据业务上下文,选择合适的语言、工具对其进行构建。
微服务技术栈:服务集群、注册中心、配置中心(热更新)、服务网关(校验、路由、负载均衡)、分布式缓存、分布式搜索、消息队列(异步通信)、数据库集群、分布式日志、系统监控链路追踪。
单体架构:将业务的所有的功能模块集中到一个项目中开发,打包成一个包部署。优点:架构简单、部署成本低;缺点:耦合度高 图片地址:XX系统架构图 流程图模板_ProcessOn思维导图、流程图https://www.processon.com/view/643bcd5f6dcb245472aae47a?fromnew=1
分布式架构:根据业务功能对系统进行拆分,每一页五五模块作为独立项目开发,称为一个服务。优点:降低服务耦合,有利于服务升级拓展;缺点:架构非常负载,运维、监控、部署难度提高。
2. Spring Cloud简介
SpringCloud=分布式微服务架构的一站式解决方案,是多种微服务架构落地技术的集合体,俗称微服务全家桶。Spring Cloud就是为开发人员所提供的一套快速构建的分布式系统工具。对于单体架构和分布式架构可以这么理解,单体架构对于Java开发人员可以说就是一个单体Spring Boot框架搭建的系统,而对于分布式架构如果使用微服务方式实现就是多个Spring Boot开发的服务集形成的系统。因此Spring Cloud相比于Spring Boot不在注重服务本身的开发而是服务集管理。
3. Spring Cloud技术栈
-
SpringCloud:注册中心(Eureka、Consul)、服务远程调用(Fegin--http协议)、配置中心(Spring Cloud Config)、服务网关(Spring Cloud Gateway、Zuul)、服务监控和保护(Hystrix)
-
Spring Cloud Alibaba:注册中心(Nacos、Eureka)、服务远程调用(Dubbo、Fegin)、配置中心(Spring Cloud Config、Nacos)、服务网关(Spring Cloud Gateway、Zuul)、服务监控和保护(Sentinel)
4. Spring Cloud与Spring Boot版本依赖
Spring Boot在git源代码地址:https://github.com/spring-projects/spring-boot/releases Spring Boot2.0新特性:https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.0-Release-Notes Spring Boot官网:Spring Boot
Spring Cloud在git源代码地址:https://github.com/spring-projects/spring-cloud Spring Cloud官网:Spring Cloud
Spring Cloud与Spring Boot版本选择: 1.进入官网:Spring Cloud,
第一步:
第二步:
2.进入https://start.spring.io/actuator/info,筛选版本(对于json数据格式,可以使用tool.lu在线工具)
3.进入Spring Cloud官网滑到中底部
停更不停用: 被动修复bugs、不再接受和并请求、不在发布新版本
服务注册中心:Eureka(停更不停用)\Zookeeper\Consul\Nacos 服务调用:Ribbon\LoadBalancer\Feign(死了)\OpenFeign 服务降级:Hystrix(死了)\resilience4j\sentinel 服务网关:Zuul(死了)\gateway 服务配置:Config(不使用)\Nacos 服务总线:Bus(不使用)\Nacos
5. 微服务服务架构搭建
技术和工具版本选型:spring cloud(Hoxton.SR1)、spring boot(2.2.2.RELEASE)、cloud alibaba(2.1.0.RELESE)、Java(8)、Maven(3.5以上)、MySQL(5.7以上)
5.1 搭建父工程
搭建父工程目的是为了规范jar的版本,对于整个微服务来说使用相同版本的jar包实现版本统一或者减少子项目多次输入jar包版本。
这里详细展示需要注意搭建一个项目工程步骤,后续省略: 1.New Project中(选择一个最小)
2.字符编码(setting->file encoding)
3.注解激活
4.Java编译版本
5.文件过滤
5.2 父工程pom
<groupId>com.yicai.springcloud</groupId>
<artifactId>cloud2020</artifactId>
<version>1.0-SNAPSHOT</version>
<!-- 表示pom总的父工程-->
<packaging>pom</packaging>
<!--统一jar和版本号管理-->
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compailer.target>1.8</maven.compailer.target>
<junit.version>4.12</junit.version>
<log4j.version>1.2.17</log4j.version>
<lombok.version>1.18.24</lombok.version>
<mysql.version>5.1.47</mysql.version>
<druid.version>1.2.8</druid.version>
<mybatis.spring.boot.version>1.3.2</mybatis.spring.boot.version>
</properties>
<!-- 子模块继承之后,提供作用:锁定版本+子module不写groupId和version-->
<!-- 父pom的依赖管理,子项目不用引入版本号,Maven会沿着父子层次向上爬,直到有个dependencyManagement -->
<dependencyManagement>
<dependencies>
<!-- Spring Boot版本-->
<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版本-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Hoxton.SR1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- spring cloud alibaba 2.1.0.RELEASE-->
<!-- spring cloud alibaba 2.1.0.RELEASE 关于依赖来取问题:https://blog.csdn.net/xxly1994/article/details/107058474-->
<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>
</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>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.2.5.RELEASE</version>
<configuration>
<fork>true</fork>
<addResources>true</addResources>
</configuration>
</plugin>
</plugins>
</build>
Maven中dependencyManagement与depency:
Maven 使用dependencyManagement 元素来提供了一种管理依赖版本号的方式。通常会在一个组织或者项目的最顶层的父POM 中看到dependencyManagement 元素。使用pom.xml 中的dependencyManagement 元素能让所有在子项目中引用一个依赖而不用显式的列出版本号。Maven 会沿着父子层次向上走,直到找到一个拥有dependencyManagement 元素的项目,然后它就会使用这个dependencyManagement 元素中指定的版本号。 dependencyManagement里只是声明依赖,并不实现引入,因此子项目需要显示的声明需要用的依赖。如果不在子项目中声明依赖,是不会从父项目中继承下来的;只有在子项目中写了该依赖项,并且没有指定具体版本,才会从父项目中继承该项,并且version和scope都读取自父pom。如果子项目中指定了版本号,那么会使用子项目中指定的jar版本。
Maven中跳过单元测试:
5.3 Rest微服务工程构建
1.构建cloud-provider-payment8001
pom文件:
<dependencies>
<!-- spring-boot-web 启动类-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- spring-boot-actuator 健康监控-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
<!-- druid基于spring-boot-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- jdbc-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!-- 热更新-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
application.yaml
#端口
server:
port: 8001
spring:
application:
name: cloud-payment-service
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://192.168.25.153:3306/db2019?useUnicode=true&characterEncoding=utf-8&useSSL=false
username: root
password: Mya_123456
mybatis:
mapper-locations: classpath:mapper/*.xml
type-aliases-package: com.atguigu.springcloud.entities
主启动类:
@SpringBootApplication
public class PaymentMain8001 {
public static void main(String[] args) {
SpringApplication.run(PaymentMain8001.class,args);
}
}
业务类:
Linux安装MySQL数据库
-
建表
create table `payment`(
`id` bigint(20) not null auto_increment comment 'ID',
`serial` varcahr(200) default '',
primary key(`id`)
)engine=innodb auto_increment=1 default charset=utf8;
-
entities
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Payment implements Serializable { //序列化
private Long id;
private String serial;
}
-
dao
@Mapper
public interface PaymentDao {
//新增
int create(Payment payment);
//读取
Payment getPaymentById(@Param("id") Long id);
}
<mapper namespace="com.yicai.springcloud.dao.PaymentDao">
<insert id="create" parameterType="com.yicai.springcloud.entities.Payment" useGeneratedKeys="true" keyProperty="id">
insert into payment(serial) value(#{serial})
</insert>
<resultMap id="BaseResultMap" type="com.yicai.springcloud.entities.Payment">
<id property="id" column="id" jdbcType="BIGINT"></id>
<id property="serial" column="serial" jdbcType="VARCHAR"></id>
</resultMap>
<select id="getPaymentById" resultMap="BaseResultMap" parameterType="Long">
select * from payment where id=#{id}
</select>
</mapper>
-
service
public interface PaymentService {
//新增
int create(Payment payment);
//读取
Payment getPaymentById(@Param("id") Long id);
}
@Service
public class PaymentServiceImpl implements PaymentService {
@Resource
private PaymentDao paymentDao;
@Override
public int create(Payment payment) {
return paymentDao.create(payment);
}
@Override
public Payment getPaymentById(Long id) {
return paymentDao.getPaymentById(id);
}
}
-
controller
@RestController
@Slf4j
public class PaymentController {
@Autowired
private PaymentService paymentService;
@PostMapping(value = "/payment/create")
public CommonResult create(Payment payment){
int result= paymentService.create(payment);
log.info("*********插入结果:"+result);
if(result>0){
return new CommonResult(200,"插入成功",result);
}else {
return new CommonResult(444,"插入失败");
}
}
@GetMapping(value = "/payment/get/{id}")
public CommonResult getPaymentById(@PathVariable("id") Long id){
Payment payment= paymentService.getPaymentById(id);
log.info("*********插入结果:"+payment);
if(payment != null){
return new CommonResult(200,"成功",payment);
}else {
return new CommonResult(444,"没有");
}
}
}
-
测试
2.构建cloud-consumer-order80
pom文件:
<dependencies>
<!-- spring-boot-web 启动类-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- spring-boot-actuator 健康监控-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- 热更新-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
application.yaml:
server:
port: 80
主启动类:
@SpringBootApplication
public class OrderMain80 {
public static void main(String[] args) {
SpringApplication.run(OrderMain80.class,args);
}
}
业务层:
-
实体类:跟colud-provider-payment8001项目一样
-
使用RestTemplate,配置RestTempalte
@Configuration
public class ApplicationContextConfig {
@Bean
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
}
-
controller
@RestController
@Slf4j
public class OrderController {
public static final String PAYMENT_URL="http://localhost:8001";
@Resource
private RestTemplate restTemplate;
@GetMapping("/consumer/payment/create")
public CommonResult<Payment> create(Payment payment){
return restTemplate.postForObject(PAYMENT_URL+"/payment/create",payment,CommonResult.class);
}
@GetMapping("/consumer/payment/get/{id}")
public CommonResult<Payment> getPayment(@PathVariable("id") Long id){
return restTemplate.getForObject(PAYMENT_URL+"/payment/get/"+id,CommonResult.class);
}
}
-
测试
添加注解@RequestBody解决此类问题。
RestTemplate:RestTemplate提供了多种便捷访问远程Http服务的方法,是一种简单便捷的访问restful服务模板类,是Spring提供的用于访问Rest服务的客户端模板工具集。 官网:https://docs.spring.io/spring-framewprk/docs/5.2.2.RELEASE/javadoc-api/org/springframework/web/client/RestTemplate.html
快捷方式:
-
热部署(生产不建议)
-
RunDashboard
3.工程重构
工程重构:主要就是将相同代码部分组成一个module项目,将module项目打成jar的方式,在其他项目中引入,解决代码冗余。
创建cloud-api-commons模块:
pom文件:
<dependencies>
<!-- 热更新-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.6</version>
</dependency>
</dependencies>
entities:跟colud-provider-payment8001项目一样
cloud-api-commons项目clean和install,其他模块并引入jar包:
<dependency>
<groupId>com.yicai.springcloud</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
测试: