Dubbo使用Nacos注册中心

前言

以下类容来自书籍《Spring Cloud Alibaba 微服务原理与实战》

一、基本使用

这里nacos的安装就不写了

服务端

依赖

<dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.cloud</groupId>
                    <artifactId>spring-cloud-context</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-dubbo</artifactId>
        </dependency>
        <dependency>
            <groupId>com.gupaoedu.book.nacos</groupId>
            <artifactId>spring-cloud-nacos-sample-api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-nacos-discovery</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.cloud</groupId>
                    <artifactId>spring-cloud-context</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-context</artifactId>
            <version>2.1.1.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

配置文件

spring.application.name=spring-cloud-nacos-sample

dubbo.scan.base-packages=com.book.nacos.bootstrap

dubbo.protocol.name=dubbo
dubbo.protocol.port=20880
dubbo.registry.address=spring-cloud://localhost

spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848

实现类

需要注意的是这里的@Service是dubbo包下的。

import com.book.nacos.IHelloService;
import org.apache.dubbo.config.annotation.Service;

@Service
public class HelloServiceImpl implements IHelloService {

    @Override
    public String sayHello(String s) {
        return "Hello World:"+s;
    }
}

服务启动后,查看nacos上的服务列表,如图所示
在这里插入图片描述
点击详情可查看元数据
在这里插入图片描述
但是在这里并没有看到暴露出的接口,此时转到配置列表中可看到mapping-com.book.nacos.IHelloService
在这里插入图片描述

客户端

依赖

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</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.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-dubbo</artifactId>
            <version>2.1.1.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>com.gupaoedu.book.nacos</groupId>
            <artifactId>spring-cloud-nacos-sample-api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-nacos-discovery</artifactId>
            <version>2.1.1.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>



    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

配置文件

dubbo.cloud.subscribed-services=spring-cloud-nacos-sample
dubbo.scan.base-packages=com.book.nacos.bootstrap
spring.application.name=spring-cloud-nacos-consumer
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848

调用服务端

import com.book.nacos.IHelloService;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {

    @Reference
    private IHelloService helloService;

    @GetMapping("/say")
    public String sayHello(){
        return helloService.sayHello("springCloud-Dubbo");
    }
}

服务启动后可在nacos中查看服务
在这里插入图片描述
此时请求http://127.0.0.1:8080/say,可得到服务端返回给客户端的数据
在这里插入图片描述

二、原理浅析

架构图

在这里插入图片描述
从架构图中可以看到

  • 服务提供者在启动时向nacos发起服务注册,并建立心跳。
  • 服务消费者查询服务提供方实例,并每10秒拉取一次数据,而nacos检测到服务提供者异常时,会向消费者推送更新的列表。

源码

服务注册

直接定位到org.springframework.cloud.client.serviceregistry,AbstractAutoServiceRegistration,在这里有一个事件监听。

    public void onApplicationEvent(WebServerInitializedEvent event) {
        this.bind(event);
    }

监听WebServerInitializedEvent事件,即Webserver初始化完成之后,调用this.bind(event)。

    public void bind(WebServerInitializedEvent event) {
        ApplicationContext context = event.getApplicationContext();
        if (!(context instanceof ConfigurableWebServerApplicationContext) || !"management".equals(((ConfigurableWebServerApplicationContext)context).getServerNamespace())) {
            this.port.compareAndSet(0, event.getWebServer().getPort());
            this.start();
        }
    }

接着往下找,会发现最终会调用com.alibaba.cloud.nacos.registry.NacosServiceRegistry下的register(Registration registration)方法。

Dubbo在集成nacos时,在com.alibaba.cloud.dubbo.autoconfigure.DubboServiceRegistrationNonWebApplicationAutoConfiguration中也有一个监听刷新上下文之后的事件,他最终也会调用com.alibaba.cloud.nacos.registry.NacosServiceRegistry下的register(Registration registration)方法。

    @EventListener({ApplicationStartedEvent.class})
    public void onApplicationStarted() {
        this.setServerPort();
        this.register();
    }

    private void register() {
        if (!this.registered) {
            this.serviceRegistry.register(this.registration);
            this.registered = true;
        }
    }

那么下面就来看看这个register(Registration registration)方法
在此方法中直接看namingService.registerInstance(serviceId, group, instance),这里做了两件事,建立心跳和服务注册。

    public void registerInstance(String serviceName, String groupName, Instance instance) throws NacosException {
        if (instance.isEphemeral()) {
            BeatInfo beatInfo = new BeatInfo();
            beatInfo.setServiceName(NamingUtils.getGroupedName(serviceName, groupName));
            beatInfo.setIp(instance.getIp());
            beatInfo.setPort(instance.getPort());
            beatInfo.setCluster(instance.getClusterName());
            beatInfo.setWeight(instance.getWeight());
            beatInfo.setMetadata(instance.getMetadata());
            beatInfo.setScheduled(false);
            long instanceInterval = instance.getInstanceHeartBeatInterval();
            beatInfo.setPeriod(instanceInterval == 0L ? DEFAULT_HEART_BEAT_INTERVAL : instanceInterval);
            this.beatReactor.addBeatInfo(NamingUtils.getGroupedName(serviceName, groupName), beatInfo);   //建立心跳
        }

        this.serverProxy.registerService(NamingUtils.getGroupedName(serviceName, groupName), groupName, instance);  //服务注册
    }

这里的心跳机制是通过schedule定时发送心跳包给nacos服务端,nacos服务端根据心跳包不断更新服务状态。

    public void addBeatInfo(String serviceName, BeatInfo beatInfo) {
        LogUtils.NAMING_LOGGER.info("[BEAT] adding beat: {} to beat map.", beatInfo);
        String key = this.buildKey(serviceName, beatInfo.getIp(), beatInfo.getPort());
        BeatInfo existBeat = null;
        if ((existBeat = (BeatInfo)this.dom2Beat.remove(key)) != null) {
            existBeat.setStopped(true);
        }

        this.dom2Beat.put(key, beatInfo);
        this.executorService.schedule(new BeatReactor.BeatTask(beatInfo), beatInfo.getPeriod(), TimeUnit.MILLISECONDS);
        MetricsMonitor.getDom2BeatSizeMonitor().set((double)this.dom2Beat.size());
    }

而服务注册阶段最终会调用nacos提供的Open API,/nacos/v1/ns/instance,这里的逻辑在nacos的服务端,主要将客户端(业务服务提供者)缓存到内存,并建立心跳监测机制,通过定时任务不断检测客户端发送过来的心跳包,如果超时则改变服务状态。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值