基于Spring Cloud Alibaba搭建nacos

2023-11-04

关系

Spring Boot是框架。将各个组件集合在一起,方便快速开发web应用。
Spring Cloud基于Spring Boot,限定了一组特定的组件,从而可以方便地进行微服务工程的开发。
Spring Cloud Alibaba在Spring Cloud的基础上进行了一些调整,将某些组件替换为阿里巴巴的组件,同样是为了方便微服务工程的开发。
也就是说,Spring Cloud Alibaba依赖于Spring Cloud。
故而,想要使用Spring Cloud Alibaba,必须在Spring Boot的基础上引入Spring Cloud,然后引入Spring Cloud Alibaba。
查看官方的版本说明:

https://github.com/alibaba/spring-cloud-alibaba/wiki/%E7%89%88%E6%9C%AC%E8%AF%B4%E6%98%8E

其中的 毕业版本依赖关系(推荐使用) 当前内容为:

Spring Cloud Version Spring Cloud Alibaba Version Spring Boot Version
Spring Cloud 2020.0.0 2021.1 2.4.2
Spring Cloud Hoxton.SR8 2.2.5.RELEASE 2.3.2.RELEASE
Spring Cloud Greenwich.SR6 2.1.4.RELEASE 2.1.13.RELEASE
Spring Cloud Hoxton.SR3 2.2.1.RELEASE 2.2.5.RELEASE
Spring Cloud Hoxton.RELEASE 2.2.0.RELEASE 2.2.X.RELEASE
Spring Cloud Greenwich 2.1.2.RELEASE 2.1.X.RELEASE
Spring Cloud Finchley 2.0.4.RELEASE(停止维护,建议升级) 2.0.X.RELEASE
Spring Cloud Edgware 1.5.1.RELEASE(停止维护,建议升级) 1.5.X.RELEASE

该表指明了使用Spring Cloud Alibaba时,要同时引入的Spring Boot版本与Spring Cloud版本。
以表中第一行为例,其Spring Cloud Alibaba Versio为2021.1,那么:

  • 需引入Spring Cloud Version的版本为Spring Cloud 2020.0.0。
  • 需引入Spring Boot Version的版本为2.4.2。
  • 一般来说版本向下兼容,因此可以使用比该指定更高的版本。但使用指定版本可能更稳定。

父子工程

一般地,使用SpringCloud开发往往会使用父子工程。
所谓父子工程,指的是先创建一个父工程,在pom.xml中用<dependencyManagement>指定组件的<version>;然后在其下创建子工程,修改pom.xml中的<parent>来指向父工程,这样子工程的依赖将从父工程继承。
这样即可将依赖统一划归父工程管理,多个子工程使用的依赖将保持一致。
父工程仅仅负责对依赖的管理,不包含任何具体的逻辑。

创建父工程

  1. 点击File→New→Project,在左侧选择Spring Initializr,配置好后点Next。
  2. 左上角选择Spring Boot版本,左侧通常选择Developer Tools/Lombok,以及Web/Spring Web。然后点击Finish。

这样一个父工程就创建好了。
打开父工程的pom.xml,添加<dependencyManagement>

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>Hoxton.SR3</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-dependencies</artifactId>
            <version>2.2.1.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

注意其中的版本与官方文档中的 毕业版本依赖关系(推荐使用) 保持一致。
pom.xml源码:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.0.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>alibaba</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>pom</packaging>
    <name>SpringCloudAlibaba</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Hoxton.SR3</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>2.2.1.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

其中的<parent>,该标签下的多个属性指明了父工程。
<parent></parent>结束后紧跟的<groupId><artifactId><version>3个标签则指明了本工程。这3个标签及内容会复制到子工程中。
特别注意其中的<packaging>标签,需要将其设置为pom

创建子工程。

  1. 打开Project面板,在父工程上点右键,选择New→Module。
  2. 在左侧选择Spring Initializr,配置好后点Next。
  3. 左上角选择Spring Boot版本,左侧什么也不要选。然后点击Finish。

这样一个子工程就创建完毕了。
打开子工程的pom.xml,将其<parent>标签下的内容删除,更换为上一步提到的父工程的3个标签。

nacos

打开父工程的pom.xml,按下Ctrl+鼠标左键来点击<artifactId>spring-cloud-alibaba-dependencies</artifactId>。此时会显示 spring-cloud-alibaba-dependcies-2.2.1.RELEASE.pom 文件内容。
在其中分别搜索 nacosnacos-discovery,可以找到内容:

<nacos.client.version>1.2.1</nacos.client.version>

<dependency>
  <groupId>com.alibaba.cloud</groupId>
  <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
  <version>2.2.1.RELEASE</version>
</dependency>

从而可知当前spring-cloud-alibaba所需的nacos客户端版本为1.2.1,spring-cloud-starter-alibaba-nacos-discovery版本为2.2.1.RELEASE

