Spring-Cloud-Alibaba

文章目录

  • Spring Cloud Alibaba Nacos
    • 1. Spring Cloud Alibaba简介
    • 2. Nacos作为服务注册中心
      • 1. Nacos简介
      • 2. Nacos安装与运行
      • 3. Nacos作为服务注册中心
        • 1. 基于Nacos的服务提供者
        • 2. 基于Nacos的服务消费者
        • 3. 测试
    • 3. 各种服务注册中心的对比
    • 4. Nacos作为服务配置中心
      • 1. Nacos作为配置中心——基础配置
      • 2.Nacos作为配置中心——分类配置
        • 1. `dataId` 方案
        • 2. `Group` 方案
        • 3. `namespace` 方案

Spring Cloud Alibaba Nacos

1. Spring Cloud Alibaba简介

SpringCloud Netflix进入维护模式,意味着不再开发新的组件,这就出现了SpringCloud Alibaba这个替代品,SpringCloud Alibaba能实现以下功能,也可以参考SpringCloud Alibaba官网:

功能 具体说明
服务限流与降级 默认支持Servlet、Feign、RestTemplate、Dubbo和RocketMQ限流降级功能的接入,可以在运行时通过控制台实时修改限流降级规则,还支持查看限流降级Metrics监控。
服务注册与发现 适配SpringCloud服务注册与发现标准,默认集成了Ribbon的支持。
分布式配置管理 支持分布式系统中的外部化配置,配置更改时自动刷新。
消息驱动能力 基于SpringCloud Stream为微服务应用构建消息驱动鞥能力。
阿里云对象存储 阿里云提供的海量、安全、低成本、高可靠的云存储服务。支持在任何应用、任何时间、任何地点存储和访问任意类型的数据。
分布式任务调度 提供秒级、精准、高可靠、高可用的定时(基于Cron表达式)任务调度服务。同时提供分布式的任务执行模型,如网格任务。网格任务支持海量子任务均匀分配到所有Worker上执行。

使用SpringCloud Alibaba需要在POM文件中引入其依赖:

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>com.alibaba.cloudgroupId>
            <artifactId>spring-cloud-alibaba-dependenciesartifactId>
            <version>2.1.0.RELEASEversion>
            <type>pomtype>
            <scope>importscope>
        dependency>
    dependencies>
dependencyManagement>

2. Nacos作为服务注册中心

1. Nacos简介

“Nacos”,前四个字母分别问Naming和Configuration的前两个字母,最后的s为Service,它是一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台,说白了就是注册中心+配置中心的组合,等价于SpringCloud之前的Eureka+Config+Bus,所以Nacos可以替代Eureka做服务中心,可以替代Config做配置中心。

2. Nacos安装与运行

在Nacos官网下载地址中下载Nacos,在安装Nacos前需要本地Java8和Maven的环境已经准备好,然后下载其压缩包:
Spring-Cloud-Alibaba_第1张图片
解压该压缩文件后直接运行在bin目录下的startup.cmd启动Nacos:
Spring-Cloud-Alibaba_第2张图片
然后访问 http://localhost:8848/nacos/ 进入Nacos,其默认的账号密码都是nacos,登录成功后即可看到如下界面:
Spring-Cloud-Alibaba_第3张图片
在之前学习服务注册中心的时候讲过CAP理论,即

C A P
Consistency Available Partition tolerance
强一致性 可用性 分区容错性

CAP原则又称CAP定理,指的是在一个分布式系统中,一致性、可用性、分区容错性。CAP 原则指的是,这三个要素最多只能同时实现两点,不可能三者兼顾。在分布式架构中,P永远要求被保证,所以当前的分布式架构只有AP和CP两种。Nacos属于AP模型,再次对比这些服务注册中心:

服务注册与发现框架 CAP模型 控制台管理 社区活跃度
Eureka AP 支持 低(2.x版本历史问题)
Zookeeper CP 不支持
Consul CP 支持
Nacos AP(事实上也可以支持CP) 支持

