(四)项目接入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.ymlbootstrap.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配置文件(上面提到一个命名空间对应一个项目)

image-20210128221137804

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})
原文地址:https://www.cnblogs.com/six-hc/p/14359409.html