【谷粒商城】开发篇三:微服务组件 SpringCloud & SpringCloud Alibaba

谷粒商城微服务应用说明

【谷粒商城】开发篇三:微服务组件 SpringCloud & SpringCloud Alibaba_第1张图片

SpringCloud Alibaba

SpringCloud Alibaba 简介

SpringCloud Alibaba 简介

  • Spring Cloud Alibaba 致力于提供微服务开发的一站式解决方案。此项目包含开发分布式应用微服务的必需组件,方便开发者通过Spring Cloud 编程模型轻松使用这些组件来开发分布式应用服务。

  • 依托Spring Cloud Alibaba,我们只需要添加一些注解和少量配置,就可以将Spring Cloud 应用接入阿里微服务解决方案,通过阿里中间件来迅速搭建分布式应用系统。

  • github地址:https://github.com/alibaba/spring-cloud-alibaba
    【谷粒商城】开发篇三:微服务组件 SpringCloud & SpringCloud Alibaba_第2张图片

为什么使用SpringCloud Alibaba

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 整合

详细可以参考官方文档:https://spring.io/projects/spring-cloud-alibaba

  • 在 gulimall-common 中引入SpringCloud Alibaba的依赖版本号管理,这样在引入其中某个组件的时候就不用标明版本号了
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>com.alibaba.cloudgroupId>
                <artifactId>spring-cloud-alibaba-dependenciesartifactId>
                <version>2.1.0.RELEASEversion>
                <type>pomtype>
                <scope>importscope>
            dependency>
        dependencies>
    dependencyManagement>
    

SpringCloud Alibaba - Nacos【作为注册中心】

Nacos 是阿里巴巴开源的一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。他是使用Java编写,需要依赖java 环境。

Nacos 文档地址: https://nacos.io/zh-cn/docs/quick-start.html

Nacos 配置:https://github.com/alibaba/spring-cloud-alibaba
【谷粒商城】开发篇三:微服务组件 SpringCloud & SpringCloud Alibaba_第3张图片

nacos-server 下载并启动

Nacos Server 支持直接下载和源码构建两种方式,可以参考官网。

这里我使用Docker部署Naccos,参考:https://blog.csdn.net/qq_36389060/article/details/132418204

Nacos【注册中心】微服务集成

  • 在gulimall-common中引入 Nacos【注册中心】依赖
    <dependency>
        <groupId>com.alibaba.cloudgroupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-configartifactId>
    dependency>
    
  • 增加配置,在微服务应用的 /src/main/resources/application.yml 配置文件中配置 Nacos Server 地址,并设置微服务的名称
    spring:
      cloud:
        nacos:
          discovery:
            server-addr: 192.168.217.138:8848
       application:
       	name: gulimall-coupon
    
  • 使用 @EnableDiscoveryClient 注解开启服务注册与发现功能
    @EnableDiscoveryClient
    @MapperScan("com.atguigu.gulimall.coupon.dao")
    @SpringBootApplication
    public class GulimallCouponApplication {
    	public static void main(String[] args) {
    		SpringApplication.run(GulimallCouponApplication.class, args);
    	}
    }
    
  • 启动服务,注册成功
    【谷粒商城】开发篇三:微服务组件 SpringCloud & SpringCloud Alibaba_第4张图片

SpringCloud Alibaba - Nacos【作为配置中心】

详细可以参考官方文档:https://github.com/alibaba/spring-cloud-alibaba
【谷粒商城】开发篇三:微服务组件 SpringCloud & SpringCloud Alibaba_第5张图片
在没有配置中心之前,传统应用配置的存在以下痛点:

  • 采用本地静态配置,无法保证实时性:修改配置不灵活且需要经过较长的测试发布周期,无法尽快通知到客户端,还有些配置对实时性要求很高,比方说主备切换配置或者碰上故障需要修改配置,这时通过传统的静态配置或者重新发布的方式去配置,那么响应速度是非常慢的,业务风险非常大。

  • 易引发生产事故:比如在发布的时候,容易将测试环境的配置带到生产上,引发生产事故。

  • 配置散乱且格式不标准:有的用properties格式,有的用xml格式,还有的存DB,团队倾向自造轮子,做法五花八门。

  • 配置缺乏安全审计、版本控制、配置权限控制功能:谁?在什么时间?修改了什么配置?无从追溯,出了问题也无法及时回滚到上一个版本;无法对配置的变更发布进行认证授权,所有人都能修改和发布配置。