据说Nacos在阿里巴巴内部有超过10万的实例运行,已经过了类似双十一等各种大型流量的考验。。。

3. Nacos作为服务注册中心

1. 基于Nacos的服务提供者

新建Module:cloudalibaba-provider-payment9002作为服务提供方微服务。当然为了实现Nacos的负载均衡,使nacos-payment-provider服务集群化,我们同事也仿照9002搭建一个9003微服务。

然后在工程的父POM中引入依赖1. Spring Cloud Alibaba简介中引入的依赖的前提下,在该模块的POM引入依赖Nacos服务注册发现的依赖:


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

然后添加其配置文件application.yml:

server:
  port: 9002

spring:
  application:
    name: nacos-payment-provider # 微服务名称
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848 # 配置Nacos地址

management:
  endpoints:
    web:
      exposure:
        include: '*' # 监控端点全部打开

编写其主启动类并在主启动类上添加 @EnableDiscoveryClient 注解,使9002微服务能够被注册中心发现:

package cn.sher6j.springcloudalibaba;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

/**
 * @author sher6j
 * @create 2020-05-26-9:56
 */
@EnableDiscoveryClient
@SpringBootApplication
public class PaymentMain9002 {
    public static void main(String[] args) {
        SpringApplication.run(PaymentMain9001.class);
    }
}

然后编写一个简单的业务类:

@RestController
public class PaymentController {

    @Value("${server.port}")
    private String serverPort;

    @GetMapping("/payment/nacos/{id}")
    public String getPayment(@PathVariable("id") Integer id) {
        return "Nacos服务注册,端口:" + serverPort + ";id:" + id;
    }
}

启动9002、9003微服务模块,在Nacos的服务列表中我们可以看到这两个微服务已经入驻服务注册中心:
Spring-Cloud-Alibaba_第4张图片
点开nacos-payment-provider服务的详情页面,可以看到服务的实例详情:
Spring-Cloud-Alibaba_第5张图片

2. 基于Nacos的服务消费者

新建Module:cloudalibaba-consumer-nacos-order83作为服务消费方微服务,在该模块的POM中同样引入令Nacos服务注册中心发现自己的依赖,配置其配置文件:

server:
  port: 83

spring:
  application:
    name: nacos-order-cosumer
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848

# 消费者将要去访问的微服务名称(注册成功进Nacos的微服务提供者)
service-url:
  nacos-user-service: http://nacos-payment-provider

然后编写服务消费方的主启动类,Nacos本身就具有负载均衡功能,因为引入Nacos依赖的同时,Nacos内部集成了Ribbon,如图所示:
Spring-Cloud-Alibaba_第6张图片
而我们在学习Ribbon时知道,用了Ribbon就需要使用 RestTemplate ,所有我们编写配置类,向Spring容器中注入 RestTemplate

package cn.sher6j.springcloudalibaba.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

/**
 * @author sher6j
 * @create 2020-05-26-10:40
 */
@Configuration
public class ApplicationContextConfig {

    @Bean
    @LoadBalanced //负载均衡
    public RestTemplate getRestTemplate() {
        return new RestTemplate();
    }
}

注意注入 RestTemplate 时一定要添加 @LoadBalanced 注解,否则不会开启负载均衡,在服务提供方集群的情况下,由于没有开启负载均衡,消费方会无法选择具体调用哪个微服务实例,也就是服务提供方实例有很多个,而消费方服务不知道要调用哪个具体的服务提供方实例,不加该注解会产生 UnknownHostException 的异常:
在这里插入图片描述
然后编写其业务类:

package cn.sher6j.springcloudalibaba.controller;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

/**
 * @author sher6j
 * @create 2020-05-26-10:42
 */
@RestController
@Slf4j
public class OrderNacosController {

    @Autowired
    private RestTemplate restTemplate;
	//直接读取配置文件中的值,减少代码冗余
    @Value("${service-url.nacos-user-service}")
    private String serverURL;

