SpringCloud 是微服务一站式服务解决方案,微服务全家桶。它是微服务开发的主流技术栈。它采用了名称,而非数字版本号。

SpringCloud 和 SpringCloud Alibaba 目前是最主流的微服务框架组合。本笔记根据B站尚硅谷教程整理而成!

教程:https://www.bilibili.com/video/BV18E411x7eT

系统架构的演变

概述

  • 随着互联网的发展,网站应用的规模不断扩大,常规的应用架构已无法应对,分布式服务架构以及微服务架构势在必行,亟需一个治理系统确保架构有条不紊的演进。

单体应用架构

  • web应用程序发展的早期,大部分web工程(包含前端页面,web层代码,service层代码,dao层代码)是将所有的功能模块,打包到一起并放在一个web容器中运行。

  • 比如搭建一个电商系统:客户下订单,商品展示,用户管理。这种将所有功能度部署在一个web容器中运行的系统就叫做单体架构,目前也有人称为单体地狱。

  • 优点:

    • 所有的功能集成在一个项目工程中。
    • 项目架构简单,前期开发成本低,周期短,小型项目的首选。
  • 缺点:

    • 全部功能集成在一个工程中,对于大型项目不易开发、扩展和维护。
    • 系统性能只能通过扩展集群结点,成本高,有瓶颈。
    • 技术栈受限。
    • 代码耦合度很高。
    • 容错性差,比如用户管理出问题了,整个系统全部出问题,牵一发而动全身。

垂直应用架构

  • 当访问量逐渐增大,单一应用增加机器带来的加速度越来越小,将应用拆成互补相干的几个应用,以提高效率。

  • 优点:

    • 项目架构简单,前期开发成本低,周期daunt,小型项目的首选。
    • 通过垂直拆分,原来的单体项目不至于无线扩大。
    • 不同的项目可采用不同的技术。
    • 针对不同的子工程优化。
    • 解决高并发问题。
    • 方便水平扩展,容错性好(相对于单体架构来说的,比如上图中的商品管理出问题了,对CMS系统和后台管理系统来说没影响)。
  • 缺点:

    • 全部功能集成在一个工程中,对于大型项目不易开发、扩展和维护。
    • 系统性能扩展只能通过扩展集群结点,成本高,有瓶颈。
    • 系统间相互独立,会产生session共享问题(可以使用Redis Cluster、SpringSession等技术解决)。
    • 重复的开发工作(比如上图中的用户管理功能在电商系统和后台管理系统中都有)。

分布式SOA架构

什么是SOA?

  • SOA,全称是Service-Oriented Architecture,即面向服务的架构。它可以根据需要通过网络对松散耦合的粗粒度应用组件(服务)进行分布式部署、组合和使用。一个服务通常以独立的形式存在于操作系统进程中。

  • 站在功能的角度,把业务逻辑抽象成可复用、可组装的服务,通过服务的编排实现业务的快速再生,目的是把原先固有的业务功能转变为通用的业务服务,实现业务逻辑的快速复用。

  • 通过上面的描述可以发现SOA有如下的特点:分布式、可重用、扩展灵活、松耦合。

SOA架构

  • 当垂直应用越来越多,应用之间交互不可避免,将核心业务抽取出来,作为独立的服务,逐渐形成稳定的服务中心,使得前端应用能够更快速的响应多变的市场需求。

  • 优点:

    • 抽取公共的功能为服务,提高开发效率。
    • 对不同的服务进行集群化部署解决系统压力。
    • 基于ESB或Dubbo减少系统耦合。
  • 缺点:

    • 抽取服务的粒度较大。
    • 服务提供方和调用方接口耦合度较高。

微服务架构

  • 优点:

    • 通过服务的原子化拆分,以及微服务的独立打包、部署和升级,小团队的交付周期将会缩短,运维成本也将大幅度下降。
    • 微服务遵循单一原则。微服务之间采用RESTful等轻量级协议传输。
  • 缺点:

    • 微服务过多,服务治理成本高,不利于系统维护。
    • 分布式系统开发的技术成本高(容错、分布式事务等)。