nacos客户端

已知所需nacos客户端版本为1.2.1,因此从官网下载对应版本客户端。官网的nacos目前已分为1.x与2.x两个分支,因此下载1.x最新版本1.4.2
下载后,运行nacos。

子工程

依赖

打开子工程的pom.xml,在其中引入nacos:

<dependencies>
    ...

    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    </dependency>
</dependencies>

由于父工程负责版本管理,因此子工程只需要引入即可,不需要再设置<version>属性。

设置

需要在子工程的配置文件application.yml中设置工程名与nacos地址。

server:
  port: 8081
spring:
  application:
    name: provider
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848

一般来说也会在该处指定当前子工程的端口号。
服务提供者必须配置spring.application.namespring.cloud.nacos.discovery.server-addr两个属性。但服务消费者可以不配置。
特别注意:若使用Ribbon,则服务名不能包含_

服务提供者与消费者

创建2个子工程,一个作为服务提供者,另一个作为服务消费者。
其pom.xml与application.yml设置相同,都使用上述设置。注意调试时端口号需要有所区别。

服务提供者

服务提供者定义一个简单的测试接口:

@RestController
public class ProviderTestController {

    @RequestMapping("/test")
    String test() {
        return "this is the test string.";
    }
}

运行工程。查看nacos后台,可以看到服务已顺利注册。

服务消费者

服务消费者根据访问方式不同,处理也不同。这里使用RestTemplate访问。
可以使用Ribbon来自动负载均衡,仅需引入@LoadBalanced注解。但需注意的是非Ribbon方式Ribbon方式并不兼容,一旦使用了Ribbon,则RestTemplate会被处理,以至于常规方式将无法使用。

非Ribbon方式

首先定义一个Configuration类来注册RestTemplate:

@Configuration
public class SpringCloudAlibabaConfig {
    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

然后定义访问类:

@RestController
public class ConsumerTestController {
    @Autowired
    private DiscoveryClient discoveryClient;
    @Autowired
    private RestTemplate restTemplate;

    @RequestMapping("/test")
    public String test() {
        // 获取指定服务下所有的实例。
        List<ServiceInstance> serviceInstanceList = this.discoveryClient.getInstances("provider");
        ServiceInstance serviceInstance = serviceInstanceList.get(0);
        String uri = serviceInstance.getUri().toString();
        String url = uri + "/test";

        String r = restTemplate.getForObject(url, String.class);
        return r;
    }
}

其中RestTemplate.getForObject()的第二个参数指明了返回值的类型。
运行后,调用/test接口即可。

Ribbon方式

上述方法,需要人为获取所有服务实例,然后选择一个来调用。然后还需要人为拼接接口,非常烦琐。
Ribbon会自动按可配置策略选择一个实例来调用,且不再需要拼接接口:
注册RestTemplate时添加@LoadBalanced注解:

@Configuration
public class SpringCloudAlibabaConfig {
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

然后定义访问类:

@RestController
public class ConsumerTestController {
    @Autowired
    private RestTemplate restTemplate;

    @RequestMapping("/test")
    public String test() {
        String r = restTemplate.getForObject("http://provider/test", String.class);
        return r;
    }
}

其url使用"http://" + "服务名" + "接口名"的形式。
访问即可。

请求传参

上述方式RestTemplate转发请求,仅仅转发了请求的url,不包含参数。若要包含参数,根据请求的不同,方式不同:

get方式

对于get方式,直接将参数拼接在url后即可。
例如,要增加一个参数value

String value = "abc123";
String r = restTemplate.getForObject("http://provider/test" + "?value=" + value, String.class);

这样即可将value参数传给服务提供者。

post方式

对于post方式,需将参数放入一个LinkedMultiValueMap中:

MultiValueMap<String, Object> paramMap = new LinkedMultiValueMap<String, Object>();
paramMap.add("value", "abc123");
String r = this.restTemplate.postForObject("http://provider/test", paramMap, String.class);

Feign

Feign可替换RestTemplate,用于转发请求。实际上,Feign的本质就是生成一个RestTemplate来转发请求。
使用Feign的流程为:

  1. 引入依赖:

    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>
    

    由于在父工程中已引入了org.springframework.cloud,故而引入依赖时不需要指定版本号。

  2. 在启动类上添加注解开启Feign

    @EnableFeignClients
    
  3. 开发Feign客户端:

    @FeignClient("provider")
    public interface Client {
        @RequestMapping("/test")
        String test();
    }
    

    其中:

    • @FeignClient("provider")指定了nacos的服务名为provider
    • @RequestMapping("/test")指定了要访问的接口为/test
  4. 调用:

    @Resource
    Client client;
    