而配置中心区别于传统的配置信息分散到系统各个角落的方式,对系统中的配置文件进行集中统一管理,而不需要逐一对单个的服务器进行管理。那这样做有什么好处呢?

  • 通过配置中心,可以使得配置标准化、格式统一化。

  • 当配置信息发生变动时,修改实时生效,无需要重新重启服务器,就能够自动感知相应的变化,并将新的变化统一发送到相应程序上,快速响应变化。比方说某个功能只是针对某个地区用户,还有某个功能只在大促的时段开放,使用配置中心后只需要相关人员在配置中心动态去调整参数,就基本上可以实时或准实时去调整相关对应的业务。

  • 通过审计功能还可以追溯问题。

这里我遇到了无法从Nacos获取动态配置的问题,如果大家遇到可以参考这篇文章。

Nacos【配置中心】微服务集成

在gulimall-common中引入 Nacos【配置中心】依赖

<dependency>
    <groupId>com.alibaba.cloudgroupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-configartifactId>
dependency>

补充说明:Springboot配置文件加载顺序

其实yml和properties文件是一样的原理,且一个项目上要么yml或者properties,二选一的存在。推荐使用yml,更简洁。

(1)加载顺序:这里主要是说明application和bootstrap的加载顺序。

  • bootstrap.yml(bootstrap.properties)先加载

  • application.yml(application.properties)后加载

  • bootstrap.yml 用于应用程序上下文的引导阶段。

  • bootstrap.yml 由父Spring ApplicationContext加载。

(2)配置区别

  • bootstrap.yml 和application.yml 都可以用来配置参数。

  • bootstrap.yml 可以理解成系统级别的一些参数配置,这些参数一般是不会变动的。application.yml 可以用来定义应用级别的。

在应用的 /src/main/resources/bootstrap.properties 配置文件中配置 Nacos Config 地址并引入服务配置

提示:bootstrap.properties 会优先于 application.properties 或 application.yml 进行加载。

spring:
  cloud:
    nacos:
      serverAddr: 192.168.217.138:8848
  config:
    import:
      - nacos:nacos-config-example.properties?refresh=true

Nacos 添加配置

以gulimall-coupon服务为例,当我们配置好Nacos配置中心后,启动服务后,控制台会打印如下内容,表明可以从Nacos中名为 gulimall-coupon.properties 的配置文件中读取配置信息。

Located property source: CompositePropertySource {name='NACOS', propertySources=[NacosPropertySource {name='gulimall-coupon.properties'}]}

创建配置文件:需要给Nacos配置中心默认添加一个 数据集(Data Id),这里为gulimall-coupon.properties。默认规则为 应用名.properties

【谷粒商城】开发篇三:微服务组件 SpringCloud & SpringCloud Alibaba_第6张图片
【谷粒商城】开发篇三:微服务组件 SpringCloud & SpringCloud Alibaba_第7张图片

  • 发布的配置可以在配置列表中看到
    【谷粒商城】开发篇三:微服务组件 SpringCloud & SpringCloud Alibaba_第8张图片

如果想动态获取配置还需要在Controller上加 @RefreshScope 注解动态获取并刷新配置

注意: 如果配置中心和当前应用的配置文件中都配置了相同的项,优先使用配置中心的配置。

@RestController
@RequestMapping("coupon/coupon")
@RefreshScope
public class CouponController {
}

