专栏首页码农UP2U服务注册、发现和远程调用

服务注册、发现和远程调用

早期文章

本篇文章介绍如何完成一个简单的服务注册、发现和远程调用的 Demo,通过该 Demo 来学习和了解关于 Spring Cloud 相关的知识。

项目结构

创建一个 Maven 的聚合项目,使用 SpringBoot 作为其父项目,然后通过在其下添加子模块来构建一个简单的微服务的项目。

创建一个 service_user 服务

在 Maven 项目下创建一个 Module 作为子模块,在项目的 POM 文件中加入 web 依赖,依赖如下:

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

引入依赖后,创建 controller、service、impl 三个包,然后分别创建 UserController、UserService 和 UserServiceImpl 三个类文件,以及一个启动类。项目结构如下图。

该项目来模拟通过输入用户的 id 来返回用户名。UserController 代码如下:

@RestController
@RequestMapping("/admin/user")
public class UserController
{
    @Autowired
    private UserService userService;

    @GetMapping("getUser/{id}")
    public String getUser(@PathVariable Long id)
    {
        return userService.getUser(id);
    }
}

UserServiceImpl 的代码如下:

@Service
public class UserServiceImpl implements UserService
{

    @Override
    public String getUser(Long id) {

        String name = null;
        
        if (id == 1) {
            name = "admin";
        } else {
            name = "user";
        }

        return name;
    }
}

application.yml 配置文件如下:

server:
  port: 8001
spring:
  application:
    name: service-user

注意,这里的 spring.application.name 的名字不能使用 下划线,否则后面使用 OpenFeign 进行远程调用时会报错。

因为创建的子模块是 Maven 类型的项目,因此需要手动添加启动类,代码如下:

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

启动项目,访问 8001 端口来请求我们的接口,如下所示。

创建 service_dict 项目

接着再创建一个子模块,同样引入 web 依赖,创建 controller、service 和 impl 的包,并创建 DictController、DictService 和 DictImpl 三个类,以及启动类和 application.yml 配置文件,项目结构如下:

分别来写 DictController 和 DictServiceImpl 两个类的代码,DictController 代码如下:

@RestController
@RequestMapping("/admin/dict")
public class DictController
{
    @Autowired
    private DictService dictService;

    @GetMapping("getDict/{id}")
    public String getDict(@PathVariable Long id)
    {
        return dictService.getDict(id);
    }
}

DictServiceImpl 代码如下:

@Service
public class DictServiceImpl implements DictService
{

    @Override
    public String getDict(Long id) {

        String name = null;

        if (id == 1) {
            name = "管理员";
        } else {
            name = "普通用户";
        }

        return name;
    }
}

application.yml 配置文件如下:

server:
  port: 8002
spring:
  application:
    name: service-dict

该项目的端口号为 8002,在添加了该项目的启动类之后,启动该项目,访问 8002 接口,如下图所示。

服务注册

可以看到,我们完成了两个服务,第一个服务通过 id 来获取用户名,第二个服务通过 id 来判断用户的类型。为了提高服务的可用性,可以将每个服务进行水平扩展,当调用这些服务的时候,服务有不同的 IP 地址,或者有不同的端口号。想要调用服务,就需要知道服务的 IP 地址和端口号。但是,这样做有一定的问题,比如某个服务下线了,或者新增加了服务,那么调用方需要动态的了解服务的变化,而服务的地址直接在调用方里进行管理,那么就不方便了。

在这种情况下,可以通过服务注册中心来动态的管理服务,服务中心有 Zookeeper、Eureka、Nacos 等。这里我们使用 Nacos 来管理服务的注册。这里,我们在 Windows 下启动 Nacos,启动画面如下:

然后通过浏览器访问 http://localhost:8848/nacos 来访问 Nacos 的管理页面,登录后的管理页面如下图所示:

有了 Nacos 后我们修改上面的两个子模块,让两个子模块将自己注册到 Nacos 中。分别在 service_user 和 service_dict 的 POM 文件中增加如下的依赖。

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

并在启动类上增加注解,注解如下:

@EnableDiscoveryClient

在 application.yml 中将注册中心的地址配置一下,配置如下:

server:
  port: 8002
spring:
  application:
    name: service-dict
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848

然后重新启动这两个子模块,这样,两个服务就被注册到了 Nacos 中,可以在 Nacos 中查看服务列表,如下图所示。

通过上图可以看到,已经将自己注册到了 Nacos 中。

服务发现与远程服务调用

现在,我们让 service_user 去调用 service_dict 来模拟一次远程调用的过程,也就是在调用 getUser 接口时,在 getUser 接口的内部去调用 getDict 接口。

创建一个子模块,命名为 client,引入如下依赖:

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

有了该依赖以后,在项目中添加一个接口,通过该接口调用 service_dict 下的 getDict 接口。项目结构如下:

这里只有 DictFeignClient 接口文件,该文件的代码如下:

@FeignClient("service-dict")
@Repository
public interface DictFeignClient
{
    @GetMapping("/admin/dict/getDict/{id}")
    String getDict(@PathVariable Long id);
}

在注解 @FeignClient 中定义服务的名称,在 @GetMapping 注解中写入接口地址的 uri。将该子模块引入 service_user 中,即可通过 OpenFeign 来完成远程调用。修改 service_user 中的 UserServiceImpl 文件,代码如下:

@Service
public class UserServiceImpl implements UserService
{

    @Autowired
    private DictFeignClient dictFeignClient;