SOA和微服务的关系

  • SOA:面向服务的架构,是一种设计方法,其中包含多个服务,服务和服务之间通过相互依赖最终提供一系列的功能。一个服务通常以独立的形式存在于操作系统的进程之中。各个服务之间通过网络调用。

  • 微服务架构:其实和SOA架构类似,微服务是SOA架构上的升华,微服务架构强调的一个重点是"业务需要彻底的组件化和服务化",原有的单个业务系统会拆分为多个可以独立开发、设计、运行的小应用。这些小应用之间通过服务完成交互和集成。

功能 SOA 微服务
组件大小 大块业务逻辑 单独任务或小块业务逻辑
耦合 通常松耦合 总是松耦合
公司架构 任何类型 小型,专注于功能交叉团队
管理 着重中央管理 着重分散管理
目标 确保应用能够交互操作 执行新功能、快速拓展开发团队

分布式核心知识

分布式的远程调用

  • RESTful。

  • RPC。

分布式中的CAP原理

  • 现如今,对于大多数大型互联网应用,分布式系统正变得越来越重要。分布式系统最大的难点,就是各个节点的状态如何同步。CAP定理是这方面的基本定理,也是理解分布式系统的起点。

  • CAP理论有Eirc Brewer在ACM研讨会上提出的,而后CAP被奉为分布式领域的重要理论。分布式系统的CAP理论,首先把分布式系统中的三个特性进行了如下的归纳。

  • C(Consistency,一致性):数据一致更新,所有数据的变化都是同步的。

  • A(Availability,可用性):在集群中一部分节点故障后,集群整体是否还能有影响客户端的读写请求。

  • P(Partition tolerance,分区容错性):某个节点的故障,并不影响整个系统的运行。

一个分布式系统里面,节点组成的网络本来应该是连通的。然而可能因为一些故障,使得有些节点之间不连通了,整个网络就分成了几块区域。数据就散布在了这些不连通的区域中。这就叫分区。

当你一个数据项只在一个节点中保存,那么分区出现后,和这个节点不连通的部分就访问不到这个数据了。这时分区就是无法容忍的。

提高分区容忍性的办法就是一个数据项复制到多个节点上,那么出现分区之后,这一数据项就可能分布到各个区里。容忍性就提高了。

然而,要把数据复制到多个节点,就会带来一致性的问题,就是多个节点上面的数据可能是不一致的。要保证一致,每次写操作就都要等待全部节点写成功,而这等待又会带来可用性的问题。

总的来说就是,数据存在的节点越多,分区容忍性越高,但要复制更新的数据就越多,一致性就越难保证。为了保证一致性,更新所有节点数据所需要的时间就越长,可用性就会降低。

作者:邬江
链接:https://www.zhihu.com/question/54105974/answer/139037688
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

选择 说明
CA 放弃分区容错性,加强一致性和可用性,其实就是传统的关系型数据库的选择
AP 放弃一致性(强一致性),追求分区容错性和可用性,这时很多分布式系统设计时的选择,比如很多NoSQL数据库就是如此
CP 放弃可用性,追求一致性和分区容错性,基本不会选择,网络问题会直接让整个系统不可用,比如zookeeper就是CP
  • 需要明确一点的是,在一个分布式系统当中,分区容错性和可用性是最基本的需求,所以在分布式系统中,我们的系统最应该关注的是AP,通过补偿机制寻求数据的一致性。

常见微服务框架

SpringCloud

  • SpringCloud是一系列框架的有序集合。它利用SpringBoot的开发便利性巧妙的简化了分布式系统基础设施的开发,如服务发现注册配置中心消息中线负载均衡熔断器数据监控等,都可以用SpringBoot的开发风格做到一键启动和部署。SpringCloud并没有重复制造轮子,它只是将目前各家公司开发的比较成熟、经得起实际考研的服务框架组合起来,通过SpringBoot风格进行再封装屏蔽掉了复杂的配置和实现原理,最终给开发者留出了一套简单易懂、易部署和易维护的分布式系统开发工具包。

