springcloud 微服务Spring Cloud Alibaba Nacos使用详解

Posted 逆风飞翔的小叔

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了springcloud 微服务Spring Cloud Alibaba Nacos使用详解相关的知识,希望对你有一定的参考价值。

目录

一、前言

二、nacos介绍

2.1  什么是 Nacos

2.2 nacos 核心能力

2.2.1 服务发现和服务健康监测

2.2.2 动态配置服务

2.2.3 动态 DNS 服务

2.2.4 服务及其元数据管理

2.2.5 nacos生态地图

2.3 与其他配置中心对比

三、nacos快速部署

3.1 获取安装包

3.2 修改脚本启动模式

3.3  启动nacos 服务

3.4 访问控制台

四、连接mysql

4.1 前置准备

4.2 操作步骤

4.2.1 导入安装包下nacos的建表sql

4.2 修改配置文件

4.3 重启nacos服务

五、nacos配置管理

5.1 配置管理菜单

5.1.1 配置列表

5.1.2 历史版本

六、nacos权限管理

6.1 用户

6.2 角色

6.3 权限

七、nacos命名空间

7.1 创建命名空间

7.2 创建配置文件

八、Spring Cloud 使用 Nacos

8.1  前置准备

8.2  读取nacos配置

8.2.1 配置文件

8.2.2 nacos添加一个配置文件

8.2.3 添加测试接口

8.2.4 模拟测试

8.3  namespace与group使用

8.3.1 同一个namespace不同dataid

8.3.2 不同namespace的配置读取

 8.3.3 不同group的配置读取

8.4  nacos动态刷新配置

 九、写在最后


一、前言

nacos作为Spring Cloud Alibaba微服务体系中一个非常重要的组件,在微服务治理中担当着不可替代的角色,比如作为分布式配置中心,服务注册中心,相比其他的配置中心和注册中心来说,nacos具有更出色的性能以及云原生优势,本篇将从多个维度全面深入的学习nacos这个组件。

二、nacos介绍

nacos官网:nacos官网 ,中文参考手册地址:中文手册

2.1  什么是 Nacos

  • Nacos 致力于帮助您发现、配置和管理微服务。帮助您快速实现动态服务发现、服务配置、服务元数据及流量管理;
  • Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。 Nacos 是构建以“服务”为中心的现代应用架构 (例如微服务范式、云原生范式) 的服务基础设施;

2.2 nacos 核心能力

2.2.1 服务发现和服务健康监测

Nacos 支持基于 DNS 和基于 RPC 的服务发现。服务提供者使用 原生SDKOpenAPI、或一个独立的Agent TODO注册 Service 后,服务消费者可以使用DNS TODO 或HTTP&API查找和发现服务。

1、Nacos 提供对服务的实时的健康检查,阻止向不健康的主机或服务实例发送请求;

2、Nacos 支持传输层 (PING 或 TCP)和应用层 (如 HTTP、mysql、用户自定义)的健康检查。 对于复杂的云环境和网络拓扑环境中(如 VPC、边缘网络等)服务的健康检查,Nacos 提供了 agent 上报模式和服务端主动检测2种健康检查模式;

3、Nacos 还提供了统一的健康检查仪表盘,帮助您根据健康状态管理服务的可用性及流量

2.2.2 动态配置服务

  • 动态配置服务可以让您以中心化、外部化和动态化的方式管理所有环境的应用配置和服务配置。
  • 动态配置消除了配置变更时重新部署应用和服务的需要,让配置管理变得更加高效和敏捷。
  • 配置中心化管理让实现无状态服务变得更简单,让服务按需弹性扩展变得更容易。

Nacos 提供了一个简洁易用的控制台,可以管理所有的服务和应用的配置。Nacos 还提供包括配置版本跟踪、金丝雀发布、一键回滚配置以及客户端配置更新状态跟踪在内的一系列开箱即用的配置管理特性,帮助您更安全地在生产环境中管理配置变更和降低配置变更带来的风险。

2.2.3 动态 DNS 服务

动态 DNS 服务支持权重路由,让您更容易地实现中间层负载均衡、更灵活的路由策略、流量控制以及数据中心内网的简单DNS解析服务。动态DNS服务还能让您更容易地实现以 DNS 协议为基础的服务发现,以帮助您消除耦合到厂商私有服务发现 API 上的风险。