代码测试能否动态获取配置信息

  • 测试代码
    @RestController
    @RequestMapping("coupon/coupon")
    @RefreshScope
    public class CouponController {
        @Autowired
        private CouponService couponService;
    
        @Value("${coupon.user.name}")
        private String name;
        @Value("${coupon.user.age}")
        private Integer age;
    
        @RequestMapping("/test")
        public R test(){
    
            return R.ok().put("name",name).put("age",age);
        }
    }
    
  • 本地应用配置文件内容
    在这里插入图片描述
  • Nacos配置中心文件内容
    在这里插入图片描述
  • 测试结果
    【谷粒商城】开发篇三:微服务组件 SpringCloud & SpringCloud Alibaba_第9张图片

Nacos 命名空间 - 配置隔离

命名空间的核心作用是用来进行配置隔离。

不同的命名空间下,可以存在相同的 Group 或Data ID 的配置。默认为 public(保留空间),默认新增的所有配置都在public空间。

Namespace 的常用场景之一是不同环境的配置的区分隔离,例如开发测试环境和生产环境的资源(如配置、服务)隔离等。

  • 创建开发,测试,生产环境命名空间,利用命名空间来做环境隔离。
    【谷粒商城】开发篇三:微服务组件 SpringCloud & SpringCloud Alibaba_第10张图片
    【谷粒商城】开发篇三:微服务组件 SpringCloud & SpringCloud Alibaba_第11张图片

  • 为gulimall-coupon创建开发环境下的配置
    【谷粒商城】开发篇三:微服务组件 SpringCloud & SpringCloud Alibaba_第12张图片
    【谷粒商城】开发篇三:微服务组件 SpringCloud & SpringCloud Alibaba_第13张图片

  • 在bootstrap.properties上指定使用哪个命名空间下的配置

    spring.cloud.nacos.config.namespace=e523efec-62db-4526-be4d-451f8055677e
    

    在这里插入图片描述

命名空间除了上面基于环境进行配置隔离的创建方式,也可以每一个微服务都创建自己的命名空间,只加载自己命名空间下的所有配置,实现每一个微服务之间互相隔离配置。

Naocs 配置集【所有的配置的集合】

一组相关或者不相关的配置项的集合称为配置集。在系统中,一个配置文件通常就是一个配置集,包含了系统各个方面的配置。例如,一个配置集可能包含了数据源、线程池、日志级别等配置项。

Naocs 配置集ID(Data ID)

  • Data ID:类似文件名
    【谷粒商城】开发篇三:微服务组件 SpringCloud & SpringCloud Alibaba_第14张图片

Nacos 克隆配置

【谷粒商城】开发篇三:微服务组件 SpringCloud & SpringCloud Alibaba_第15张图片
可以发现有四个名称空间:public(默认)以及我们自己添加的3个名称空间(prod、dev、test),可以点击查看每个名称空间下的配置文件,当然现在只有public下有一个配置。

默认情况下,项目会到public下找 服务名.properties文件。

接下来,在dev名称空间中也添加一个nacos-provider.properties配置。这时有两种方式:

  • 方式一:切换到dev名称空间,添加一个新的配置文件。缺点是每个环境都要重复配置类似的项目

  • 方式二:直接通过clone方式添加配置,并修改即可。推荐使用
    【谷粒商城】开发篇三:微服务组件 SpringCloud & SpringCloud Alibaba_第16张图片

Nacos 配置分组(Group)

  • 默认所有的配置集都属于:DEFAULT_GROUP【谷粒商城】开发篇三:微服务组件 SpringCloud & SpringCloud Alibaba_第17张图片

  • 每个微服务创建自己的命名空间,然后使用配置分组区分环境(dev、test、prod)【谷粒商城】开发篇三:微服务组件 SpringCloud & SpringCloud Alibaba_第18张图片

  • 使用配置分组的时候需要在bootstrap.properties中指定使用的配置分组

    spring.cloud.nacos.config.group=dev
    

Nacos 同时加载多个配置集