Apache的ServiceComb

  • Apache ServiceCombo是业界第一个Apache微服务顶级项目,是一个开源微服务解决方案,致力于帮助企业、用户和开发者将企业应用轻松微服务化上云,并实现对微服务应用的高效运维管理。其提供一站式开源微服务解决方案,融合SDK框架级、零入侵ServerMesh场景并支持多种语言。

ZeroC ICE

  • Zeroc ICE是Zeroc公司的杰作,继承了CORBA的血统,是新一代的面向对象的分布式系统中间件。作为一种微服务架构,它基于RPC框架发展而来,具有良好的性能和分布式能力。

微服务中的相关概念

服务注册和发现

  • 服务注册:服务实例将自身服务信息注册到注册中心。这部分服务信息包括服务所在主机IP和提供服务的Port,以及暴露服务自身状态以及访问协议等信息。

  • 服务发现:服务实例请求注册中心获取所依赖服务信息。服务实例通过注册中心,获取到注册到其中的服务实例的信息,通过这些信息去其你去它们提供的服务。

负载均衡

  • 负载均衡是高可用网络基础架构的关键组件,通常用于将工作负载到多个服务器来提高网站、应用、数据库或其他服务的性能和可靠性。

熔断

  • 熔断这一概念来源于电子工程中的断路器。在互联网系统中,当下游服务因为访问压力过大而响应变慢或失败,上游服务为了保护系统整体的可用性,可以暂时切断对下游服务的调用。这种牺牲局部,保全整体的措施就叫熔断。

链路追踪

  • 随着微服务架构的流行,服务按照不同的纬度进行拆分,一次请求往往需求涉及到多个服务。互联网应用构建在不同的软件模块上,这些软件模块,有可能是由不同的团队开发,可能使用不同的编程语言来实现、有可能部署在几千台服务器上,横跨多个不同的数据中心。因此,就需要对一次请求涉及的多个服务链路进行日志记录,性能监控即链路追踪。

API网关

  • 随着微服务的不断增多,不同的微服务一般会有不同的网络地址,而外部客户端可能需要调用多个服务的接口才能完成一个业务需求,如果让客户端直接和各个微服务通信可能出现:

  • 客户端需要调用不同的URL地址,增加难度。

  • 在一定的场景下,存在跨域请求的问题。

  • 每个微服务都需要进行单独的身份认证。

  • 针对上面的问题,API网关顺势而生。

  • API网关直面意思是将所有API调用统一接入到API网关层,由网关层统一接入和输出。一个网关的基本功能有:统一接入、安全防护、协议适配、流量监管、长短链接支持、容错能力。有了网关之后,各个API服务提供团队可以专注于自己的业务逻辑处理,而API网关更专注于安全、流量和路由等问题。

SpringCloud

SpringCloud概述

  • Spring Cloud是一系列框架的有序集合。它利用Spring Boot的开发便利性巧妙地简化了分布式系统基
    础设施的开发,如服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等,都可以用
    Spring Boot的开发风格做到一键启动和部署。Spring Cloud并没有重复制造轮子,它只是将目前各家
    公司开发的比较成熟、经得起实际考验的服务框架组合起来,通过Spring Boot风格进行再封装屏蔽掉
    了复杂的配置和实现原理,最终给开发者留出了一套简单易懂、易部署和易维护的分布式系统开发工具
    包 。

SpringCloud的架构

参考资料,尽量去官网

SpringCloud 官网:https://spring.io/projects/spring-cloud#learn

SpringCloud 官方文档:https://cloud.spring.io/spring-cloud-static/Hoxton.SR1/reference/htmlsingle/

SpringBoot 官网:https://spring.io/projects/spring-boot#learn

SpringBoot 官方文档:https://docs.spring.io/spring-boot/docs/2.2.2.RELEASE/reference/htmlsingle/

Spring Cloud中文文档:https://www.bookstack.cn/read/spring-cloud-docs/docs-index.md