Nacos 提供了一些简单的 DNS APIs TODO 帮助您管理服务的关联域名和可用的 IP:PORT 列表

2.2.4 服务及其元数据管理

Nacos 能让您从微服务平台建设的视角管理数据中心的所有服务及元数据,包括管理服务的描述、生命周期、服务的静态依赖分析、服务的健康状态、服务的流量管理、路由及安全策略、服务的 SLA 以及最首要的 metrics 统计数据。

2.2.5 nacos生态地图

2.3 与其他配置中心对比

在微服务治理生态中,作为配置中心来说其实是有很多选择的,比如大家熟知的zk,apollo,consul等,如下是springcloud生态中可以作为技术选型的配置中心对比,从各项指标对比来看,nacos可以说是非常完美的存在,其优势是不言而喻的。

三、nacos快速部署

在之前的一篇,springcloud-alibaba整合nacos 中分享了如何快速部署单机nacos,还是比较简单的,为了方便后面的演示说明,这里再简单做一下说明;

3.1 获取安装包

安装包下载地址:下载地址

选择完版本后,可以选择linux或者windows环境的安装包下载即可

我这里选择了zip压缩包

3.2 修改脚本启动模式

nacos启动脚本里面提供了集群模式和单机模式启动两种方式,由于本机搭建使用,选用单机模式即可,修改启动脚本中如下的关键参数;

3.3  启动nacos 服务

修改并保存脚本之后,双击启动服务

3.4 访问控制台

启动成功之后,按上图中地址访问nacos的客户端控制台,默认登录用户名和密码:nacos/nacos

登录成功后,看到如下的控制台界面;

四、连接mysql

配置文件的信息在实际的生产环境中是需要持久化保存的,nacos服务默认启动之后,配置信息是保存在本地内存中,一旦重新启动就丢失了,因此安全起见,我们将其配置信息持久化到数据库,配置的话也很简单,按照下面的操作步骤

4.1 前置准备

创建一个mysql数据库

4.2 操作步骤

4.2.1 导入安装包下nacos的建表sql

导入完成后,可以看到nacos的一些表

 

4.2 修改配置文件

修改conf下的application.properties,主要修改mysql的连接信息

4.3 重启nacos服务

重启之后,后面再操作nacos的数据将会存储到nacos的数据表中。

五、nacos配置管理

接下来详细说明一下配置管理中相关重要的菜单项的使用说明,如下图所示

5.1 配置管理菜单

配置管理是用于集中管理微服务中的各类配置信息的,比如为了减少开发,测试,生产等不同的环境下因为配置文件带来的麻烦,可以在这里进行分门别类的做管理。

5.1.1 配置列表

配置列表维护环境中所有的配置文件,使用很简单,直接创建即可

 对上面的配置参数做简单的补充说明:

  • Data ID命名时,建议使用具有业务通识含义的全局唯一的名称,比如以 dev,test等区分不同的环境;

  • Group,具有相同业务归属的建议使用相同的分组,避免都使用DEFAULT_GROUP;

  • 配置内容中建议不要包含敏感信息;

最佳实践

5.1.2 历史版本

通过该项,可以查看指定配置的历史变更信息,便于信息的追溯

六、nacos权限管理

使用权限管理可以更好的对配置文件的读写权限进行控制,nacos的权限体系比较简单,主要涉及到用户,角色和权限三个模块;

使用权限管理需要在application.properties配置文件中开启下面的配置项

### If turn on auth system:
nacos.core.auth.enabled=true

6.1 用户

即具体登录nacos控制台的账户,你可以在这里管理nacos的账户,如添加新的账户,删除账户等,比如使用的默认账户nacos;

6.2 角色

即操作资源的身份,某个账户要能使用某个功能,必须具备这个角色才有操作权限,你可以在这个创建一个新的角色,并为某个账户绑定这个角色;

6.3 权限

具体的权限项,比如为某个具体的角色,具体的资源授权,权限可以是读或写,或者读写,那么被角色关联的账户就具备了操作这个资源的权限;

七、nacos命名空间

