(四)项目接入springcloud alibaba
SpringCloud Alibaba简介
简介
Spring Cloud Alibaba 致力于提供微服务开发的一站式解决方案。此项目包含开发分布式应用 微服务的必需组件,方便开发者通过 Spring Cloud 编程模型轻松使用这些组件来开发分布 式应用服务。 依托 Spring Cloud Alibaba,您只需要添加一些注解和少量配置,就可以将 Spring Cloud 应用 接入阿里微服务解决方案,通过阿里中间件来迅速搭建分布式应用系统。
SpringCloud的优劣势
SpringCloud 的几大痛点
SpringCloud 部分组件停止维护和更新,给开发带来不便;
SpringCloud 部分环境搭建复杂,没有完善的可视化界面,我们需要大量的二次开发和定制
SpringCloud 配置复杂,难以上手,部分配置差别难以区分和合理应用
SpringCloud Alibaba 的优势:
阿里使用过的组件经历了考验,性能强悍,设计合理,现在开源出来大家用
成套的产品搭配完善的可视化界面给开发运维带来极大的便利
搭建简单,学习曲线低。
结合 SpringCloud Alibaba 我们最终的技术搭配方案:
SpringCloud Alibaba - Nacos:注册中心(服务发现/注册)
SpringCloud Alibaba - Nacos:配置中心(动态配置管理)*
SpringCloud - Ribbon:负载均衡
SpringCloud - Feign:声明式 HTTP 客户端(调用远程服务)
SpringCloud Alibaba - Sentinel:服务容错(限流、降级、熔断)
SpringCloud - Gateway:API **网关(webflux **编程模式)
SpringCloud - Sleuth:调用链监控
SpringCloud Alibaba - Seata:原 Fescar,即分布式事务解决方案
版本选择
springcloud alibaba和springcloud、springboot的版本对应关系,详情见github网址
- 1.5.x 版本适用于 Spring Boot 1.5.x
- 2.0.x 版本适用于 Spring Boot 2.0.x
- 2.1.x 版本适用于 Spring Boot 2.1.x
- 2.2.x 版本适用于 Spring Boot 2.2.x
注意:springcloud alibaba和spring cloud也有版本对应关系。
项目接入SpringCloud Alibaba
在父工程的pom.xml文件加入依赖
<dependencyManagement>
<dependencies>
<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>
</dependencies>
</dependencyManagement>
上面是依赖管理,这样在子工程里引spring cloud alibaba就不用写版本号, 全用dependencyManagement进行管理
Nacos
Nacos 是阿里巴巴开源的一个更易于构建云原生应用的动态服务发现、配置管理和服务管理 平台。他是使用 java 编写。需要依赖 java 环境
项目引入nacos
在common项目中加入依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
由于在父工程已统一管理jar包版本,这里不需要在声明版本换号。
下面举例在window下下载并启动nacos服务:
1、下载nacos
要将项目注册到注册中心,首先我们需要一个nacos服务器,下载地址为https://github.com/alibaba/nacos/releases。
2、启动nacos
下载完成后,双击bin目录的startup.cmd文件启动后,访问http://localhost:8848/nacos/,初始账号密码都是nacos
3、在各个项目的application.yml
文件配置注册中心
spring:
application:
name: gulimmall-coupon # 每一个应用都应该有名字,这样才能注册上去
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
4、在springboot的主启动类加上@EnableDiscoveryClient
注解开启服务注册与发现功能。
Feign远程调用
feign是一个声明式的HTTP客户端,他的目的就是让远程调用更加简单。给远程服务发的是HTTP请求。
如会员服务想要远程调用优惠券服务,只需要给会员服务里引入openfeign依赖,他就有了远程调用其他服务的能力。下面我们用这两个服务举例。
1、在common项目加入feign依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
2、在启动类上加注解@EnableDiscoveryClient
3、在启动类上加注解@EnableFeignClients(basePackages="")
,basePackages指定远程调用功能放的基础包
下面我们就用会员服务调用优惠券服务举例:
1、在会员服务和优惠券服务的pom.yml
文件加入feign依赖
2、在会员服务的启动类上加上@EnableDiscoveryClient
和@EnableFeignClients(basePackages="com.atguigu.gulimall.member.feign")
/*
* 想要远程调用的步骤:
* 1 引入openfeign
* 2 编写一个接口,接口告诉springcloud这个接口需要调用远程服务
* 2.1 在接口里声明@FeignClient("gulimall-coupon")他是一个远程调用客户端且要调用coupon服务
* 2.2 要调用coupon服务的/coupon/coupon/member/list方法
* 3 开启远程调用功能 @EnableFeignClients,要指定远程调用功能放的基础包
* */
@EnableFeignClients(basePackages="com.atguigu.gulimall.member.feign")
@EnableDiscoveryClient
@SpringBootApplication
public class gulimallMemberApplication {
public static void main(String[] args) {
SpringApplication.run(gulimallMemberApplication.class, args);
}
}
3、在会员服务com.atguigu.gulimall.member.feign
包下新建一个接口,并加上注解@FeignClient("gulimall-coupon")
指定我们要调的服务是优惠券服务(gulimall-coupon已注册在注册中心)
@FeignClient("gulimall-coupon") //告诉spring cloud这个接口是一个远程客户端,要调用coupon服务,再去调用coupon服务/coupon/coupon/member/list对应的方法
public interface CouponFeignService {
@RequestMapping("/coupon/coupon/member/list")//这个路径指向优惠券服务的controller方法地址
public R membercoupons();//得到一个R对象
}
4、优惠券服务的controller提供一个方法给会员服务调用
@RequestMapping("coupon/coupon")
public class CouponController {
@Autowired
private CouponService couponService;
@RequestMapping("/member/list")
public R membercoupons(){ //全系统的所有返回都返回R
// 应该去数据库查用户对于的优惠券,但这个我们简化了,不去数据库查了,构造了一个优惠券给他返回
CouponEntity couponEntity = new CouponEntity();
couponEntity.setCouponName("满100-10");//优惠券的名字
return R.ok().put("coupons",Arrays.asList(couponEntity));
}
5、在会员服务的controller写一个测试方法,去调用优惠券服务
@RequestMapping("/coupons")
public R test(){
MemberEntity memberEntity = new MemberEntity();
memberEntity.setNickname("会员昵称张三");
R membercoupons = couponFeignService.membercoupons();//假设张三去数据库查了后返回了张三的优惠券信息
//打印会员和优惠券信息
return R.ok().put("member",memberEntity).put("coupons",membercoupons.get("coupons"));
}
启动优惠券和会员服务,访问会员服务的测试方法,
http://localhost:8000/member/member/coupons
使用nacos作为配置中心
为什么需要配置中心?
假设我们的应用上线了,这时候我们需要修改配置文件的一些值,按传统的方式我们要停掉应用,修改配置文件后重新打包部署。当我们的应用部署在10台机器上,那么需要对这10台机器都做同样的操作,非常的费劲。
当我们有配置中心了,就不需重新打包部署,可以热部署配置文件。
项目接入nacos配置中心
1、引入pom依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
2、在bootstrap.yml
或bootstrap.properties
文件配置
spring:
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848
file-extension: yaml #指定yaml格式的配置
注意:一定要在bootstrap.yml或bootstrap.properties文件配置,不能在application.yml/application.properties文件配置。
3、在nacos建立一个Data ID为 项目名.yaml 的文件(配置文件的类型在第二步file-extension
指定)
4、若实现配置热加载,在Controller上添加 @RefreshScope
注解
nacos加载多配置集
前面我们知道,在bootstrap.yml
配置好nacos后,项目启动会自动加载nacos服务器上 项目名.yaml配置文件。但实际情况下,我们的配置文件不那么简单。
有以下几种情况:
1、为了代码可阅读性,我们不把配置都配置在一个文件,而是分开配置,如db.xml、mybatis.xml等等。项目如何加载多个nacos的配置文件?
2、项目在开发环境和生产环境的配置不同,如何保证指定环境启动时服务能正确读取到nacos上相应环境的配置文件?
3、一个大型微服务有很多个子项目,每个子项目又有自己的开发环境、测试环境和生产环境。怎么对这些微服务配置进行管理呢?
问题一可以在bootstrap.yml
使用以下属性来解决:
#配置文件一
spring.cloud.nacos.config.extension-configs[0].data-id=datasource.yml
spring.cloud.nacos.config.extension-configs[0].group=dev
spring.cloud.nacos.config.extension-configs[0].refresh=true
#配置文件二
spring.cloud.nacos.config.extension-configs[1].data-id=mybatis.yml
spring.cloud.nacos.config.extension-configs[1].group=dev
spring.cloud.nacos.config.extension-configs[1].refresh=true
#配置文件三
spring.cloud.nacos.config.extension-configs[2].data-id=other.yml
spring.cloud.nacos.config.extension-configs[2].group=dev
spring.cloud.nacos.config.extension-configs[2].refresh=true
nacos使用 namespace(命名空间)+Group(分组)+Data ID来唯一标识一个配置文件,不同的项目对应不同的命名空间,使用分组来区分环境(dev、test、prod),Data ID为配置文件的名字。这样可以解决第二、第三个问题。
springcloud getway网关
网关是请求浏览的入口,常用功能包括路由转发,权限校验,限流控制等。
三大核心概念
- Route: The basic building block of the gateway. It is defined by an ID, a destination URI, a collection of predicates断言, and a collection of filters. A route is matched if the aggregate predicate is true.发一个请求给网关,网关要将请求路由到指定的服务。路由有id,目的地uri,断言的集合,匹配了断言就能到达指定位置,
- Predicate断言: This is a Java 8 Function Predicate. The input type is a Spring Framework
ServerWebExchange
. This lets you match on anything from the HTTP request, such as headers or parameters.就是java里的断言函数,匹配请求里的任何信息,包括请求头等 - Filter: These are instances of Spring Framework
GatewayFilter
that have been constructed with a specific factory. Here, you can modify requests and responses before or after sending the downstream request.过滤器请求和响应都可以被修改。
项目接入springcloud getway
1、创建一个新名为gulimall-gateway
的Module,在pom文件加入依赖
<dependency>
<groupId>io.niceseason.gulimall</groupId>
<artifactId>gulimall-common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
2、在主启动类上加上@EnableDiscoveryClient
注解
3、在nacos中创建gateway命名空间,同时在该命名空间中创建gulimall-gateway.yaml
配置文件(上面提到一个命名空间对应一个项目)
4、创建``bootstrap.yml`文件,添加如下配置,指明配置中心地址和所属命名空间
spring:
cloud:
nacos:
config:
namespace: ea1519c4-9046-407d-b8ca-e003a43bdbc9
server-addr: 127.0.0.1:8848
5、创建application.yml文件,指定服务名和注册中心地址
spring:
application:
name: gulimall-gateway
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
server:
port: 88
6、在application.yml
配置路由
spring:
cloud:
gateway:
routes:
- id: test_route
uri: https://www.baidu.com
predicates:
- Query=foo,ba.
- id: qq_route
uri: https://www.qq.com
predicates:
- Query=toUrl,reg
其中Query=toUrl的意思是,当请求路径存在参数toUrl,且这个参数满足正则表达式reg时,则路由到uri指定的网址https://www.qq.com。
如我们请求路径http://localhost:88/gateway/toUrl=reg时,会自动帮我们路由到https://www.qq.com/toUrl=reg
7)启动“gulimall-gateway”
启动报错:
Description:
Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured.
Reason: Failed to determine a suitable driver class
解决方法:在“io.niceseason.gulimall.gulimallgateway.GulimallGatewayApplication”中排除和数据源相关的配置
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})