SpringCloud中的核心组件

  • Spring Cloud的本质是在 Spring Boot 的基础上,增加了一堆微服务相关的规范,并对应用上下文
    (Application Context)进行了功能增强。既然 Spring Cloud 是规范,那么就需要去实现,目前
    Spring Cloud 规范已有 Spring官方,Spring Cloud Netflix,Spring Cloud Alibaba等实现。通过组件
    化的方式,Spring Cloud将这些实现整合到一起构成全家桶式的微服务技术栈。

  • Spring Cloud Netflix组件 :

组件名称 作用
Eureka 服务注册中心
Ribbon 客户端负载均衡
Feign 声明式服务调用
Hystrix 客户端容错保护
Zuul API服务网关
  • Spring Cloud Alibaba组件 :
组件名称 作用
Nacos 服务注册中心
Sentinel 客户端容错保护
  • Spring Cloud原生及其他组件 :
组件 作用
Consul 服务注册中心
Config 分布式配置中心
Gateway API服务网关
Sleuth/Zipkin 分布式链路追踪

SpringCloud的体系结构

  • 从上图可以看出Spring Cloud各个组件相互配合,合作支持了一套完整的微服务架构。

  • 注册中心负责服务的注册与发现,很好将各服务连接起来。

  • 断路器负责监控服务之间的调用情况,连续多次失败进行熔断保护。

  • API网关负责转发所有对外的请求和服务。

  • 配置中心提供了统一的配置信息管理服务,可以实时的通知各个服务获取最新的配置信息 。

SpringCloud和SpringBoot的对应版本

版本选择:

  • 可以通过浏览器查看版本对应关系:https://start.spring.io/actuator/info

    • json信息可以通过工具格式化:https://tool.lu/
  • springboot gitub 源码地址:https://github.com/spring-projects/spring-boot/releases
  • springboot 官网查看版本:https://spring.io/projects/spring-boot#learn
  • springcloud 官网查看版本:https://spring.io/projects/spring-cloud#learn

查看官网:https://spring.io/projects/spring-cloud#overview,拖到下面查看官方给出的版本对应关系。

例如以如下版本对应为例:

模拟微服务

工程步骤:

  • 1、New Project
  • 2、聚合总父工程名字
  • 3、Maven选版本
  • 4、工程名字
  • 5、字符编码
  • 6、注解生效激活
  • 7、java编译版本选8

开始构建

构建父工程 spring_cloud_atguigu_2020 ,后面的项目模块都在此工程中:

设置编码:Settings -> Editor-> File Encodings

注解激活:

选择java编译版本:

文件过滤,可以不设置(这样就显示不出来这些文件了,有的文件看着有点烦):

父工程 pom 配置

删掉 src 目录,只留 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>com.itjing.springcloud</groupId><artifactId>spring_cloud_atguigu_2020</artifactId><version>1.0-SNAPSHOT</version><!--第一步--><packaging>pom</packaging><!-- 统一管理 jar 包版本 --><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><maven.compiler.source>1.8</maven.compiler.source><maven.compiler.target>1.8</maven.compiler.target><junit.version>4.12</junit.version><log4j.version>1.2.17</log4j.version><lombok.version>1.16.18</lombok.version><mysql.version>5.1.47</mysql.version><druid.version>1.1.16</druid.version><mybatis.spring.boot.version>1.3.0</mybatis.spring.boot.version></properties><!-- 子模块继承之后,提供作用:锁定版本 + 子module不用写 groupId 和 version --><dependencyManagement><dependencies><dependency><groupId>org.apache.maven.plugins</groupId><artifactId>maven-project-info-reports-plugin</artifactId><version>3.0.0</version></dependency><!-- 下面三个基本是微服务架构的标配 --><!--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><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></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>

上面配置的解释:

首先要加

<packaging>pom</packaging>

聚合版本依赖,dependencyManagement声明依赖,并不实现引入,所以子项目还需要写要引入的依赖。

第一个微服务架构

步骤:

  1. 建模块 module
  2. 改 pom
  3. 写yml
  4. 主启动
  5. 业务类

提供者

在父工程中新建子模块:cloud-provider-payment8001

建子模块后父工程变化

查看父工程 pom 文件变化,多了 modules标签