    @RequestMapping("/test")
    public String test() {
        String r = client.test();
        return r;
    }
    

这样即可请求成功。
Feign传参,必须将参数放在接口定义中,并指明value属性。例如:

@FeignClient("provider")
public interface Client {
    @RequestMapping("/testName")
    String testName(@RequestParam(value = "name") String name);

    @RequestMapping("/testUser")
    String testUser(@RequestBody User user);
}

部署

上述测试,都是基于IDEA直接运行。而实际环境中,无论服务提供者还是服务消费者,都需要部署到Tomcat。在此过程中会遇到两个问题:

  • 端口问题。
  • 工程名问题。

端口问题

一个服务提供者,在yml文件中配置了server.port,使用IDEA运行一切正常。然而部署到Tomcat后,发现服务没有注册给naocs。
这是因为nacos的注册类绑定了一个监听事件,监听到容器端口后即会向注册中心注册。然而,当使用外部容器时,不能监听到事件,因此注册失败。
故而,解决方案为:容器初始化时人为地将服务提供者端口注册给注册中心。
考虑到部署在容器内的应用,必须通过容器指定的端口才能访问,因此注册的服务提供者端口必须与容器端口相同。

@Configuration
public class NacosConfig implements ApplicationContextAware {

    @Autowired(required = false)
    private NacosAutoServiceRegistration registration;

    @Override
    public void setApplicationContext(ApplicationContext context) throws BeansException {
        if (registration != null) {
            try {
                Integer tomcatPort = new Integer(getTomcatPort());
                registration.setPort(tomcatPort);
            } catch (Exception e) {
                e.printStackTrace();
            }
            registration.start();
        }
    }

    /**
     *	获取外部tomcat端口
     */
    public String getTomcatPort() throws Exception {
        MBeanServer beanServer = ManagementFactory.getPlatformMBeanServer();
        Set<ObjectName> objectNames = beanServer.queryNames(new ObjectName("*:type=Connector,*"),
                Query.match(Query.attr("protocol"), Query.value("HTTP/1.1")));
        String port = objectNames.iterator().next().getKeyProperty("port");
        return port;
    }
}

该配置仅服务提供者需要,服务消费者是不需要的。

工程名问题

设服务提供者的工程名为myPorject,接口名为test
在IDEA中直接运行的工程,若没有在配置文件中设置server.servlet.context-path,那么消费者访问的路径是不包含工程名的。此时访问接口的路径为:

http://127.0.0.1:8080/test

然而部署到Tomcat后,需带工程名访问,此时访问接口的路径为:

http://127.0.0.1:9080/myProject/test

因此,最佳实践应该是将工程名作为接口的一部分。即服务消费者获取到nacos实例后,拼接的接口名不再是/test,而是/myProject/test
同时,为了IDEA调试与Tomcat的表现统一,需在服务提供者的配置文件中设置server.servlet.context-path为工程名。

其他

nacos中显示的已注册服务地址不对:查看windows的网络和Internet,打开适配器选项,看是否有其他网卡,例如虚拟机或翻墙软件所使用的虚拟网卡。关闭即可。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

基于Spring Cloud Alibaba搭建nacos 的相关文章

随机推荐

  • 未来十年互联网十大发展趋势

    世界已被互联网占领 互联网未来10年将如何变化与发展 1 互联网全球普及 根据国际电信联盟最近统计 全球互联网用户总数已经达到20亿人 而联合国公布的最新统计数字显示 世界人口在2011年底突破70亿大关 所以到2020年毫无疑问会有更多的
  • Ubuntu下各种压缩与解压的操作

    这篇文章主要给大家介绍了在Ubuntu系统下各种压缩与解压的操作 其中包括 tar gz bz2 bz Z tgz zip rar以及 lha等各个的解压与压缩方法 每一种都给出了示例代码 需要的朋友可以参考学习 一起来看看吧 一 tar
  • vue项目中高德地图根据城市名定位到城市中心位置,并在该位置做标记

    先看效果 首先记得引入高德地图 并且要带上 plugin AMap DistrictSearch 如下
  • 加密方式

    目录 MD5和RSA 1 MD5 a MD5简介 MD5一种不可逆的加密算法 什么意思呢 网站一般会保存用户密码 为了不让数据库管理员看到用户的密码 你输入的密码是这样的 12345 网站加密后的密码可能是这样的 E10ADC3949BA5
  • 缓存穿透,缓存雪崩的四种解决方案

    2019独角兽企业重金招聘Python工程师标准 gt gt gt 前言 设计一个缓存系统 不得不要考虑的问题就是 缓存穿透 缓存击穿与失效时的雪崩效应 缓存穿透 缓存穿透是指查询一个一定不存在的数据 由于缓存是不命中时被动写的 并且出于容
  • [管理与领导-60]:IT基层管理者 - 扩展技能 - 3 - 通过面试招到合适的人选