命名空间这个概念相信大家并不陌生,也不是nacos的独创,命名空间是为了更好的区分微服务之间的使用边界的一种用于实现逻辑隔离的概念,有点像docker容器的概念,即你只能在自己的容器内使用,使用过apollo的同学对此应该有较深的体会,apollo在使用的时候,不同的应用之间一定要通过nacos去管理;

7.1 创建命名空间

为你的微服务创建一个新的命名空间,名称最好见名知意

创建完成后,回到配置列表,可以看到在默认的public右侧就多了order和user这两个命名空间

7.2 创建配置文件

后续如果我们需要在user微服务下创建配置文件,就可以切换到user这个命名空间下创建,就能更好的区分和维护不同命名空间的配置文件了;

八、Spring Cloud 使用 Nacos

接下来将从多个维度详细介绍下在springcloud中如何使用Nacos

8.1  前置准备

导入依赖,在工程中导入如下依赖,第一个是使用nacos的配置使用,第二个是将nacos作为配置中心时使用;

        <!--nacos-config 配置中心-自带动态刷新-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>

        <!--nacos-discovery 注册中心-服务发现与注册-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>

8.2  读取nacos配置

上面在某个命名空间下创建完成配置文件后,就可以在程序中进行读取了,具体使用步骤如下:

8.2.1 配置文件

使用nacos时,关于nacos的连接配置需要在一个bootstrap.yaml 中进行设置

springboot加载配置文件优先级:bootstrap.yaml > application.yaml

bootstrap.yaml 配置如下:


server:
  port: 8087

spring:
  application:
    #这里的名称和nacos中的配置文件名称保持一致
    name: nacos-config-client
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
      config:
        server-addr: localhost:8848
        #指定要加载的配置文件的格式后缀名
        file-extension: yaml

application.yaml配置如下:

spring:
  profiles:
    active: dev

关于这里两个配置文件的内容为什么要这么做,官方文档给了如下说明:

 简单来说可以这么理解:

1、spring.application.name 的值为nacos配置文件的名称;

2、nacos配置文件的名称需要拼接application.yaml中的环境变量名,比如上文的:dev;

3、通过这种写法,可以在本地的配置文件中,根据环境的不同,快速切换不同的环境;

8.2.2 nacos添加一个配置文件

在默认的public命名空间下添加如下配置文件

配置内容如下:

config:
    info:
        name: nacos center

8.2.3 添加测试接口

为了测试效果,使用一个接口读取nacos的配置

@RestController
@RefreshScope
public class ConfigController 

    @Value("$config.info.name")
    private String configName;

    @GetMapping("/get/config")
    public String getConfigName()
        return configName;
    

8.2.4 模拟测试

启动工程后,调用接口测试,发现可以正常读取到上面的配置信息

8.3  namespace与group使用

通过上文中对于namespace的讲述了解了namespace在nacos中的使用,从微服务配置管理的设计思想来说,通过namespace + group的划分,可以更加精准的管控应用归属的配置信息,真正做到比较安全的隔离,下面来具体说说不同场景下namespace + group的组合使用。

8.3.1 同一个namespace不同dataid

在上文,我们使用的是默认的namespace即public,nacos-config-client-dev.yaml 配置文件名称即应用层级的唯一名称,这里叫做 Data Id;

再创建一个新的配置文件,名为:nacos-config-client-test.yaml,配置内容如下

config:
    info:
        name: config center,test

创建完成后可以看到列表中新增了一个配置文件

修改如下配置文件

启动工程后,再次测试接口,此时读取到的就是test的配置文件中的信息

8.3.2 不同namespace的配置读取

再在user这个namespace下面也创建一个nacos-config-client-dev.yaml的配置文件

config:
    info:
        name: config center,ns user

工程中bootstrap.yaml加上namespace的配置,注意namespace的值是那一长串字符串;

 启动工程后再次读取配置,可以看到本次读取的就是新的配置文件里的信息

 8.3.3 不同group的配置读取

上文在public命名空间下没有配置分组的情况下,默认使用的都是DEFAULT_GROUP这个分组,如果希望读取自己分组下的配置怎么做呢?可以自定义一个新的分组。

这样在user这个命令空间下就多了一个分组user_test_group,并且在这个分组下,有一个nacos-config-client-test.yaml的配置文件;