在一些情况下需要加载多个配置文件。假如gulimall-coupon现在dev名称空间下有三个配置文件:

  • 数据源配置文件 datasource.yml

  • MyBatis配置文件 mybatis.yml

  • 其它配置信息文件 other.yml
    【谷粒商城】开发篇三:微服务组件 SpringCloud & SpringCloud Alibaba_第19张图片

  • 在bootstrap.properties中指定多个配置集

    spring.cloud.nacos.config.server-addr=192.168.217.138:8848
    # 指定命名空间
    spring.cloud.nacos.config.namespace=603d4bc4-6e92-4487-990a-4de97625433e
    # 指定多个配置集
    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
    
  • 将原有application.yml中的配置信息全部注释进行测试,从控制台打印信息中可以看到服务加载的Nacos配置文件

    [subscribe] mybatis.yml+dev+603d4bc4-6e92-4487-990a-4de97625433e
    [subscribe] other.yml+dev+603d4bc4-6e92-4487-990a-4de97625433e
    [subscribe] datasource.yml+dev+603d4bc4-6e92-4487-990a-4de97625433e
    

SpringCloud

Feign - 声明式远程调用

Feign 简介

Feign 是一个声明式的HTTP 客户端,它的目的就是让远程调用更加简单。Feign 提供了HTTP请求的模板,通过编写简单的接口和插入注解,就可以定义好HTTP 请求的参数、格式、地址等信息。

Feign 整合了Ribbon(负载均衡)和Hystrix(服务熔断),可以让我们不再需要显式地使用这两个组件。

SpringCloudFeign 在NetflixFeign 的基础上扩展了对SpringMVC 注解的支持,在其实现下,我们只需创建一个接口并用注解的方式来配置它,即可完成对服务提供方的接口绑定。简化了 SpringCloudRibbon 自行封装服务调用客户端的开发量。

Feign微服务集成

这里以gulimall-member服务调用gulimall-coupon服务为例进行讲解

引入依赖

<dependency>
	<groupId>org.springframework.cloudgroupId>
	<artifactId>spring-cloud-starter-openfeignartifactId>
dependency>

编写gulimall-coupon ==》CouponController测试方法

【谷粒商城】开发篇三:微服务组件 SpringCloud & SpringCloud Alibaba_第20张图片

@RequestMapping("/member/list")
    public R memberCoupons() {
        CouponEntity couponEntity = new CouponEntity();
        couponEntity.setCouponName("满100减10");
        return R.ok().put("coupons",Arrays.asList(couponEntity));
    }

编写声明式的远程调用接口,,告诉SpringCloud这个接口需要调用远程服务

声明接口的每一个方法都是调用哪个远程服务的那个请求
【谷粒商城】开发篇三:微服务组件 SpringCloud & SpringCloud Alibaba_第21张图片

@FeignClient("gulimall-coupon") // 名称为nacos中的注册名称
public interface CouponFeignService {

    /**
     * 返回所有会员优惠券
     * @return
     */
    @RequestMapping("/coupon/coupon/member/list")
    public R memberCoupons();
}

使用 @EnableFeignClients 开启远程调用功能

@EnableFeignClients(basePackages = {"com.atguigu.gulimall.member.feign"})
@EnableDiscoveryClient
@MapperScan("com.atguigu.gulimall.member.dao")
@SpringBootApplication
public class GulimallMemberApplication {

	public static void main(String[] args) {
		SpringApplication.run(GulimallMemberApplication.class, args);
	}

}

在gulimall-member ==》MemberController测试方法

【谷粒商城】开发篇三:微服务组件 SpringCloud & SpringCloud Alibaba_第22张图片

@RestController
@RequestMapping("member/member")
public class MemberController {
    @Autowired
    private MemberService memberService;

    @Autowired
    CouponFeignService couponFeignService;

    @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"));
    }
}

开启nacos,访问 http://localhost:8000/member/member/coupons 进行测试

【谷粒商城】开发篇三:微服务组件 SpringCloud & SpringCloud Alibaba_第23张图片

Feign原理 TODO

