Spring Cloud 教程(二) | 搭建SpringCloudAlibaba
- 前言
- 一、SpringBoot 与 SpringCloud 版本对应关系:
- 二、SpringCloud 与 SpringCloudAlibaba版本对应关系:
- 三、SpringCloudAlibaba版本 与 组件版本 对应关系:
- 四、搭建SpringCloudAlibaba 项目
- 1. 聚合工程搭建
- 2. 集成nacos-discovery,实现服务注册和发现
- 3. 集成OpenFeign,实现Feign调用
- 1.引入OpenFeign 和 LoadBalancer 依赖(这两个要一起用)
- 2. 商品服务加入测试代码
- 3. 用户服务 准备 Feign调用 商品服务
- 4. 集成Loadbalancer,实现负载均衡
- 5. 集成 sentinel,实现流量卫兵的监控
- 6. 集成 nacos-config,实现配置中心
- 7. 集成 gateway,实现云梯网关
前言
通过上一篇文章,我们得知目前最新的都是 SpringCloud 第二代(Spring Cloud + Alibaba)这一套
接下来,就是针对于如何搭建SpringCloudAlibaba.
一、SpringBoot 与 SpringCloud 版本对应关系:
- 1 进入 SpringCloud 官网
地址: https://spring.io/projects/spring-cloud/#overview
这里列出了 SpringCloud 的最近几个版本,在往下看也说明了 关于Spring Cloud的Dalston、Edgware、Finchley、Greenwich、2020.0(aka Ilford)、2021.0(aka Jubilee)和2022.0(aka Kilburn)版本已经达到生命周期终止状态且不再受支持的情况。
Spring Cloud Dalston, Edgware, Finchley, Greenwich, 2020.0 (aka Ilford), 2021.0 (aka Jubilee), and 2022.0 (aka Kilburn) have all reached end of life status and are no longer supported.
以看到它的命名规则是 YYYY.MINOR.MICRO ;其中 YYYY 代表年份,MINOR 每年都从 0 开始;MICRO 是小版本;
在 SpringCloud 概览的页面我们选择任意一个版本进入,就可以看到改大版本下都有哪些小版本:
可以看出这个 2021 版本下的最新版本为 2021.0.8 版本的
二、SpringCloud 与 SpringCloudAlibaba版本对应关系:
【方式 1】点击 gitcode 地址 即可查看
【方式 2】点击 github 地址 即可查看
点击 版本说明 即可查看
老版本说明如下(我这边是SpringBoot为 2.6.13):
使用我的 spring-cloud-alibaba-dependencies 即为 2021.0.5.0 版本
三、SpringCloudAlibaba版本 与 组件版本 对应关系:
点击 组件版本关系 即可查看
我这边用的是2021.0.5.0 版本
四、搭建SpringCloudAlibaba 项目
1. 聚合工程搭建
使用Maven聚合工程创建微服务架构
- alibaba-common 服务:公共服务,包含各种通用的工具类、常量定义、异常类等
- alibaba-user 服务:用户服务
- alibaba-product 服务:商品服务
创建步骤就是 springboot搭建聚合工程一样的操作
聚合父工程的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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>spring-cloud-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-cloud-demo</name>
<description>Demo project for Spring Boot</description>
<!-- 一般来说父级项目的packaging都需要改为pom,packaging默认类型jar类型-->
<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-boot.version>2.6.13</spring-boot.version>
</properties>
<!-- 模块说明:这里声明多个子模块 -->
<modules>
<module>alibaba-common</module>
<module>alibaba-user</module>
<module>alibaba-product</module>
</modules>
<dependencies>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--spring cloud 2021.0.8-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>2021.0.8</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--spring cloud alibaba 2021.0.5.0-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2021.0.5.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- common 公共模块-->
<dependency>
<groupId>com.example</groupId>
<artifactId>alibaba-common</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>
然后以 alibaba-user 用户服务为例(三部曲:引依赖,写配置文件,写启动类):
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-demo</artifactId>
<groupId>com.example</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>alibaba-user</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>com.example</groupId>
<artifactId>alibaba-common</artifactId>
</dependency>
</dependencies>
</project>
配置文件如下:
用户服务给的端口 是6666,商品服务给的端口 是6667
注意一下:我这边使用这些端口6000 区域 的,使用浏览器直接请求接口会显示为:
“嗯… 无法访问此页面,网址为http://127.0.0.1:6667/product/list 的页面可能存在问题,或者已永久移动到新的网址。”
原因是:端口号 6000 区域的 并不是被普遍认为是“不安全”的端口,但浏览器可能基于其安全策略或配置限制了对该端口的访问。
所以后面我测试的时候用的是 postman工具,或者你可以改成浏览器支持安全的端口,例如:8000区域
server.port=6666
spring.application.name=alibabauser
启动类如下:
package com.example.alibabauser;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class AlibabaUserApplication {
public static void main(String[] args) {
SpringApplication.run(AlibabaUserApplication.class,args);
}
}
alibaba-product 服务 也是如上操作,这里就不具体写了。
2. 集成nacos-discovery,实现服务注册和发现
在 alibaba-common 公共服务 的pom.xml 添加 nacos 依赖
<?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-demo</artifactId>
<groupId>com.example</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>alibaba-common</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<!--provided 意味着打包的时候可以不用包进去-->
<scope>provided</scope>
</dependency>
<!--nacos client-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
</dependencies>
</project>
alibaba-user 服务 和 alibaba-product 服务 的配置文件
都加上以下naocos配置
#配置 nacos 地址
spring.cloud.nacos.discovery.server-addr=localhost:8848
#表示暴露所有端点
management.endpoints.web.exposure.include=*
nacos 服务器安装启动以后(这里就不细说了。需要去下载winows版本的naocs,然后改成单例启动),然后启动 alibaba-user 服务 和 alibaba-product 服务
请求 http://localhost:8848/nacos ,就可以看到Nacos的页面上面出现了两个服务,说明成功注册到Nacos服务中心
3. 集成OpenFeign,实现Feign调用
1.引入OpenFeign 和 LoadBalancer 依赖(这两个要一起用)
在 alibaba-common 公共服务 的pom.xml 添加 openfeign 依赖 和 loadBalancer 依赖
<!--openfeign(要和客户端负载均衡器一起用) -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!--客户端负载均衡器-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
2. 商品服务加入测试代码
在 alibaba-product 服务 加 Controller 代码
package com.example.alibabaproduct.controller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
@RestController
@RequestMapping("/product")
public class ProductController {
private static final Logger logger = LoggerFactory.getLogger(ProductController.class);
@GetMapping("/list")
public Map list() {
logger.info("进入商品服务===,端口号:6667");
HashMap<String , Object> map = new HashMap<>();
map.put("这里是商品服务,端口号:",6667);
map.put("苹果",10);
map.put("辣条",7);
return map;
}
}
3. 用户服务 准备 Feign调用 商品服务
在 用户服务的 入口类加入@EnableFeignClients 注解
package com.example.alibabauser;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableFeignClients
public class AlibabaUserApplication {
public static void main(String[] args) {
SpringApplication.run(AlibabaUserApplication.class,args);
}
}
在 用户服务的 下面创建 feign目录 ,添加 feign接口
1.需要在feign接口接口上面加上@FeignClient注解,name值为 应用的名称(你想调用哪个服务的就填哪个服务)
2.把你想调用商品服务的那个方法,复制到这个feign接口 下面。
package com.example.alibabauser.feign;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import java.util.Map;
@FeignClient(name = "alibabaproduct")
public interface ProductFeign{
@GetMapping("/product/list")
Map list();
}
在 用户服务的 加 Controller 代码
package com.example.alibabauser.controller;
import com.example.alibabauser.feign.ProductFeign;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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 java.util.Map;
@RestController
@RequestMapping("/user")
public class UserController {
private static final Logger logger = LoggerFactory.getLogger(UserController.class);
@Autowired
private ProductFeign productFeign;
@GetMapping("/list")
public Map list() {
logger.info("进入用户服务===,端口号:6666");
Map list = productFeign.list();
return list;
}
}
接着启动两个服务,请求127.0.0.1:6666/user/list
会发现请求成功到了商品那边的接口。说明feign的调用方式成功了
4. 集成Loadbalancer,实现负载均衡
我们根据 商品alibaba-product 服务 再 复制一份 为 alibaba-product-6668 服务 出来,来验证负载均衡的。
记住要想实现负载均衡,这个 spring.application.name 是重点
spring.application.name(用于配置应用程序名称的配置项)
- 在单个Spring Boot应用程序内部,spring.application.name 的值是唯一的,因为它用于标识该应用程序本身。在同一个JVM实例中运行的Spring Boot应用程序通常不会有两个相同的spring.application.name。
- 在微服务架构中,spring.application.name 通常用作服务注册到服务发现组件(如Nacos、Eureka、Consul等)时的服务名称。在这种情况下,不同的微服务实例可以有相同的 spring.application.name,因为它们代表相同类型的服务,但运行在不同的物理或虚拟节点上。服务发现组件通过服务名称、实例ID、端口号等信息来区分不同的服务实例。
alibaba-product-6668 服务 和 alibaba-product 服务 的 spring.application.name 值都为 alibabaproduct
启动项目以后,你会在nacos里面看到以下情况
执行 127.0.0.1:6666/user/list 时,会发现有时候去了 商品服务6667 ,有时候去了商品服务6668
5. 集成 sentinel,实现流量卫兵的监控
如果没有 下载sentinel 控制台,请先确定版本后,在下载winows版本的
下载地址为:https://github.com/alibaba/Sentinel/releases
在 alibaba-common 公共服务 的pom.xml 添加 sentinel 依赖
<!--sentinel依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
然后配置alibaba-user,alibaba-product服务的配置文件
# sentinel配置
# 指定Sentinel控制台的地址,默认是8080
spring.cloud.sentinel.transport.dashboard=127.0.0.1:8858
# 指定客户端与Sentinel控制台交互的端口,默认是8719
spring.cloud.sentinel.transport.port=8719
#启用Eager模式,可提前处理流量控制,缺点增加应用程序的启动时间
spring.cloud.sentinel.eager=true
启动服务以后,请求访问http://localhost:8858 控制台 你就可以看到 你的服务已经被监控了
6. 集成 nacos-config,实现配置中心
在 alibaba-common 公共服务 的pom.xml 添加 nacos-config 依赖
<!--nacos统一配置中心管理依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
然后nacos新建一个命名空间:
我这边起名叫:生产环境
点击加号,进入新增页面,把 Data ID、Group、配置格式、配置内容 都填好
我这边以用户服务为例子,配置内容就是我们之前写在 application.properties 文件里面的内容
然后在到 用户 服务里面新增一个 前缀为 bootstrap.properties文件
再把之前application.properties 的内容清空也行,直接删除也行
为什么需要使用 bootstrap前缀的文件?
由于application配置文件的加载优先级低于bootstrap配置文件,如果Nacos的配置信息放在application配置文件中,那么在应用启动时可能会因为还未连接到Nacos服务器而无法加载这些配置。
虽然不是强制要求,但将Nacos的配置信息放在bootstrap配置文件中是最佳实践。
如果出现 错误 “No spring.config.import property has been defined
”,
表示 springcloud新版默认禁用了bootstrap,如果需要使用bootstrap需要自己手动引入对应的依赖。
于是在 公共服务 的maven中加上以下依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
bootstrap.properties 内容如下
#应用程序名称
spring.application.name=alibabauser
#配置 nacos 地址
spring.cloud.nacos.discovery.server-addr=localhost:8848
# nacos的配置文件读取配置
#命名空间ID
spring.cloud.nacos.config.namespace=fb3c1759-401b-4607-9bce-5e3d43590a0b
#分组配置
spring.cloud.nacos.config.group=DEFAULT_GROUP
#以下配置构成了Nacos上的dataId值
spring.cloud.nacos.config.prefix=user
spring.profiles.active=prod
项目再次启动,发现在读取到 user-prod.properties 里面端口配置6666及sentinel连接配置,说明读取ok.
7. 集成 gateway,实现云梯网关
新建一个module(alibaba-gateway)并引入依赖
(mvc的web依赖跟gateway依赖冲突,所以gateway依赖自己单独引入非web,或者排除掉web)
冲突原因如下:
冲突主要源于Spring Cloud Gateway是基于WebFlux框架实现的,它默认使用非阻塞的I/O模型,
而spring-boot-starter-web则是基于Servlet API构建的,用于传统的阻塞式Web开发。
我这边使用的是排除,完整的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>spring-cloud-demo</artifactId>
<groupId>com.example</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>alibaba-gateway</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<!--gateway依赖-->
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!-- common 公共模块-->
<dependency>
<groupId>com.example</groupId>
<artifactId>alibaba-common</artifactId>
<version>0.0.1-SNAPSHOT</version>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</project>
接着 创建启动类
创建完以后,把4个服务全部启动
先通过云梯请求用户服务
http://127.0.0.1:7666/user/list ,多请求几次,发现负载均衡的,一会6667,6668
再通过云梯请求商品服务
http://127.0.0.1:7666/product/list ,多请求几次,发现也是负载均衡的,一会6667,6668
参考文章
【1】idea 搭建springcloud+springcloud alibaba项目(maven)