修改bootstrap.yaml配置文件,添加group信息

启动工程后再次读取配置,可以看到本次读取的就是新的配置文件里的信息

8.4  nacos动态刷新配置

还记得在最早使用springcloud 的config配置中心的时候,如果某个配置文件发生了变更,程序中无法实时加载到这个最新的配置信息,而是需要配合其他的组件才能使用,而在nacos中就不必这么麻烦了;

nacos提供了@RefreshScope注解,在需要动态获取配置的类上面加上该注解就可以准实时的获取nacos中发生变更的配置信息;

在上面的接口类中,加上这个注解

@RestController
@RefreshScope
public class ConfigController 

    @Value("$config.info.name")
    private String configName;

    @GetMapping("/get/config")
    public String getConfigName()
        return configName;
    

再最后一个测试用例中,我们去user这个命名空间下,修改一下nacos-config-client-test.yaml中的配置信息;

修改完毕后保存发布,在不重启工程的情况下,再次调用接口,可以看到最新的配置信息已经读取到;

有心的同学可能会发现,当修改了配置文件信息后,控制台中输出了如下的内容,我们猜测可能是这个@RefreshScope注解的背后存在某种机制,能够动态的感知或者说监听到nacos中的配置文件内容的变化;

 九、写在最后

本文通过大量的篇幅详细介绍了nacos的各种场景的使用,对于使用springcloud alibaba这一套微服务治理框架的同学来说,nacos可以说必须要熟练掌握,同时,可以通过阅读源码深入了解其背后的架构设计思路,对于自身也是不错的借鉴。

译:基于Spring Cloud Stream构建和测试 message-driven 微服务