【谷粒商城】开发篇三:微服务组件 SpringCloud & SpringCloud Alibaba_第24张图片

Gateway 网关

Gateway 介绍

网关作为流量的入口,常用功能包括路由转发权限校验限流控制等。而 springcloud gateway 作为 SpringCloud 官方推出的第二代网关框架,取代了Zuul 网关。

网关提供API 全托管服务,丰富的API 管理功能,辅助企业管理大规模的API,以降低管理成本和安全风险,包括协议适配、协议转发、安全策略、防刷、流量、监控日志等功能。

Spring Cloud Gateway 旨在提供一种简单而有效的方式来对API 进行路由,并为他们提供切面,例如:安全性,监控/指标和弹性等。

官方文档:https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.1.3.RELEASE/single/spring-clo
ud-gateway.html

三大核心概念

  • 路由(Route):当我们发一个请求给网关,网关要将请求路由到指定的服务。路由(Route)由ID、destination URI(目标URI)、a collection of predicates(一组断言集合)、a collection of filters(一组过滤器)组成。如果路由能匹配了断言,那么就能到达指定位置。
  • 断言(Predicate):就是java里的断言函数,匹配请求里的任何信息,包括请求头等。根据请求头路由哪个服务
  • 过滤(Filter):通过配置 Spring Framework GatewayFilter 可以修改请求和响应。

客户端向 Spring Cloud GateWay网关发出请求,首先交给映射器,如果能处理就交给handler处理,然后交给一系列Filter,然后给指定的服务,再返回回来给客户端。
【谷粒商城】开发篇三:微服务组件 SpringCloud & SpringCloud Alibaba_第25张图片

Gateway 微服务集成

创建网关模块

【谷粒商城】开发篇三:微服务组件 SpringCloud & SpringCloud Alibaba_第26张图片
【谷粒商城】开发篇三:微服务组件 SpringCloud & SpringCloud Alibaba_第27张图片

引入common依赖,将自己注册到nacos中心,发现其他服务

<dependency>
	<groupId>com.atguigu.gulimallgroupId>
	<artifactId>gulimall-commonartifactId>
	<version>0.0.1-SNAPSHOTversion>
dependency>

在启动类中加上@EnableDiscoveryClient注解,开启发现其他服务的功能,因为网关服务不需要数据库的配置,所以在启动类上排除和数据库相关的配置@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})

@EnableDiscoveryClient
//去除数据源配置,否则会报错
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
public class GulimallGatewayApplication {

	public static void main(String[] args) {
		SpringApplication.run(GulimallGatewayApplication.class, args);
	}

}

在nacos中创建网关服务的命名空间,并在配置列表的网关服务的命名空间下创建当前网关的配置

在这里插入图片描述
【谷粒商城】开发篇三:微服务组件 SpringCloud & SpringCloud Alibaba_第28张图片

添加注册中心的配置文件bootstrap.properties,指定当前服务,添加注册中心的地址,网关服务的命名空间,网关服务使用的配置分组

spring.application.name=gulimall-gateway
spring.cloud.nacos.config.server-addr=192.168.217.138:8848
# 指定命名空间
spring.cloud.nacos.config.namespace=27d22758-30e4-4cef-aec2-66ff8153d163

Gateway 断言配置

断言配置可以参考官网:https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.1.3.RELEASE/single/spring-cloud-gateway.html#gateway-request-predicates-factories

  • 参考:https://blog.csdn.net/hancoder/article/details/109063671

  • 在application.yml中进行断言配置

    spring:
      cloud:
        gateway:
          routes:
            - id: test_route
              uri: https://www.baidu.com
              predicates:
                - Query=url,baidu # url=baidu 则路由到 www.baidu.com
            - id: qq_route
              uri: https://www.qq.com
              predicates:
                - Query=url,qq
    
  • 测试
    【谷粒商城】开发篇三:微服务组件 SpringCloud & SpringCloud Alibaba_第29张图片

你可能感兴趣的:(谷粒商城学习记录,微服务,spring,cloud,架构)