<modules><module>cloud-provider-payment8001</module>
</modules>

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"><parent><artifactId>spring_cloud_atguigu_2020</artifactId><groupId>com.itjing.springcloud</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>cloud-provider-payment8001</artifactId><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!--图形化--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency><!--mybatis整合spring依赖--><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.1.10</version></dependency><!--mysql-connector-java--><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><!--lombok--><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>
</project>

配置文件

在 resources 目录下新建 application.yml

# 端口号
server:port: 8001
spring:application:name: cloud-payment-service# 数据源datasource:type: com.alibaba.druid.pool.DruidDataSourcedriver-class-name: com.mysql.jdbc.Driverurl: jdbc:mysql://localhost:3306/springcloud2020?useUnicode=true&characterEncoding=utf-8&useSSL=falseusername: rootpassword: 123456# mybatis 相关
mybatis:mapper-locations: classpath:mapper/*.xmltype-aliases-package: com.itjing.springcloud.entities  # 所有Entity 别名类所在包

主启动类

package com.itjing.springcloud;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class PaymentMain8001 {public static void main(String[] args) {SpringApplication.run(PaymentMain8001.class, args);}
}

业务类

五步:

  • 建表sql
  • entities
  • dao
  • service
  • controller
建库建表

创建数据库:springcloud2020,建表:payment

CREATE TABLE `payment` (`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',`serial` varchar(200) DEFAULT '',PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
实体类
package com.itjing.springcloud.entities;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;@Data
@AllArgsConstructor
@NoArgsConstructor
public class Payment implements Serializable {private Long id;private String serial;
}
Json封装体

真正做开发的时候,可以自定义枚举类处理,具体去查询百度学习。

package com.itjing.springcloud.entities;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;/*** 如果前后端分离,这个是提供给前端信息和数据的类** @param <T>*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class CommonResult<T> {private Integer code;private String messgae;private T data;/*** 查询为空的时候使用的构造器** @param code* @param messgae*/public CommonResult(Integer code, String messgae) {this(code, messgae, null);}
}
Dao 接口
package com.itjing.springcloud.dao;import com.itjing.springcloud.entities.Payment;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;@Mapper
public interface PaymentDao {public int create(Payment payment);public Payment getPaymentById(@Param("id") Long id);
}
Mapper映射文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.itjing.springcloud.dao.PaymentDao"><insert id="create" parameterType="Payment" useGeneratedKeys="true" keyProperty="id">insert into payment(serial) values (#{serial})</insert><!--养成好习惯,使用结果映射,因为可能会由于下划线,驼峰命名造成不必要的错误--><resultMap id="BaseReslutMap" type="com.itjing.springcloud.entities.Payment"><id column="id" property="id" jdbcType="BIGINT"/><result column="serial" property="serial" jdbcType="VARCHAR"/></resultMap><select id="getPaymentById" parameterType="Long" resultMap="BaseReslutMap">select id,serial from payment where id = #{id}</select>
</mapper>
Service接口及其实现类
package com.itjing.springcloud.service;import com.itjing.springcloud.entities.Payment;
import org.apache.ibatis.annotations.Param;public interface PaymentService {public int create(Payment payment);public Payment getPaymentById(@Param("id") Long id);
}
package com.itjing.springcloud.service.impl;import com.itjing.springcloud.dao.PaymentDao;
import com.itjing.springcloud.entities.Payment;
import com.itjing.springcloud.service.PaymentService;
import org.springframework.stereotype.Service;import javax.annotation.Resource;@Service
public class PaymentServiceImpl implements PaymentService {@Resourceprivate PaymentDao paymentDao;@Overridepublic int create(Payment payment) {return paymentDao.create(payment);}@Overridepublic Payment getPaymentById(Long id) {return paymentDao.getPaymentById(id);}
}
Controller控制器
package com.itjing.springcloud.controller;import com.itjing.springcloud.entities.CommonResult;
import com.itjing.springcloud.entities.Payment;
import com.itjing.springcloud.service.PaymentService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;import javax.annotation.Resource;@RestController   //必须是这个注解,因为是模拟前后端分离的 restful风格的请求,要求每个方法返回 json
@Slf4j
public class PaymentController {@Resourceprivate PaymentService paymentService;@PostMapping(value = "/payment/payments")public CommonResult create(Payment payment) {int result = paymentService.create(payment);log.info("****插入结果:" + result);if (result > 0) {return new CommonResult(200, "插入数据库成功", result);}return new CommonResult(444, "插入数据库失败", null);}@GetMapping(value = "/payment/{id}")public CommonResult getPaymentById(@PathVariable("id") Long id){Payment result = paymentService.getPaymentById(id);log.info("****查询结果:" + result);if(result != null){return new CommonResult(200, "查询成功", result);}return new CommonResult(444, "没有对应id的记录", null);}
}
测试