    @GetMapping("/consumer/payment/nacos/{id}")
    public String paymentInfo(@PathVariable("id") Long id) {
        return restTemplate.getForObject(serverURL + "/payment/nacos/" + id, String.class);
    }
}

启动83服务消费方,在Nacos服务注册中心中我们可以看到入驻了两个服务提供方实例和一个服务消费方实例:
Spring-Cloud-Alibaba_第7张图片

3. 测试

多次访问 http://localhost:83/consumer/payment/nacos/1 (id值随意,紧作为测试用1代替),我们发现服务消费方微服务83可以完成对服务提供方微服务9002/9003的轮询负载均衡调用,也就是Nacos内部就整合了Ribbon,实现了负载均衡,默认负载均衡算法采用轮询
Spring-Cloud-Alibaba_第8张图片

3. 各种服务注册中心的对比

事实上,Nacos可以AP模式和CP模式中进行切换,也就是说Nacos不仅仅支持AP(可用性和分区容错性),它同样支持CP(一致性和分区容错性)。当采取入驻到Nacos服务注册中心的微服务对自己的健康状态进行上报时,也就是对入驻到注册中心的微服务进行非持久化的保存,一旦客户端上报不健康信息,就将不健康的实例摘除掉,这类似于Eureka(当然Eureka可以开启自我保护模式);当采取由Nacos服务注册中心自己探测入驻到中心的微服务是否健康时,也就是对入驻到注册中心的微服务进行持久化保存,即使服务注册中心发现微服务已经不健康了,也不会删除到微服务,这类似于Consul。如下图(CoreDNS也是一种服务注册中心):
Spring-Cloud-Alibaba_第9张图片
Nacos与其他服务注册中心特性的对比:

Nacos Eureka Consul CoreDNS Zookeeper
一致性协议 CP/AP AP CP / CP
健康检查 TCP/HTTP/MySQL/Client Beat(客户端心跳) Clent Beat TCP/HTTP/gRPC/cmd / Client Beat
负载均衡 权重/DSL/元数据/CMDB Ribbon Fabio RR /
雪崩保护 支持 支持 不支持 不支持 不支持
自动注销实例 支持 支持 不支持 不支持 支持
访问协议 HTTP/DNS/UDP HTTP HTTP/DNS DNS TCP
监听支持 支持 支持 支持 不支持 不支持
多数据中心 支持 支持 支持 不支持 不支持
跨注册中心 支持 不支持 支持 不支持 不支持
SpringCloud集成 支持 支持 支持 不支持 不支持
Dubbo集成 支持 不支持 不支持 不支持 支持
K8s集成 支持 不支持 支持 支持 不支持

从理论知识中我们知道Nacos服务注册中心可以在AP和CP模式中进行切换,C是所有节点在同一时间看到的数据是一致的,而A是所有的请求都会受到响应(A可以近似理解为高可用)。

一般来说,如果不需要存储服务级别的信息且服务实例是通过Nacos-Client注册的,并且服务能保持心跳上报,那么就可以选择AP模式,当前主流的微服务框架如SpringCloud和Dubbo,都适用于AP模式,AP模式为了服务的可能性而减弱了一致性,因此AP模式下只支持注册临时实例

而如果需要在服务级别编辑或存储配置信息,那么CP是必须的,K8s服务和DNS服务使用于CP模式,CP模式下则支持注册持久化实例,此时以Raft协议为集群运行模式,该模式下注册实例之前必须先注册服务,如果服务不存在,则会返回错误。

如果需要让Nacos服务从AP模式切换到CP模式的话,只需要向服务注册中心发送POST请求即可:

curl -X PUT '$NACOS_SERVER:8848/nacos/v1/ns/operator/switches?entry=serverMode&value=CP'

4. Nacos作为服务配置中心

在用SpringCloud Config结合SpringCloud Bus时,我们可以把配置信息托管到远端如GitHub上,而现在我们应用了Nacos后,可以直接在Nacos上托管配置信息。

