10 | 集成 Nacos:如何通过服务发现机制向服务提供者发起调用?
添加 Nacos 依赖项和配置信息
- 深入了解
- 翻译
- 解释
- 总结
Nacos服务发现与远程调用技术总结 本文深入介绍了Nacos服务发现机制及其在微服务化改造中的应用。通过注册到Nacos Server,服务提供者可以实现服务发现和注册,为构建完整的服务调用请求提供支持。文章详细介绍了在coupon-customer-serv服务中如何利用Nacos的服务发现功能获取可供调用的服务列表,并发起远程服务调用。涉及添加Nacos依赖项和配置信息、清理门户、删除实现层依赖、添加接口层依赖以及在项目的application.yml文件中添加Nacos的配置项等步骤。此外,还介绍了使用Webflux发起远程调用以及搭建基于Nacos的服务治理方案的方法。最后,文章详细介绍了如何添加WebClient对象,并在业务类中注入WebClient对象,并发起服务调用。通过本文,读者可以全面了解Nacos服务治理改造的流程和原理,为深入学习和应用提供了良好的基础。文章还介绍了Nacos服务发现的底层实现,通过UpdateTask类实现了服务端注册表的底层原理。整体而言,本文内容涵盖了微服务化改造、Nacos服务发现功能、Webflux服务调用等技术特点,对读者快速了解文章概览有很好的帮助。
《Spring Cloud 微服务项目实战》,新⼈⾸单¥59
全部留言(18)
- 最新
- 精选
- ~回答一下调用链路的问题: 首先在 spring.factory 文件中配置了 NacosDiscoveryClientConfiguration 类,用于 springboot 的初始化时的自动装配。在 NacosDiscoveryClientConfiguration 类中会向 spring 容器中添加 NacosWatch 这个 bean。顺着 NacosWatch 的 start 方法一路往下,就能看到:NacosWatch#start ->NacosNamingService#subscribe -> HostReactor#subscribe -> HostReactor#addTask;UpdateTask 就是作为 task 添加到定时执行队列里的。
作者回复: 非常棒!
2022-01-10227 - Lee KouKuKing【分享】nacos的“订阅者列表”中的多块网卡地址问题,以及应用名为unknown的问题: customer服务向nacos注册后,在nacos web的“订阅者列表”菜单中,发现订阅者的地址是我的第二块网卡的地址(我在笔记本上装过virtualbox,有一个虚拟网卡。说明:我是在win10上运行了3个nacos进程组成的集群。),并且应用名是:unknown。这样看着很别扭,我就想修改一下,于是在application.yml添加了spring.cloud.nacos.discovery.ip,但是发现不生效。最后通过源码发现在UpdateTask中请求所有服务器列表时:/instance/list,请求的clientIP是这样获取的: String ip = System.getProperty("com.alibaba.nacos.client.naming.local.ip",InetAddress.getLocalHost().getHostAddress()); 使用System.getProperty获取系统变量,而不是从application.yml中获取,如过获取不到就查找本机的网卡,由于本机有两块网卡,所有就选中了那块虚拟网卡的ip了。 同时/instance/list请求的app参数也是System.getProperty("project.name");这样获取的,由于没有获取到"project.name",所以就默认应用名是:unknown,然后我就在java启动服务加了这俩参数进行解决的。 不只为什么这俩参数不在application.yml中配置呢?这俩参数在application.yml中配置这样多方便呀。 java -D"com.alibaba.nacos.client.naming.local.ip"="192.168.18.8" -D"project.name"="customer" -jar coupon-customer-impl-1.0-SNAPSHOT.jar
作者回复: 使用虚拟机或者多网卡的同学可以参考上面的的解决方案哦
2022-02-036 - Avalon老师,我有两个疑问: 1、为什么依赖注入的是 WebClient.Builder,而不直接注入 WebClient? 2、bodyToMono 的返回值类型 Mono,“Mono”是什么意思?
作者回复: 注入builder的一个比较方便的原因是,你在使用webclient的时候就能利用builder的链式构建风格来注入参数。Mono可以理解为一个元素的发布者(publisher),像Mono和Flux都是响应式编程的一个概念,mono表示发布了empty或1个对象,同学也可以通过一些响应式编程的教程了解更多的应用方式。
2022-01-043 - Geek_e93c48老师,我发现UpdateTask通过当前类addTask()方法进行任务调度,顺着藤蔓一直摸上去:addTask()->scheduleUpdateIfAbsent()->NamingClientProxyDelegate.subscribe()->NacosNamingService.getAllInstances()->NamingFactory->App启动类加载时调用。
作者回复: 同学摸到了一个大瓜!非常不错,读源码就这么顺藤摸瓜,从启动入口正着摸,从结果处反着摸,反正一通十八Mo之后就都整明白了
2022-01-043 - alex_lai根据目前项目里的service discovery setup 所有在一个group里的service都可以互相调用? customer service 也可以被另外两个子项目调用?所以nacos有可以设置service topo的相关设置么? 大厂里PP也是有这个专门的architect和team 去review和维护吧
作者回复: customer service可以被任何子项目调用,可以用k8s中的service topo来管理,不过如果做topo的目的单纯为了实现集群优先的策略,直接定制本地负载均衡策略就好了, nacos的cluster属性会在服务发现的过程中封装到metadata节点,client端可以根据这个属性做routing定制 PP确实有冗长的review process,服务之间相互调用也要通过arch review,但这是一家技术基建很差劲的公司,被国内互联网大厂完爆的渣都不剩,没啥可借鉴的
2022-01-2132 - so longnacos服务发现正向顺藤摸瓜:主要靠NacosWatch实现SmartLifecycle,在spring容器初始化后开始进行服务发现 NacosDiscoveryClientConfiguration->NacosWatch.start()->NamingService. subscribe(String serviceName, String groupName, List<String> clusters, EventListener listener)->HostReactor. subscribe(String serviceName, String clusters, EventListener eventListener)
作者回复: 同学摸瓜水平越来越高了。Nacos在watch机制上有了一个比较大的改变,如果查看nacos老版本的源码你会发现nacosServicesWatch这个方法里简直一顿操作猛如虎,但是新版本里,nacosServicesWatch只做一件事就是发布心跳事件了,所以这个watch机制做了一个比较大的减法,没老版本那么牛逼的服务发现了
2022-01-052 - 6点无痛早起学习的和尚2 个问题: 1. 项目 customer 上的注解:@LoadBalancerClient(value = "coupon-template-serv", configuration = CanaryRuleConfiguration.class),没有说明是啥作用 2. 运行 customer 这个项目的时候会报错,Access to DialectResolutionInfo cannot be null when 'hibernate.dialect' not set, Google 解决方式:加入spring:jpa:database-platform: org.hibernate.dialect.MySQLDialect
作者回复: Loadbalancer注解是spring cloud loadbalancer的内容,在Nacos讲完之后紧接着一课里会讲到。如果项目版本和MySQL版本都保持和源码一致的话(在环境准备篇里有版本信息),那么新版里database-platform不用显式配置,默认auto-detect后会自动在日志里打印这一行 org.hibernate.dialect.Dialect: HHH000400: Using dialect: org.hibernate.dialect.MySQL8Dialect
2022-01-032 - 王鸿轩老师,以下这段代码似乎有问题(CouponCustomerServiceImpl -> findCoupon): Map<Long, CouponTemplateInfo> templateMap = webClientBuilder.build().get() .uri("http://coupon-template-serv/template/getBatch?ids=" + templateIds) .retrieve() .bodyToMono(new ParameterizedTypeReference<Map<Long, CouponTemplateInfo>>() {}) .block(); 好像不能在查询参数上直接拼接一个数组,要转化成xx=1,2,3...这样的形式
作者回复: templateIds这个参数是拼装好的1,2,3格式
2022-02-1521 - 摊牌咨询老师个阅读源码的思路与技巧,比如nacos的服务发现,如何从应用的角度追溯到UpdateTask这个类呢,想了解nacos的服务发现底层逻辑,最繁琐的办法是得从头来,搭建nacos的调试环境,下载源码跟踪分析,有没有办法在应用的时候作为切入点去分析局部的底层逻辑呢
作者回复: 其实有个简单的方法,就是从log追溯。因为大部分同学的习惯是下载下来代码,然后慢慢啃,我的习惯可能特殊一点,同学可以听一听看是不是适合自己哈。 我会下载下来nacos在本地运行起来,log级别调低,然后通过remote debug的方式把本地代码链接到运行的实例中,这时候你通过发起注册、心跳等方式,就很容易在日志中查到对应的响应类名,直接断点打上去顺藤摸瓜即可。 我感觉这个方式比较“直捣黄龙”一些
2023-08-17归属地:陕西 - 在路上老师可以聊聊这个吗:通过WebClient非阻塞方式优化性能
作者回复: 非阻塞一般是使用场景是在方法内发生多个并行调用的时候,使用类似future的方式缩短接口访问时间,现在用的比较多的是基于webflux的响应式编程,挺火的~
2023-01-20归属地:北京