使用 postman 工具进行测试,自测通过!

SpringBoot热部署的流程

pom文件中导入 spring-boot-devtools依赖:

(或者创建springboot工程时,勾选devtools选项,会自动在pom中加入依赖)

<!--SpringBoot热部署配置 -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><scope>runtime</scope><optional>true</optional>
</dependency>

继续在父工程的 pom.xml 中添加插件:

<build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><!--SpringBoot热部署时配置 --><configuration><fork>true</fork><addResources>true</addResources></configuration><!--SpringBoot热部署时配置 --></plugin></plugins>
</build>

设置application.properties

#配置项目热部署
spring.devtools.restart.enabled=true

在idea中设置自动编译

1.打开Settings,设置当前项目自动编译,搜索Compiler,勾选Build project automatically

2.打开Other Settings ,设置新建的项目都自动编译,搜索Compliler,勾选Build project automatically

3.按住ctrl + shift + alt + /,出现如下图所示界面,点击Registry…

4.点击进入后,勾选compiler.automake.allow.when.app.running后关闭即可

重启IDEA!

通过以上步骤,就完成了SpringBoot项目的热部署功能!!!

消费者

步骤参考提供者。

创建子模块:cloud-consumer-order80

消费者现在只模拟调用提供者的Controller方法,没有持久层配置,只有Controller和实体类

当然也要配置主启动类和启动端口

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"><parent><artifactId>spring_cloud_atguigu_2020</artifactId><groupId>com.itjing.springcloud</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>cloud-consumer-order80</artifactId><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!--图形化--><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><!--lombok--><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>
</project>

配置文件

server:port: 80spring:application:name: cloud-order-service

主启动类

package com.itjing.springcloud;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class OrderMain80 {public static void main(String[] args) {SpringApplication.run(OrderMain80.class, args);}
}

业务类

实体类

将 提供者 中的 CommonResult 和 Payment 拷贝过来,创建

服务调用概述
  • 在用户下单的时候需要调用商品微服务获取商品数据,那么应该需要怎么做呢?商品微服务提供了供人调用的HTTP接口,所以下订单的时候使用HTTP请求的相关工具类完成,如常见的HttpClient、OkHttp,当然也可以使用Spring提供的RestTemplate
RestTemplate介绍
  • Spring框架提供的RestTemplate类可用于在应用中调用RESTful服务,它简化了和HTTP服务的通信方式,统一了RESTful的标准,封装了HTTP的链接,我们只需要传入URL和返回值类型即可。相较于之前常用的HttpClient、OkHttp等,RestTemplate是一种更加优雅的调用RESTful服务的方式。

  • 在Spring应用程序中访问第三方REST服务和Spring的RestTemplate类有关。RestTemplate类的设计原则和许多其他Spring模块类(例如JdbcTemplate、JmsTemplate)相同,为执行复杂任务提供了一种具有默认行为的简化方法。

  • RestTemplate默认依赖JDK提供HTTP连接的能力(HttpURLConnection),如果有需要的话也可以通过setRequestFactory方法替换为如Apache HttpComponents、Netty或OkHttp等其他HTTP库。

  • 考虑到RestTemplate类是为调用REST服务而设计的,因此他的主要方法和REST的基础紧密相连就不足为奇,后者是HTTP协议的方法:HEAD、GET、POST、PUT、DELETE和OPTIONS。例如,RestTemplate类具有headForHeaders()、getForObject()等方法。