原文链接:https://piotrminkowski.wordpress.com/2018/06/15/building-and-testing-message-driven-microservices-using-spring-cloud-stream/ 作者: Piotr Mińkowski 译者: helloworldtang img Spring Boot和Spring Cloud为您提供了一个利用不同的通信方式快速构建微服务的解决方案。您可以基于Spring Cloud Netflix库创建同步REST微服务,正如我在之前的一篇文章中所展示的那样 使用Spring Boot 2.0, Eureka and Spring Cloud快速搭建微服务指南。您可以使用Spring WebFlux项目在Netty上创建异步的、响应式的微服务,并将其与一些Spring Cloud库相结合,如我的文章所示 使用Spring WebFlux and Spring Cloud搭建响应式微服务。最后,您可以使用Spring Cloud Stream和类似Apache Kafka或RabbitMQ这样的broker来实现基于发布/订阅模型的message-driven微服务。构建微服务的最后一种方法是本文的主要主题。我将向您展示如何在RabbitMQ broker的基础上有效地构建、扩展、运行和测试消息传递微服务。 体系结构 为了演示Spring Cloud Stream的特性,我们将设计一个示例系统,该系统使用发布/订阅模型进行跨服务通信。我们有三个微服务:order-service、product-service和account-service。应用程序order-service暴露了负责处理发送到我们系统的订单的HTTP endpoint。所有传入的订单都是异步处理的——order-service准备并发送消息到RabbitMQ exchange,然后就对调用的客户端进行响应,不需要等到消息被消费后再响应。应用程序的account-service和product-service正在侦听进入该RabbitMQ exchange的订单消息。微服务account-service负责检查客户账户是否有足够的资金来支付该订单需要的金额,如果有就从该账户扣款。微服务product-service检查是否有足够的库存,并在处理订单后改变可用产品的数量。account-service 和 product-service 都通过RabbitMQ exchange(这一次是使用direct exchange的一对一通信)发送带有操作状态的异步响应。微服务 order-service根据接收到的响应消息来更新订单状态,并通过REST endpoint GET /order/{id}提供给外部客户端。 如果您觉得我们的示例描述有点难以理解,这里有一个用于澄清的架构图。 stream-1 启用 Spring Cloud Stream 在项目中使用Spring Cloud Stream的推荐方法是使用依赖管理系统。Spring Cloud Stream有一个与整个Spring Cloud framework相关,并且独立发布的依赖管理。然而,如果我们已经在Elmhurst.RELEASE版本的dependencyManagement部分声明了spring-cloud-dependencies,就不需要在pom.xml中声明任何其他内容。如果您喜欢只使用Spring Cloud Stream项目,那么您应该定义以下部分。 下一步是将spring-cloud-streamartifact添加到项目依赖项中。我还建议您至少包括spring-cloud-sleuth 库,以提供作为源请求进入order-service 的发送消息用的traceId。 Spring Cloud Stream 编程模型 为了使您的应用程序能够连接到一个message broker,请在主类上使用@EnableBinding注解。 @EnableBinding注解将一个或多个接口作为参数。您可以在Spring Cloud Stream提供的三个接口之间进行选择: Sink:这是用来标记从入站通道接收消息的服务。 Source: 这是用来向出站通道发送消息的。 Processor:当你需要一个入站通道和一个出站通道时,它可以被使用,因为它继承了Source and Sink接口。因为order-service发送消息,并接收它们,它的主类已经使用了@EnableBinding(Processor.class)注解。 下面是order-service项目中启用了Spring Cloud Stream binding的主类。 @SpringBootApplication @EnableBinding(Processor.class) public class OrderApplication { ... public static void main(String[] args) { new SpringApplicationBuilder(OrderApplication.class).web(true).run(args); } ... } 增加 message broker 在Spring Cloud Stream术语中,负责与特定message broker集成的实现称为binder。默认情况下,Spring Cloud Stream为 Kafka and RabbitMQ提供了binder实现。它能够自动检测和在类路径上查找binder。任何特定于中间件的设置都可以通过Spring Boot支持的外部配置属性来覆盖,譬如应用程序参数、环境变量,或者仅仅是application.yml文件。为了包含对RabbitMQ的支持,RabbitMQ将这篇文章用作message broker,您应该向项目添加以下依赖项。 现在,我们的应用程序需要连接RabbitMQ broker的一个共享实例。这就是为什么我使用RabbitMQ在默认的5672端口上运行Docker镜像。它还可以在地址http://192.168.99.100:15672(http://192.168.99.100:15672/)下启动web仪表板。 我们需要通过设置属性 spring.rabbitmq.host为Docker机器IP 192.168.99.100 ,来覆盖Spring Boot application的中的默认设置。 实现消息驱动的微服务 Spring Cloud Stream是在Spring Integration项目之上构建的。Spring Integration扩展了Spring编程模型,以支持众所周知的企业集成模式(EIP)。EIP定义了许多在分布式系统中经常使用的经典组件。您可能已经听说过诸如消息通道、路由器、聚合器或endpoints之类的模式。让我们回到上面的例子。让我们从order-service开始,它负责接收订单,将它们发布在shared topic上,然后从下游服务收集异步响应。下面是@service,它使用Sourcebean来构建消息并将其发布到远程topic。 这个 @Service 是由controller调用,controller暴露提交新订单和通过 id获得订单状态的HTTP endpoints。 现在,让我们更仔细地看看消费端。来自order-service的OrderSender bean所发送的消息是由 account-service和product-service接收。为了从 topic exchange中接收消息,我们只需要在入参为Order的方法上添加 @StreamListener注解。我们还必须为监听器定义目标通道——在这种情况下,它是Processor.INPUT。譬如: @StreamListener(Processor.INPUT) public void receiveOrder(Order order) throws JsonProcessingException { LOGGER.info("Order received: {}", mapper.writeValueAsString(order)); service.process(order); } 接收订单由AccountServicebean处理。account-service会根据客户账户上是否有足够的资金来实现订单接受或拒绝订单。验收状态的响应通过OrderSenderbean调用的输出通道发回order-service 。 最后一步是配置。它是在 application.yml中提供的。我们必须正确地定义通道的destination。而order-service则将orders-outdestination分配给输出通道,而orders-indestination则是输入通道,account-service和 product-service则恰恰相反。这是合乎逻辑的,因为通过其输出destination通过 order-service发送的消息是通过其输入destination接收的服务接收的。但在shared broker’s exchange中,它仍然是相同的destination。下面是 order-service的配置设置。 spring: application: name: order-service rabbitmq: host: 192.168.99.100 port: 5672 cloud: stream: bindings: output: destination: orders-out producer: partitionKeyExpression: payload.customerId partitionCount: 2 input: destination: orders-in rabbit: bindings: input: consumer: exchangeType: direct 这是为 account-service和product-service提供的配置。 最后,您可以运行上面示例中的微服务。现在,我们只需要运行每个微服务的单个实例。您可以通过运行JUnit测试类OrderControllerTest来轻松地生成一些测试请求,这是在我的源代码库中提供的 order-service中提供的。这种情况下很简单。在下一篇文章中,我们将学习更高级的示例,其中包含多个正在运行的消费服务实例。 扩展 为了扩展我们的Spring Cloud Stream应用程序,我们只需要启动每个微服务的附加实例。他们仍然会侦听与当前正在运行的实例相同的 topic exchange 中的传入消息。在添加了一个 account-service和 product-service的实例之后,我们可以发送一个测试订单。这个测试的结果对我们来说是不令人满意的… 为什么?每个微服务运行的所有实例都接收到了这个订单。这正是 topic exchanges 的工作方式——发送到topic的消息被所有的消费者接收,他们正在侦听这个topic。幸运的是,Spring Cloud Stream能够通过提供称为 consumer group的解决方案来解决这个问题。它负责保证一个消息只被一个实例处理,如果它们被放置在一个相互竞争的消费者关系中。在运行多项服务实例时,对consumer group机制的转换已经在下图中可视化了。 stream-2 一个 consumer group 机制的配置不是很困难。我们只需要设定group参数,并给出给定destination的组名。下面是account-service的当前binding配置。orders-indestination地是一个为直接与order-service通信而创建的队列,因此只有orders-out被分组使用spring.cloud.stream.bindings..group属性。 Consumer group机制是Apache Kafka的一个概念,它也在Spring Cloud Stream中实现,也适用于RabbitMQ broker,它本身并不支持它。因此,我认为它在RabbitMQ上的配置非常有趣。如果您在destination运行两个服务实例,而没有在destination设置组名,那么就会有两个为单个交易所创建的bindings(每个实例一个bindings),如下图所示。因为有两个应用程序在这个exchange中监听,总共有四个binding分配给那个exchange。 stream-3 如果您为选定的destination Spring Cloud Stream设置组名,则将为给定服务的所有运行实例创建单一binding。binding的名称将以组名为后缀。 B08597_11_06 因为,我们已经在项目依赖项中包含了 spring-cloud-starter-sleuth ,在实现 order-service POST endpoint的单个请求时,在交换的所有异步请求之间发送相同的 traceId 头部。由于这个原因,我们可以使用Elastic Stack (Kibana)轻松地将所有日志关联起来。 B08597_11_05 自动化测试 您可以轻松地测试您的微服务,而不需要连接到message broker。要实现它,您需要将 spring-cloud-stream-test-support包含到您的项目依赖项中。它包含 TestSupportBinderbean,它允许您与绑定通道进行交互,并检查应用程序发送和接收的任何消息。 在测试类中,我们需要声明 MessageCollectorbean,它负责接收由TestSupportBinder保留的消息。这是我的account-service测试类。使用Processorbean,我将测试订单发送到输入通道。然后,MessageCollector接收到通过输出通道发送回 order-service 的消息。测试方法的 testAccepted创建了应该被帐户服务接受的顺序,而testRejected方法则设置了过高的订单价格,从而导致拒绝订单。 总结 当您不需要来自API的同步响应时,Message-driven的微服务是一个不错的选择。在本文中,我展示了在您的微服务之间的跨服务通信中发布/订阅模型的示例用例。源代码在GitHub上是常见的(https://github.com/helloworldtang/sample-message-driven-microservices.git【原文源码maven不能运行,这个项目fork原代码并修复了错误】)。对于使用Spring Cloud Stream库、Apache Kafka的更有趣的例子,您可以参考我的书中第11章, Mastering Spring Cloud(https://www.packtpub.com/application-development/mastering-spring-cloud)。 关注社区公号,加入社区纯技术微信群

以上是关于springcloud 微服务Spring Cloud Alibaba Nacos使用详解的主要内容,如果未能解决你的问题,请参考以下文章

微服务框架之Spring Cloud简介

spring cloud 微服务 需要service层吗

Spring Cloud简介

初识SpringCloud微服务

Spring Cloud封神之旅-微服务与springcloud

Spring Cloud封神之旅-微服务与springcloud