    @Override
    public String getUser(Long id) {

        String name = null;

        String dictName = dictFeignClient.getDict(id);

        if (id == 1) {
            name = "admin";
        } else {
            name = "user";
        }

        return name + " " + dictName;
    }
}

使用 @Autowired 来注入 DictFeignClient,调用 DictFeignClient 接口中定义的 getDict 来调用 service_dict 中的 getDict 接口。这样就完成了远程调用。在 service_user 的启动类上加如下注解:

@EnableFeignClients(basePackages = "com.coderup2u")

重新启动 service_user 项目,并在浏览器中进行访问 getUser 接口,如下图所示。

从上面的代码中可以看出,进行远程调用时,只定义了服务的名称,也就是 通过 @FeignClient("service-dict"),但是并没有给出该服务实际的地址和端口号。由此,我们可以想到,服务的 IP 地址和端口号是由服务中心获取到的,即服务发现。服务发现会动态的根据注册中心服务列表的变化而变化。当服务增加、下线,注册中心管理的地址列表都会发生变化,从而提供给服务调用方,这样就避免了调用了已经下线的服务,从而导致服务调用的失败。他们大致的关系如下图所示。

总结

本文通过简单的 Demo 介绍 Spring Cloud Alibaba 中 Nacos 的使用,服务注册、服务发现,及远程服务的调用。可以通过在简单的 Demo 上来完成 Nacos 集群的搭建,服务集群的搭建来进行测试。

本文分享自微信公众号 - 码农UP2U(gh_3c91b47a82e0),作者:码农UP2U

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2021-10-11

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Eureka服务发现和注册

    爱撒谎的男孩
  • Zookeeper 服务注册和发现

    ZooKeeper 是一种分布式,开源的协同服务。分布式应用可以基于其所提供的一些特性来实现服务同步,配置维护,服务分组及命名等。zookeeper是比较简单易...

    WindWant
  • Consul初探-服务注册和发现

    经过上一篇的学习,现在已经来到了服务注册发现环节;Consul 的核心功能就是服务注册和发现,Consul 客户端通过将自己注册到 Consul 服务器集群,然...

    梁规晓
  • 服务注册/发现-consul

    当系统的数量越来越多的时候,提供的各种系统接口基本都写在配置文件之中,从而在进行接口升级的时候,关联的系统总是要进行同步升级。。。强耦合了解一下,在程序的世界...

    SRE运维实践
  • SpringCloud:Eureka服务注册与发现

    Eureka 其实就是一个 服务注册与发现的中心,也就是相当于我们前面做的一些生产者的服务需要注册到我们的注册中心,那么我们的消费者就不用把代码写死,而是可以去...

    lwen
  • 服务注册与发现---eureka

    eureka简介:云端服务发现,一个基于 REST 的服务,用于定位服务,以实现云端中间层服务发现和故障转移。 话不多说直接上代码 首先新建一个springcl...

    dalaoyang
  • Eureka服务注册与发现

    注册Eureka的服务非常的简单,只需要引入spring-cloud-starter-netflix-eureka-client的jar包即可。

    小忽悠
  • Eureka服务注册与发现

    注册Eureka的服务非常的简单,只需要引入spring-cloud-starter-netflix-eureka-client的jar包即可。

    小忽悠
  • 03Zookeeper服务注册与发现

    wget https://mirrors.estointernet.in/apache/zookeeper/zookeeper-3.6.2/apache-zoo...

    Remember_Ray
  • 02Eureka服务注册与发现

    访问:C:\Windows\System32\drivers\etc 下的 host 文件,添加如下内容

    Remember_Ray
  • 04Consul服务注册与发现

    https://learn.hashicorp.com/tutorials/consul/get-started-install

    Remember_Ray
  • 服务注册与发现Eureka

    在上篇文章《使用SpringBoot2.0整合SpringCloud》中在消费者调用提供者的时候把提供者的地址硬编码在了代码中,这样的方式肯定是不行的,今天,我...

    Java学习录
  • Eureka服务注册与发现

    在这个例子中,Eureka就是大型商场,就是一个服务中心。加了服务端注解@EnableEurekaServer之后就可以开启服务中心了,然后商家就是客户端,要加...

    chenchenchen
  • Dubbo服务注册与发现

    本文链接:https://blog.csdn.net/u014427391/article/details/96754952

    SmileNicky
  • Springcloud:Eureka服务注册与发现

    @EnableEurekaServer加上个注解就是Eureka的服务端了,我们并不需要写什么业务员,启动之后访问

    冷环渊
  • Eureka服务注册与发现

    注意: 保护机制在生产环境中,通常是为了防止因网络原因而导致原本没有问题的服务被清除。而如果真的是大面积服务失效,那么久需要服务容错机制了,往后会提到的熔断器。...

    呆呆
  • 在系统中用etcd实现服务注册和发现

    在分布式系统中,如何管理节点间的状态一直是一个难题,etcd 是由开发并维护的,它使用 Go 语言编写,并通过Raft 一致性算法处理日志复制以保证强一致性。e...

    KevinYan
  • SpringCloud技术指南系列(七)服务注册发现之Zookeeper服务调用

    目前服务发现的解决方案有Eureka,Consul,Zookeeper等,这三个是SpringCloud官方支持的。

    品茗IT
  • SpringCloud技术指南系列(三)服务注册发现之Eureka服务调用

    目前服务发现的解决方案有Eureka,Consul,Zookeeper等,这三个是SpringCloud官方支持的。

    品茗IT

扫码关注云+社区

领取腾讯云代金券