向Spring容器中注册RestTemplate
package com.itjing.springcloud.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;@Configuration
public class ApplicationContextConfig {@Beanpublic RestTemplate restTemplate() {return new RestTemplate();}
}
Controller控制器
package com.itjing.springcloud.controller;import com.itjing.springcloud.entities.CommonResult;
import com.itjing.springcloud.entities.Payment;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;import javax.annotation.Resource;@RestController
@Slf4j
public class OrderController {//远程调用的 地址public static final String PAYMENT_URL = "http://localhost:8001";@Resourceprivate RestTemplate restTemplate;@PostMapping("consumer/payment/create")public CommonResult<Payment> create(Payment payment) {/**param1 请求地址,param2 请求参数, param3 返回类型*/return restTemplate.postForObject(PAYMENT_URL + "/payment/payments", payment, CommonResult.class);}@GetMapping("consumer/payment/{id}")public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id) {return restTemplate.getForObject(PAYMENT_URL + "/payment/" + id, CommonResult.class);}
}
测试

启动 服务提供者:cloud-provider-payment8001

启动服务消费者:cloud-consumer-order80

这时候右下角会弹出 Run Dashboard 提示,我们应该让它显示出来,以后微服务多了,我们需要它管理。

访问消费者的接口进行测试!

发现执行添加操作的时候,数据库中的数据为 null,是因为之前的 服务提供者中 没有加 @RequestBody 注解

//   注意这里的 @RequestBody  是必须要写的,虽然 MVC可以自动封装参数成为对象,
//  但是当消费者项目调用,它传参是 payment 整个实例对象传过来的, 即Json数据,因此需要写这个注解public CommonResult create(@RequestBody Payment payment){...}

工程重构

上面的两个子模块,有多次重复的导入jar,和重复的 Entity 实体类

可以把多余的部分,加入到一个独立的模块中,将这个模块打包,并提供给需要使用的 module 。

1、新建一个 cloud-api-commons 子模块

2、将 entities 包里面的实体类复制到这个子模块中,将所需依赖引入 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"><parent><artifactId>spring_cloud_atguigu_2020</artifactId><groupId>com.itjing.springcloud</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>cloud-api-commons</artifactId><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.1.0</version></dependency><!--关于这个hutool 是个功能强大的工具包,官网:https://hutool.cn/--></dependencies>
</project>

3、将此项目打包 install 到 maven仓库

先 clean,再 install

4、改造提供者和消费者,将 提供者 和 消费者 两个项目中的 entities 包删除。

5、将 打包到 maven 仓库的 cloud-api-commons 模块,引入到 提供者 和 消费者的 pom 文件中,如下所示

<!-- 引入自己定义的api通用包-->
<dependency><groupId>com.itjing.springcloud</groupId><artifactId>cloud-api-commons</artifactId><version>${project.version}</version>
</dependency>

分析模拟微服务中存在的问题

  • 服务调用者将微服务的请求路径硬编码到Java代码中。

  • 不能对微服务负载均衡的调用,因为请求路径的URL硬编码了。

  • 服务多起来,对前端调用不友好,需要加入API网关。

  • 微服务多起来的话,如果每次都需要重新修改配置文件,很麻烦,需要配置的统一管理。

  • 链路追踪。

  • 系统容错。

  • ……

