环境:Nacos 1.4.2
在前两篇:Nacos注册中心实战和Nacos 配置中心实战阿鉴已经详细介绍了Nacos的两大功能,本篇就来补充一下之前未涉及到的小细节
有时候一个小细节就能使人自闭
OpenAPI
在讲注册中心内容时,我们已经知道Nacos本质上是一个服务,那么,是服务就会有接口,下面阿鉴给大家介绍一下注册实例接口
更多OpenAPI可查看Nacos官网:https://nacos.io/zh-cn/docs/open-api.html
注册实例接口
接口:/nacos/v1/ns/instance
请求方式:POST
参数:
名称 | 类型 | 是否必选 | 描述 |
---|---|---|---|
ip | 字符串 | 是 | 服务实例IP |
port | int | 是 | 服务实例port |
namespaceId | 字符串 | 否 | 命名空间ID |
weight | double | 否 | 权重 |
enabled | boolean | 否 | 是否上线 |
healthy | boolean | 否 | 是否健康 |
metadata | 字符串 | 否 | 扩展信息 |
clusterName | 字符串 | 否 | 集群名 |
serviceName | 字符串 | 是 | 服务名 |
groupName | 字符串 | 否 | 分组名 |
ephemeral | boolean | 否 | 是否临时实例 |
测试:
-
发送一个curl请求,当然使用Postman也可以
curl -i -X POST \ -H "Content-Type:application/json" \ 'http://192.168.2.11:8850/nacos/v1/ns/instance?serviceName=test&ip=123.123.123.123&port=8081&username=nacos&password=nacos'
-
打开Nacos控制台查看效果
由于只传了必要参数,所以命名空间和分组名称都是默认的。
注意:由于我们只注册了实例,并未定时发送心跳,所以实例会在一定时间内被Nacos剔除
-
打开详情
ip和端口号即为我们填入的信息
OpenAPI在服务中的关系
相信小伙伴已经发现了,我们在调用接口时传入的参数是什么,注册到Nacos上的实例信息就是什么,那么在实际项目中能不能也这样玩呢?
在之前我们使用Nacos时,我们使用的配置是这样:
server:
port: 8080
spring:
application:
name: my-order
cloud:
nacos:
discovery:
server-addr: 192.168.2.11:8850
username: nacos
password: nacos
此时我们并未使用ip和port配置,Nacos将自动发现本地ip地址进行注册, port则使用
server.port
现在我们将ip
和port
加上
server:
port: 8080
spring:
application:
name: my-order
cloud:
nacos:
discovery:
server-addr: 192.168.2.11:8850
ip: 123.123.123.123
port: 1234
username: nacos
password: nacos
但实际上我本机ip地址为192.168.65.91
启动服务并在控制台查看服务详情
此时IP和端口就成了我们实际配置了的
心急的小伙伴这时候可能就会给阿鉴个大嘴巴子:讲那么多,这有啥用?!
阿鉴:不急不急
容器部署
在实际项目使用时,我们肯定倾向于让服务自己发现IP和端口号进行注册。
多实例部署时,谁关心你的本机ip是个啥,一个服务一会在那台机器,一会在这台机器,不可能每次部署时都改下配置。
但是有一种情况让Nacos自己发现IP是不可行的。那就是使用容器部署服务。
-
比如我们在
192.168.2.11
的服务器上部署一个my-goods
服务,此时Nacos自动发现的IP实际上是容器内部IP,如172.19.0.16
-
现在尝试使用在
192.168.2.12
的服务器上的my-order
服务,对my-goods
服务进行调用,此时会收到一个拒绝连接错误,因为调用的地址是172.19.0.16
,但实际需要的地址是192.168.2.11
问题解决
简单的办法就是在配置文件中加上ip的配置,如
server:
port: 8081
spring:
application:
name: my-goods
cloud:
nacos:
discovery:
server-addr: 192.168.2.11:8850
ip: 192.168.2.11
username: nacos
password: nacos
此时my-goods注册到Nacos上的地址就是服务器的地址了。
但是这种方式有个很明显的弊端,就是服务迁移时需要改动配置,多实例部署时需要频繁改动配置。
一个更优雅的方式
我们把配置改成如下:
server:
port: 8081
spring:
application:
name: my-goods
cloud:
nacos:
discovery:
server-addr: 192.168.2.11:8850
ip: ${HOST_IP_ADDRESS:127.0.0.1}
username: nacos
password: nacos
此时ip配置中增加了变量:HOST_IP_ADDRESS
docker-compose.yaml
version: '3.5'
services:
my-goods:
restart: always
image: my-goods
container_name: my-goods
environment:
HOST_IP_ADDRESS: $HOST_IP_ADDRESS
TZ: Asia/Shanghai
ports:
- 8081:8081
在执行docker-compose
前,将HOST_IP_ADDRESS
输出到环境变量中
export HOST_IP_ADDRESS=$(ifconfig eth0 | grep -E "([0-9]{1,3}\.){3}[0-9]{1,3}" | awk '{ print $2 }'| cut -f2 -"d:")
这行命令表示将本机ip输出到环境变量
HOST_IP_ADDRESS
中这个步骤可根据不同的部署工具进行执行,比如阿鉴用的是gitlab-ci,就是在gitlab-ci中执行的。
如此,使用容器部署的方式便优雅完成了~
边车挂载
奇技淫巧
当我们发现了奥秘:只要我们配了IP,配的IP是啥,注册到Nacos的IP就是啥。
掌握奇技淫巧的程序员们有没有想到一些骚操作呢?阿鉴这里却是想到了一个哦~
my-sidercar将my-integral的信息注册到Nacos上
-
新建一个
my-sidecar
服务,配置如下server: port: 8082 spring: application: name: my-sidecar main: allow-bean-definition-overriding: true cloud: nacos: discovery: server-addr: 192.168.1.11:8850 namespace: public service: my-integral ip: 192.168.65.91 port: 8083 username: nacos password: nacos management: endpoints: web: exposure: include: "*"
注册到Nacos的信息是
my-integral
服务的 -
新建一个Spring Boot
my-integral
服务(注意不是SpringCloud服务,不集成Nacos),配置如下server: port: 8083 spring: application: name: my-integral
spring.application.name 配置加不加无所谓
-
在
my-integral
服务中编写接口@Slf4j @RestController @RequestMapping("/integral") public class IntegralController { @GetMapping("/remain") public String remain(){ log.info("积分服务被调用了"); Random random = new Random(); int i = random.nextInt(100); return "您当前的积分为:" + i; } }
-
启动项目并打开控制台
该信息是由my-sidecar注册而来,而非my-integer所注册的,因为my-integral并未集成Nacos
-
在
my-order
编写调用代码@RestController @RequestMapping("/order") public class OrderController { @Resource private RestTemplate restTemplate; @GetMapping("/integral") public String integral(){ String url = "http://my-integral/integral/remain"; return restTemplate.getForObject(url, String.class); } }
-
启动
my-order
测试服务调用成功了
回顾一下我们做了什么:我们使用配置ip的奥秘将一个并未集成Nacos的my-integral
信息注册到了Nacos上,然后通过my-order
成功发起了调用~
意义
这样做有什么意义呢?难道真就为了骚一把?不是的。
假设我们现在有这样的需求,有一个老项目old-project
想要加入到微服务系统中,但是这个old-project
集成Nacos的成本过高,那么我们就可以使用这样的方式了。
这样的方式支持非Java语言哦~
这里阿鉴偷偷告诉大家,这个方式其实有个术语,叫做:边车模式。
Nacos的边车模式
其实Nacos已经实现了边车模式,集成方式非常简单
-
在原Nacos项目(my-sidecar)中引入依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-webflux</artifactId> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-sidecar</artifactId> </dependency>
-
编写配置
server: port: 8082 spring: application: name: my-sidecar main: allow-bean-definition-overriding: true cloud: nacos: discovery: server-addr: 192.168.1.11:8850 service: my-integral sidecar: ip: 127.0.0.1 port: 8083 health-check-url: http://127.0.0.1:8083/integral/health management: endpoints: web: exposure: include: "*"
ip:my-integral的IP
port: my-integral的端口
health-check-url: my-integral的健康检查地址
-
在
my-integral
服务中增加接口@RestController @RequestMapping("/integral") public class IntegralController { @GetMapping("/health") public Map<String,String> health(){ Map<String, String> map = new HashMap<>(2); map.put("status", "UP"); return map; } }
返回的内容必须是:status: UP
-
测试
小结
本篇补充了关于Nacos的一些细节,首先介绍了Nacos的OpenAPI, 通过OpenAPI延伸出了如何进行容器部署,以及边车模式,希望大家有所收获。