1. Nacos作为配置中心——基础配置

新建Module:cloudalibaba-config-nacos-client3377作为服务配置中心微服务,在其POM文件中引入必要的依赖(如Nacos服务注册中心的依赖)为,引入配置中心的依赖:


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

Nacos同SpringCloud Config一样,在项目初始化时,要保证先从配置中心进行配置拉取,拉取配置后,才能保证项目的正常启动,而我们知道SpringBoot配置文件的加载顺序是存在优先级的,bootstrap的优先级要高于application,所以我们创建两个配置文件 bootstrap.yml (从配置中心拉取配置)和 application.yml(写自己的配置),我们配置 bootstrap.yml 以使3377服务从Nacos上拉取配置信息:

# nacos配置
server:
  port: 3377

spring:
  application:
    name: nacos-config-client
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848 #Nacos服务注册中心地址
      config:
        server-addr: localhost:8848 #Nacos作为配置中心地址
        file-extension: yaml # 指定yaml格式的配置,也就是说从Nacos上读yaml格式的配置文件

然后用 application.yml 定制自己的配置信息,将环境定义为开发环境:

spring:
  profiles:
    active: dev # 表示开发环境

编写其主启动类后,然后编写其业务类,在业务来上添加SpringCloud的原生注解**@RefreshScope 以使服务可以支持从Nacos配置中心动态刷新配置信息**,

package cn.sher6j.springcloudalibaba.controller;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author sher6j
 * @create 2020-05-28-21:07
 */
@RestController
@RefreshScope //支持Nacos的动态刷新功能
public class ConfigClientController {

    @Value("{config.info}")
    private String configInfo;

    @GetMapping("/config/info")
    public String getConfigInfo() {
        return configInfo;
    }
}

在上面的业务层中我们从配置中心读取了配置信息

而我们在Nacos配置中心中添加配置信息,在Nacos配置中心中添加配置文件要遵循一定的匹配规则——Nacos中的 dataId 的组成格式及与SpringBoot配置文件中的匹配规则,更详细的信息可以参考Nacos官方文档,在Nacos SpringCloud中,dataId的完整格式为:

${prefix}-${spring.profile.active}.${file-extension}
  • prefix 默认为 spring.application.name (服务名)的值,也可以通过配置项 spring.cloud.nacos.config.prefix来配置。
  • spring.profile.active 即为当前环境对应的 profile(上面我们在 application.yml中配置的属性),详情可以参考 Spring Boot文档。 注意:当 spring.profile.active 为空时,对应的连接符 - 也将不存在,dataId 的拼接格式变成 ${prefix}.${file-extension}, 建议不要使spring.profile.active 为空
  • file-exetension 为配置内容的数据格式,可以通过配置项 spring.cloud.nacos.config.file-extension 来配置。目前只支持 propertiesyaml 类型。

由于prefix 默认为 spring.application.name (服务名)的值,所以 dataId 的完整格式可以替换为:

${spring.application.name}-${spring.profile.active}.${file-extension}

结合我们在 boostrap.yml 配置文件和 application.yml 配置文件的配置,我们可以得到在当前实例中的 dataId 应该为:

nacos-config-client-dev.yaml

Spring-Cloud-Alibaba_第10张图片
根据上述公式得到 dataId 应为的值后,我们就可以在Nacos配置中心的配置列表中新建配置文件:
Spring-Cloud-Alibaba_第11张图片
在新建配置文件时,Data ID 中填入我们得到的 dataId ,组名先选择默认的即可,配置格式选择我们在 file-extension 中设置的YAML格式,然后编写配置文件,编写后点击发布即可:
Spring-Cloud-Alibaba_第12张图片
注意,在Nacos中的 dataId 中的后缀名必须用 yaml 而不能用 yml。添加配置文件后再点开Nacos配置中心的配置列表,就能发现已经存在刚才创建的配置文件:
Spring-Cloud-Alibaba_第13张图片
然后我们启动3377微服务,访问 http://localhost:3377/config/info 查看能否访问都Nacos配置中心的配置信息:
Spring-Cloud-Alibaba_第14张图片
Nacos配置中心直接就支持动态刷新,再更给了Nacos配置中心的配置信息后,再通过3377微服务访问,就可以得到更新后的配置信息。目前Nacos已经实现了Eureka + Config + Bus的功能,但是Nacos之所以如此优秀是因为这些框架有的功能它有,而这些框架没有的功能它还有!下面看Nacos的一些高级功能。