SpringCloud-Alibaba之入门相关推荐

  1. SpringCloud Alibaba 从入门到精通(精选)

    SpringCloud Alibaba 从入门到精通 一. 课程介绍 1.1 课程导学 1.2 项目环境搭建 二. SpringBoot基础 2.1 本章概述 2.2 Spring Boot是什么?能 ...

  2. SpringCloud从入门到精通教程/SpringCloud Alibaba从入门到精通教程

    对于SpringCloud,很多小伙伴问到了我的研究学习资料来源,除官方文档外,特例完整整理一下自己的平时参考学习其他资料,以及分享实战项目源码和代码资源,供大家参考学习 主要教程:SpringClo ...

  3. Spring Cloud Alibaba - Sentinel入门案例(四)(热点规则 )

    Spring Cloud Alibaba - Sentinel入门案例(四)(热点规则 ) 回溯 什么是Sentinel? 正文 环境准备 简单使用 复杂使用 注意事项 回溯 什么是Sentinel? ...

  4. 关于SpringCloud Alibaba,动力节点的这份笔记教程真香

    什么是Spring Cloud Alibaba? 首先我们需要了解一下Spring Cloud,然后再来了解Spring Cloud Alibaba: Spring Cloud 源自官方描述: Spr ...

  5. Spring Cloud Alibaba - Gateway 入门案例(二)(Gateway 整合 nacos /(非阿里组件))

    Spring Cloud Alibaba - Gateway 入门案例(二)(Gateway 整合 nacos)(非阿里组件) 回溯 Gateway 整合 nacos 方式一(复杂/灵活/常用) 方式 ...

  6. SpringCloud Alibaba入门

    1.springcloud alibaba 1.1主要功能 服务限流降级:默认支持WebService.WebFlux.OpenFeign.RestTemplate.SpringCloudGatewa ...

  7. Springboot 集成Springcloud gateway的入门

    最近做项目使用到了springcloude gateway作为网关,因此在此记录下springcloud gateway的入门操作,后续再将源码解读写出来,先立个flag. 回归正题,Springcl ...

  8. SpringCloud—07—高级之SpringCloud Alibaba上

    文章目录 提前预知 17.SpringCloud Alibaba入门简介 17.1.为什么会出现SpringCloud alibaba 18.Spring Cloud Alibaba Nacos服务注 ...

  9. 最新微服务框架SpringCloud Alibaba介绍,搭建

    微服务和SpringCloud Alibaba详细介绍(一),手把手搭建微服务框架 PS:本博客是本人参照B站博主:JAVA阿伟如是说 的视频讲解手敲整理的笔记 跟着一起手动搭建的框架 供大家一起学习 ...

  10. Spring Cloud Alibaba基础入门,一周学会基操!

    Spring Cloud Alibaba基础入门,一周学会基操! 服务拆分: 1.不同微服务,不要重复开发相同业务 2.微服务数据独立,不要访问其它微服务的数据库 3.微服务可以将自己的业务暴露为接口 ...

最新文章

  1. FaceNet: A Unified Embedding for Face Recognition and Clustering
  2. scrapy 中不同页面的拼接_scrapy官方文档提供的常见使用问题
  3. python使用方法-Python的使用方法
  4. 鼠標滑過表格整行改變背景色
  5. 下防火墙命令与centos7下防火墙命令区别
  6. jupyter lab文档位置默认system_九大神招,让Python里数据分析神器Jupyter,完美升华...
  7. Spark-shell和Spark-hive的使用
  8. Java注释--单行注释、多行注释、文档注释
  9. OpenGL开发库的详细介绍
  10. 矩阵论16 17 18 19
  11. c ringbuffer 源码_Python Ring Buffer的实现
  12. python建模用什么库_Python 建模库介绍 - 树懒学堂
  13. 华为交换机Hybird 与 单臂路由
  14. iOS面试题大全2021(附答案)
  15. 如何申请注册Tom企业邮箱,教程详解来袭
  16. 沙特阿美以246亿元收购荣盛石化10%股份,还将在中国东北建设大型炼化一体化项目...
  17. F5LTM(一)逻辑关系图
  18. arcpy——利用Arcpy进行字段操作
  19. CISC(复杂指令集)与RISC(精简指令集)的区别
  20. 0CTF/TCTF 2021 Quals_Misc_singer

热门文章

  1. 如何合并同一个磁盘里面的两个区(卷)
  2. python画出K线图及技术指标
  3. error C2678
  4. 2020年拼多多数据分析一面
  5. C++与OpenCV同时批量处理图像数据
  6. 人数全球第一,但现在中国的问题不是人太多,而是太少 | 浪潮工作室
  7. web前端期末大作业——HTML+CSS简单的旅游网页设计与实现
  8. 【机器学习】强化学习算法的优化
  9. NDP1415 40V输入20A外置MOS大电流同步降压控制器IC
  10. 第二届童装品牌团2015年春夏联展