    目录 前言 一 招聘 1 1 什么是招聘 1 2 招聘 VS 招募 1 3 甄选 1 4 招聘中的重要原则 1 5 招聘的本质 1 6 人才匹配的维度 1 7 人员招聘中的误区 二 面试 2 1 何为面试 2 2 为什么面试 2 3 面试的
  • PRESENT加密算法(c++实现)

    简介 PRESENT加密算法在2007 年由来自德国波鸿鲁尔大学的 Bogdanov 在 CHES 会议中发表 PRESENT加密算法为一种轻量级分组密码算法 采用了 置换网络 SPN 结构 一共迭代 31 轮 分块 组 长度为 64 比特
  • 局域网可用IP网段

    C类局域网专用网段 192 168 0 1 192 168 255 254 很多公司网吧都是用这个网段 hoho B类局域网专用网段 172 16 0 1 172 31 255 254 A类局域网专用网段 10 0 0 1 10 255 2
  • 工作3周年小记

    时间荏苒 入职那天的情景还历历在目 却不经意的成为了组里的老员工 一直渴望着静好的岁月 不曾想 过去的岁月这般忙碌 匆匆 似乎没有留下太多彩色的记忆 蓦然回首 做了很多项目 看到各种同事的来去 也经历了组里的盛衰 内心没有波澜 只是遗憾没有
  • chatgpt赋能python:Python编译成pyd文件是什么?如何提高SEO排名?

    Python编译成pyd文件是什么 如何提高SEO排名 Python是一种非常强大的编程语言 它非常适合用于开发各种不同类型的应用程序 然而 Python虽然易于学习和使用 但是由于它的解释性质 它的运行速度相对较慢 在某些情况下 这可能会
  • docker 覆盖 entrypoint_跟我一起学docker(八)--Dockerfile

    1 利用Dockerfile创建镜像 什么是Dockerfile 定义 Dockerfile是一个文本格式的配置文件 用户可以使用Dockerfile快速创建自定义镜像 基本结构 Dockerfile由一行行的命令语句组成 并且支持以 开头
  • 一文解读Vision Transformer(ViT)

    前言 Vision Transformer 论文 https arxiv org pdf 2010 11929 pdf 跟李沐学AI https www bilibili com video BV15P4y137jb spm id from
  • 【ThreadPoolTaskSchedule】实现手动开启关闭定时任务

    最近在公司呢 有一个需求 大概意思就是需要我去调用远程接口 但如果出现异常或者响应失败的时候 就需要开启重试机制 直到返回成功的响应为止 我很疑惑 按理说这种情况通常都应该有一个最大重试次数吗 最终在我像组长确认这个需求之后 还是要求我按照
  • ELK 日志分析系统

    ELK 日志分析系统 2015 10 08 13 18 58 标签 elk 原创作品 允许转载 转载时请务必以超链接形式标明文章 原始出处 作者信息和本声明 否则将追究法律责任 http 467754239 blog 51cto com 4
  • 软件测试 - 边界值法

    文章目录 介绍 等价类划分法的区别 常见的边界值 步骤 案例 介绍 边界值分析法就是对输入或输出边界值进行测试的 也是一种黑盒测试 边界值分析法通常作为等价类划分法的补充 其测试用例来自等价类的边界 长期的经验得知 大量的错误是发现在输入或
  • 二叉树的遍历方式(前序遍历、中序遍历、后序遍历、层序遍历、深度优先遍历、广度优先遍历)

    前序 中序 后序 层序 一 前序遍历 步骤 根节点 gt 左子节点 gt 右子节点 适用场合 在第一次遍历到节点时就执行操作 一般只是想遍历执行操作 或输出结果 可选用前序遍历 二 中序遍历 步骤 左子节点 gt 根节点 gt 右子节点 适
  • 服务器虚拟化集群部署

    多服务器虚拟化集群部署 介绍 服务器虚拟化有有利于节省服务器开支 提高服务器资源利用率 将服务器物理资源逻辑化 动态分配内存 cpu 磁盘等物理资源 以dell的R730服务器为例 VMware ESXi5 5虚拟化软件 虚拟化服务器 1
  • ps命令解析

    ps命令用于报告当前系统的进程状态 可以搭配kill指令随时中断 删除不必要的程序 ps命令是最基本同时也是非常强大的进程查看命令 使用该命令可以确定有哪些进程正在运行和运行的状态 进程是否结束 进程有没有僵死 哪些进程占用了过多的资源等等
  • [mp4]The audio codec for mp4 atom

    In the esds atom there are a few fields of relevance to determining the codec used The first byte of content of the esds
  • 基于Spring Cloud Alibaba搭建nacos

    关系 Spring Boot是框架 将各个组件集合在一起 方便快速开发web应用 Spring Cloud基于Spring Boot 限定了一组特定的组件 从而可以方便地进行微服务工程的开发 Spring Cloud Alibaba在Spr