2.Nacos作为配置中心——分类配置

在多环境多项目管理时,也就是实际开发中,通常一个系统会准备不同的开发环境,如dev开发环境、test测试环境、prod生产环境,如何保证指定环境启动时服务能正确读取到Nacos上相应环境的配置文件呢?一个大型分布式微服务系统会有很多微服务子项目,每个微服务项目又都会有相应的开发环境、测试环境、预发环境、正式环境等待,那对这些微服务配置该如何管理呢?在Nacos配置中心中就可以进行分类配置,一个配置文件的具体所属由 namespace + Group + dataId 所构成:
Spring-Cloud-Alibaba_第15张图片
这种设计就类似于Java中的包名和类名,最外层的 namespace 是可以用于区分部署环境的,主要用来实现隔离,比如有三个环境:开发、测试、生产,那就可以创建三个 namespaceGroupdataId 逻辑上区分两个目标对象,默认情况下 namespace 的值为 publicGroup 的值为 DEFAULT_GROUP。 下面对这三个属性进行详细展开。

1. dataId 方案

指定 spring.profile.active 配置属性和配置文件的 dataId 来使不同环境下读取不同的配置,也就是说我们现在用默认的命名空间 namespace (即 public),默认的分组 Group (即 DEFAULT_GROUP),然后在Nacos配置中心中建立两个 dataId 分别为 dev 环境和 test 环境:
Spring-Cloud-Alibaba_第16张图片
此时在同一命名空间同一组中就有了两个应用于开发、测试不同环境的配置文件:
Spring-Cloud-Alibaba_第17张图片
然后我们通过修改微服务自己定制配置信息 application.yml 配置文件中的spring.profile.active 属性即可进行多环境下的配置文件的读取,配置什么就加载什么,在之前我们的3377微服务获取的是配置中心中 nacos-config-client-dev.yaml 配置文件的配置信息,现在我们将 application.yml 修改为:

spring:
  profiles:
#    active: dev # 表示开发环境
    active: test # 表示开发环境

然后重启3377微服务,再次进行测试发现访问到的配置信息为测试环境的配置信息:
Spring-Cloud-Alibaba_第18张图片
这就类似于在Java中的包名相同,但是类名不同。

2. Group 方案

不仅通过 dataId 可以实现环境分区,应用 Group 也可以实现环境分区,首先我们在Nacos配置中心新建两个相同 dataId,不同 Group 的配置文件,一个用于开发环境,一个用于测试环境:
Spring-Cloud-Alibaba_第19张图片
Spring-Cloud-Alibaba_第20张图片
由于这两个配置文件的 dataId 均为 nacos-config-client-info.yaml ,根据之前解释的 dataId 的命名规则,我们应该将3377微幅的自定义配置文件 application.yml 中的 spring.profile.active 属性更改为 info

spring:
  profiles:
    active: info 

在确认了读取的配置文件的 dataId 后,我们在其 bootstrap.yml 配置文件中添加 spring.cloud.nacos.config.group 属性,设置为响应的组名即可,比如我们现在设置为测试环境组:

spring:
  cloud:
    nacos:
      config:
        group: TEST_GROUP  

重启3377微服务,再次访问可以发现获取到的配置信息即为TEST_GROUP组的配置信息:
Spring-Cloud-Alibaba_第21张图片

3. namespace 方案

根据namespace同样可以进行环境区分。

你可能感兴趣的:(SpringCloud,微服务)