Spring Cloud Alibaba 实战
一、目标
- 理解什么是微服务架构
- 理解什么是springcloud及spring cloud alibaba和springcloud的关系
- 掌握使用springcloud alibaba 实现微服务远程调用
- 掌握使用springcloud alibaba 实现服务注册与发现
- 掌握使用springcloud alibaba 实现基本的服务配置
二、微服务架构
2.1 架构的演变
(1)单一应用架构
当网站流量很小时,只需要一个应用,所有功能部署在一起,减少部署节点成本的框架称之为集中式框架。此时,用于简化增删改查工作量的数据访问框架(ORM)是影响项目开发的关键。
(2)垂直应用架构
当访问量逐渐增大,单一应用增加机器带来的加速度越来越小,将应用拆成互不相干的几个应用,以提升效率。此时,用于加速前端页面开发的Web框架(MVC)是关键。
(3)分布式服务架构
当垂直应用越来越多,应用之间交互不可避免,将核心业务抽取出来,作为独立的服务,逐渐形成稳定的服务中心,使前端应用能更快速的响应多变的市场需求。此时,用于提高业务复用及整合的分布式服务框架(RPC)是关键。
(4)面向服务(SOA)架构
典型代表有两个:流动计算架构和微服务架构;
流动计算架构:
当服务越来越多,容量的评估,小服务资源的浪费等问题逐渐显现,此时需增加一个调度中心基于访问压力实时管理集群容量,提高集群利用率。此时,用于提高机器利用率的资源调度和治理中心(SOA)是关键。流动计算架构的最佳实践阿里的Dubbo。
微服务架构
与流动计算架构很相似,除了具备流动计算架构优势外,微服务架构中的微服务可以独立部署,独立发展。且微服务的开发不会限制于任何技术栈。微服务架构的最佳实践是SpringCloud及Spring Cloud Alibaba。
2.2 微服务架构
微服务架构(MicroserviceArchitect)是一种架构模式,它提倡将单块架构的应用划分成一组小的服务,服务之间互相协调、互相配合,为用户提供最终价值。每个服务运行在其独立的进程中,服务与服务间采用轻量级的通信机制互相沟通。每个服务都围绕着具体业务进行构建,并且能够被独立的部署到生产环境、类生产环境(测试环境)等.
相比传统SOA的服务实现方式,微服务更具有灵活性、可实施性以及可扩展性,其强调的是一种独立测试、独立部署、独立运行的软件架构模式。
即便了解了上面的介绍,也很难对微服务下一个准确的定义。实际上,从业界的讨论来看,微服务本身并没有一个严格的定义,ThoughtWorks首席科学家马丁福勒对微服务进行的一段描述:
微服务架构是一种架构模式,它提倡将单一应用程序划分成一组小的服务,服务之间互相协调、互相配合,为用户提供最终价值。每个服务运行在其独立的进程中,服务与服务间采用轻量级的通信机制互相沟通(通常是基于HTTP协议的RESTful API)。每个服务都围绕着具体业务进行构建,并且能够被独立的部署到生产环境、类生产环境等。另外,应当尽量避免统一的、集中式的服务管理机制,对具体的一个服务而言,应根据业务上下文,选择合适的语言、工具对其进行构建。
微服务架构特点总结:
小, 且专注于做一件事情;
独立的进程中;
轻量级的通信机制;
松耦合、独立部署;
简单理解:
将原本所有的功能放到一个应用中的系统,根据功能模块 进行合理的拆分 拆分成独立的 可运行和部署的子系统;子系统之间通过轻量级协议进行通信(http),我们将这种架构称为微服务架构。
三、Spring Cloud Alibaba
3.1 Spring cloud
微服务架构也会带来一些问题需要我们去解决,例如:
服务通信用什么解决?
服务管理用什么解决?
服务越来越多,配置文件越来越多该如何统一管理?
...
以上都可以通过一些现有的技术框架来解决,但是这些技术框架需要整合在一块相对对开发人员的技术要求较高,另外也有些兼容性问题需要解决。相对比较麻烦。所以如果有一个框架 能解决上边的问题,并且隐藏掉技术细节,框架极好的集成和兼容就再好不过了,所以技术框架下就有了spring cloud 和spring cloud alibaba.
以下摘自百度百科:
Spring Cloud是一系列框架的有序集合。它利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等,都可以用Spring Boot的开发风格做到一键启动和部署。Spring Cloud并没有重复制造轮子,它只是将各家公司开发的比较成熟、经得起实际考验的服务框架组合起来,通过Spring Boot风格进行再封装屏蔽掉了复杂的配置和实现原理,最终给开发者留出了一套简单易懂、易部署和易维护的分布式系统开发工具包.
简单理解总结一句话:
spring cloud 是基于springboot的开发工具包,是将流行的成熟的框架整合到一块。目的:就是简化配置,提供一套简单易用的工具用于快速开发分布式系统(微服务),提高开发效率。
3.2 Spring cloud alibaba
同 Spring Cloud 一样,Spring Cloud Alibaba 也是一套微服务解决方案,包含开发分布式应用微服务的必需组件,方便开发者通过 Spring Cloud 编程模型轻松使用这些组件来开发分布式应用服务。
依托 Spring Cloud Alibaba,您只需要添加一些注解和少量配置,就可以将 Spring Cloud 应用接入阿里微服务解决方案,通过阿里中间件来迅速搭建分布式应用系统。
https://github.com/alibaba/spring-cloud-alibaba/blob/master/README-zh.md
提供的功能和组件包括如下:
Spring Cloud 和Spring Cloud Alibaba的关系:可以简单理解成 集团和子公司的关系。
3.3 使用版本注意
spring cloud的版本说明:
SpringCloud是一系列框架组合,为了避免与框架版本产生混淆,采用新的版本命名方式,形式为大版本名+子版本名称
大版本名用伦敦地铁站名
子版本名称三种
SNAPSHOT:快照版本,尝鲜版,随时可能修改
M版本,MileStone,M1表示第一个里程碑版本,一般同时标注PRE,表示预览版
SR,Service Release,SR1表示第一个正式版本,同时标注GA(Generally Available),稳定版
另外:
最新版本已经更新了不再以地铁名为依据,并移除掉了一些组件例如:spring cloud netflex 中的一些组件
新的命名方式说明大家可以看下官方说明:
https://spring.io/blog/2020/04/17/spring-cloud-2020-0-0-m1-released
spring cloud alibaba使用的时候版本说明:
重要:鉴于SpringBoot与SpringCloud关系,SpringBoot建议采用2.2.x版本或者2.3.x,这里我们采用的版本为:
Hoxton SR9
spring boot 2.3.8
四、微服务远程调用
4.1 应用场景
以上就是有个应用场景例如:订单微服务 需要获取到商品信息,则需要订单微服务 远程调用 商品微服务获取到商品的信息,然后再返回给用户展示。
4.2 Spring Cloud OpenFeign介绍
Spring Cloud OpenFeign 是声明式的服务调用工具,它整合了Ribbon等其他组件,拥有负载均衡和服务容错功能.
Feign是声明式的服务调用工具,我们只需创建一个接口并用注解的方式来配置它,就可以实现对某个服务接口的调用,简化了直接使用RestTemplate来调用服务接口的开发量。Feign具备可插拔的注解支持,同时支持Feign注解、JAX-RS注解及SpringMvc注解。当使用Feign时,Spring Cloud集成了Ribbon和Eureka以提供负载均衡的服务调用.
fegin 本身是一个组件 整合到spring cloud 之后 就命名为spring cloud openFeign.
4.3 OpenFeign入门使用
基于以上的应用场景,通过代码的方式入门服务调用有多简单。
开发步骤:
1.搭建工程 管理版本
2.创建2个微服务
3.加入起步依赖 并实现远程调用
4.3.1 创建工程
如上图所示:cloud-test工程pom.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.itheima</groupId>
<artifactId>cloud-test</artifactId>
<version>1.0-SNAPSHOT</version>
<modules>
<module>cloud-test-consumer</module>
<module>cloud-test-provider</module>
</modules>
<packaging>pom</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.8.RELEASE</version>
</parent>
<properties>
<!--spring cloud版本-->
<spring.cloud-version>Hoxton.SR9</spring.cloud-version>
<!--jdk版本-->
<java.version>1.8</java.version>
<skipTests>true</skipTests>
</properties>
<dependencyManagement>
<dependencies>
<!--spring cloud-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring.cloud-version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--spring cloud alibaba-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.2.5.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>
cloud-test-provider工程pom.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">
<parent>
<artifactId>cloud-test</artifactId>
<groupId>com.itheima</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cloud-test-provider</artifactId>
<dependencies>
<!--配置feign-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!--web起步依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<!--springboot maven插件-->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
启动类:
@SpringBootApplication
public class ProviderApplication {
public static void main(String[] args) {
SpringApplication.run(ProviderApplication.class,args);
}
}
yml:
server:
port: 8081
spring:
application:
name: provider
cloud-test-consumer工程pom.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">
<parent>
<artifactId>cloud-test</artifactId>
<groupId>com.itheima</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cloud-test-consumer</artifactId>
<dependencies>
<!--web起步依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--配置feign-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<!--springboot maven插件-->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
启动类:
@SpringBootApplication
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class,args);
}
}
yml:
server:
port: 8080
spring:
application:
name: consumer
4.3.2 实现远程调用
provider端创建商品controller:
@RestController
public class ItemController {
/**
* 获取商品的信息
*
* @param id
* @return
*/
@GetMapping("/item/{id}")
public String getInfo(@PathVariable(name = "id") String id) {
String itemInfo = "SN:" + id;
return itemInfo;
}
}
consumer端创建订单controller,并实现远程调用:
@RestController
public class OrderController {
@Autowired
private ItemFeign itemFeign;
@GetMapping("/doOrder")
public String doOrder() {
//1.模拟远程调用获取到到商品信息
String info = itemFeign.getItemInfo("1");
//2.模拟下单
System.out.println("张三:下单成功,商品信息为:"+info);
//3.模拟返回成功信息
return info;
}
}
按照feign的使用创建feign接口:
@FeignClient(name="provider",url = "127.0.0.1:8081")
public interface ItemFeign {
/**
* 根据用户ID 获取用户名
* @param id
* @return
*/
@GetMapping("/item/{id}")
String getItemInfo(@PathVariable(name="id") String id);
}
解释:
@FeignClient(name="provider",url = "127.0.0.1:8081") 指定注解 标识 该类为Feign接口
name 指定要调用的服务名(目前随便填)
url 指定要调用的服务(provider)的ip和端口
该接口中的方法 和 被调用方法的controller中保持一致(即是应当声明一个接口的方法 和 controller一致)
@GetMapping("/item/{id}")
String getItemInfo(@PathVariable(name="id") String id);
接口编写的要求如下:
1.接口的方法返回值 和 被调用方controller中的方法的返回值保持一致
2.接口的方法的请求路径 和 被调用方controller中的请求路径保持一致
3.接口的参数类型和参数个数 和被调用方controller中的方法的参数类型和个数保持一致
4.接口的方法参数需要修饰注解,并设置相关属性例如:@PathVariable(name = "id") @RequestParam(name="name") @RequestBody
简单记忆:和被调用方的编写一致即可。
启动类中添加注解启用feignclients:
@SpringBootApplication
@EnableFeignClients
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class,args);
}
}
五、微服务注册与发现
5.1 NACOS介绍
5.1.1 应用场景
当服务调用越来越多,服务的地址需要管理起来,并实现动态调用而不是硬编码在接口中。此时需要一个注册中心来帮助我们管理服务。
1.商品微服务注册IP和端口到注册中心
2.订单微服务先从注册中心获取到商品微服务的IP和端口
3.订单微服务中使用获取到的IP和端口执行远程调用
5.1.2 NACOS介绍
NACOS是一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。简单来说:NACOS就是一个注册中心 ,用来实现服务的注册与发现。
Github:https://github.com/alibaba/Nacos
5.2 NACOS作为注册中心使用
如上图所示 ,当我们将NACOS作为注册中心来使用,那么就需要满足三个条件 有一个注册 有两个微服务 并且向注册中心进行注册并发现服务 实现远程调用。
使用步骤:
1.搭建nacos注册中心
2.搭建微服务并向nacos进行注册
3.实现远程调用。
5.2.1 搭建注册中心
(1)下载 zip 如图所示
(2)解压zip
(3)双击如图所示的脚本启动
(4)访问地址验证是否启动成功
浏览器中访问:http://localhost:8848/nacos
输入用户名和密码:
nacos/nacos
出现如下画面说明搭建正确:
5.2.2 实现服务的注册与发现
实现步骤
1.搭建微服务consumer 并实现注册与发现
2.搭建微服务provider 并实现注册与发现
3.修改feign 实现远程调用(非硬编码方式)
5.2.2.1 消费端
(1)在cloud -consumer-test工程中添加依赖:(依赖的版本参考之前的使用版本注意)
可以参考官方说明:
https://nacos.io/zh-cn/docs/quick-start-spring-cloud.html
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
(2)启动类中添加注解如下:
(3)yaml中进行配置:
5.2.2.2 提供端
(1)在cloud -provider-test工程中添加依赖:(依赖的版本参考之前的使用版本注意)
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
(2)启动类中添加注解 开启服务注册和发现
(3)配置yaml
(4)进行测试查看:
启动consumer 和provider 和注册中心
在nacos的控制台界面就可以看到如下效果:
1619323958652
5.2.2.3 动态远程调用
修改接口之后,重新启动一次 再次进行调用如下效果:
照样能获取到结果。
控制台输出如下
由此可以看出:实际上nacos添加之后,默认从注册中心根据服务名动态获取到ip和端口 并实现远程调用。
六、微服务实现服务配置
6.1 应用场景
随着业务的发展、微服务架构的升级,服务的数量、程序的配置日益增多(各种微服务、各种服务器地址、各种参数),传统的配置文件方式和数据库的方式已无法满足开发人员对配置管理的要求:
- 安全性:配置跟随源代码保存在代码库中,容易造成配置泄漏
- 时效性:修改配置,需要重启服务才能生效
- 局限性:无法支持动态调整:例如日志开关、功能开关
因此,我们需要配置中心来统一管理配置文件。例如:一旦配置修改,则应用即可立即生效。不需要重启微服务。
6.2 NACOS作为配置中心使用
以上,配置中心 可以有很多的技术,这里我们使用NACOS作为配置中心使用也是可以的。结合之前我们使用的注册中心 NACOS 可以两用。
使用步骤:
1.需求:获取配置文件中的jdbc.url中的值,并可以在线进行编辑修改 不需要重启系统即能生效
2.搭建配置中心服务
3.搭建微服务(consumer或者provider)此处我们以consumer来作为案例
4.实现在线编辑 之后立即生效
6.2.1 搭建配置中心
该配置中心已经搭建,就是之前搭建的nacos server端。控制台如下,将来我们的配置文件全部在如下左框所示下进行配置。
6.2.2 微服务中使用Nacos
6.2.2.1 添加起步依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
6.2.2.2 配置yaml
6.2.2.3 控制台(配置中心)进行配置
(稍微注意下目前就是只能用properites)
6.2.2.4 代码中进行测试
@RestController
@RefreshScope
public class OrderController {
@Autowired
private ItemFeign itemFeign;
@Value("${jdbc.url}")
private String url;
@GetMapping("/doOrder")
public String doOrder() {
//1.模拟远程调用获取到到商品信息
String info = itemFeign.getItemInfo("1");
//2.模拟下单
System.out.println("张三:下单成功,商品信息为:"+info);
//3.模拟返回成功信息
//4.模拟配置信息获取 打印
System.out.println("值为:"+url);
return info;
}
}
浏览器中输入:http://localhost:8080/doOrder
再次修改配置中心的配置值
再发送请求:
七、总结
讲解了如下内容:
什么是微服务架构,
springcloud是什么以及springcloud aliaba是什么及他们的关系
spring cloud alibaba的入门实战 实现:
远程调用
服务发现和注册
服务的配置
项目资源:大牛详解Spring Cloud Alibaba技术栈