服务端开发(8) NACOS
2023-08-09 14:53:19 # NJU # 服务端开发

nacos官方文档: https://nacos.io/zh-cn/docs/v2/what-is-nacos.html

基于NACOS的数据配置

1. 配置信息

将服务配置信息与代码分开

  • 配置信息硬编码到代码中
  • 分离的外部属性文件
  • 与物理部署分离,如外部数据库
  • k8s-configmap
  • 配置数据作为单独的服务提供

微服务的配置数据来源

  • Spring Cloud Config:文件系统、Git、Eureka、Consul
  • nacos:mysql、h2、derby

image-20230407135021721

2. nacos

nacos在docker上的部署

  • 下载脚本:https://github.com/nacos-group/nacos-docker
  • 在Docker上直接部署
    • docker run --name nacos-quick -e MODE=standalone -p 8848:8848 -p 9848:9848 -d nacos/nacos-server:v2.1.2
  • docker-compose部署
    • docker-compose -f example/standalone-derby.yaml up

nacos在k8s上的部署

  • 下载脚本:https://github.com/nacos-group/nacos-k8s
  • 本机的hosts文件里配置域名
    • 127.0.0.1 www.nacos.com
  • 参考我提供的文件,修改文件 ./deploy/nacos/nacos-quick-start.yaml,改成 standalone 模式
  • 部署
    • kubectl create -f ./deploy/mysql/mysql-local.yaml
    • kubectl create -f ./deploy/nacos/nacos-quick-start.yaml
  • 通过 ingress 访问:www.nacos.com/nacos,用户名:nacos,密码:nacos
  • k8s集群内访问,服务名:nacos-headless,端口号:8848
  • 去部署
    • kubectl delete -f ./deploy/nacos/nacos-quick-start.yaml
    • kubectl delete -f ./deploy/mysql/mysql-local.yaml

测试-配置数据更新获取

  • curl -X POST "http://www.nacos.com/nacos/v1/cs/configs?dataId=nacos.cfg.dataId&group=test&content=HelloWorld"

  • curl -X GET "http://www.nacos.com/nacos/v1/cs/configs?dataId=nacos.cfg.dataId&group=test"

  • 在pod中测试

    • kubectl run -i -t --rm=true mycurl --image=curlimages/curl:latest --restart=Never --command -- sh
    • curl -X POST "http://nacos-headless:8848/nacos/v1/cs/configs?dataId=nacos.cfg.dataId&group=test&content=HelloWorld"
    • curl -X GET "http://nacos-headless:8848/nacos/v1/cs/configs?dataId=nacos.cfg.dataId&group=test"

3. curl

  • curl 是常用的命令行工具,用来请求 Web 服务器。它的名字就是客户端(client)的 URL 工具的意思。它的功能非常强大,命令行参数多达几十种。如果熟练的话,完全可以取代 Postman 这一类的图形界面工具
  • 安装:https://curl.se/download.html
  • Docker部署:docker run --rm -it curlimages/curl:latest sh
  • k8s部署:kubectl run -i -t --rm=true mycurl --image=curlimages/curl:latest --restart=Never --command -- sh

常用命令使用

  • -i 打印响应的标头
    • curl -i http://spittr:8080/spittr/spittles
  • 要求客户端重定向
    • -L 让 HTTP 请求跟随服务器的重定向。curl 默认不跟随重定向。
    • curl -L http://spittr:8080/spittr/spittles
  • -v 参数输出通信的整个过程,用于调试
    • curl -v http://tzs919:123456@spittr:8080/spittr/spittles
    • curl --trace - http://tzs919:123456@spittr:8080/spittr/spittles 输出二进制信息
  • 设置认证的用户名密码
    • curl http://tzs919:123456@spittr:8080/spittr/spittles
    • curl -u tzs919:123456 http://spittr:8080/spittr/spittles 等价

4. 简单的例子

Spring Boot

  • nacos的官方例子代码:https://github.com/nacos-group/nacos-examples.git
  • 代码路径:nacos-examples\nacos-spring-boot-example\nacos-spring-boot-config-example
  • 依赖:nacos-config-spring-boot-starter、nacos-config-spring-boot-actuator
  • 使用到的注解:@NacosPropertySource@NacosValue
  • nacos上配置数据,可手工配置,可实时更新

    • curl -X POST "http://www.nacos.com/nacos/v1/cs/configs?dataId=example&group=DEFAULT_GROUP&content=useLocalCache=true"
  • 获取配置数据

    • curl -X GET "http://localhost:8080/config/get"
  • 信息查询
    • curl -X GET "http://localhost:8080/actuator/health"|python -m json.tool
    • curl -X GET "http://localhost:8080/actuator/nacos-config" |python -m json.tool

Spring Cloud

  • nacos的官方例子代码:https://github.com/nacos-group/nacos-examples.git

  • 代码路径:nacos-examples\nacos-spring-cloud-example\nacos-spring-cloud-config-example

  • 依赖

    1
    2
    3
    4
    5
    <dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
    <version>0.2.1.RELEASE</version>
    </dependency>
  • bootstrap.properties,配置Nacos server地址

  • @Value 指定要获取的属性名

  • @RefreshScope 实时刷新,可以获取到来自nacos的最新修改

  • 到nacos上手工创建data id:example.properties,内容:useLocalCache=true

  • 运行服务:mvn spring-boot:run 或者直接在IDEA里运行

  • 访问:curl -X GET "http://localhost:8080/config/get"

创建适用不同环境的属性数据

  • @Profile
  • -Dspring.profiles.active=xxx
  • 命名约定:应用程序名称-环境名称.yml

dataId 的完整格式

  • ${prefix}-${spring.profiles.active}.${file-extension}
  • prefix 默认为 spring.application.name 的值,也可以通过配置项 spring.cloud.nacos.config.prefix 来配置
  • spring.profiles.active 即为当前环境对应的 profile
  • file-exetension 为配置内容的数据格式,可以通过配置项 spring.cloud.nacos.config.file-extension 来配置。目前只支持 properties 和 yaml 类型

licensingservice服务部署

image-20230408130705587

数据更新

  • 通过 Spring Cloud 原生注解 @RefreshScope 实现配置自动更新

如何知道一个服务可用

  • 在镜像中添加 netcat
  • nc -z 服务名 端口号

image-20230408131529514

敏感信息配置

  • 属性加密:对称加密(共享密钥)、非对称加密(公钥/私钥)

  • 使用共享密钥加密后,属性值的前面加上 {cipher} 前缀

  • 配置共享密钥:设置环境变量 ENCRYPT_KEY

  • 添加以下依赖

    1
    2
    3
    4
    <dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-rsa</artifactId>
    </dependency>

基于NACOS的服务注册与发现

1. 服务

nacos练习

  • 服务注册

    • curl -X POST "http://www.nacos.com/nacos/v1/ns/instance?serviceName=nacos.naming.serviceName&ip=20.18.7.10&port=8080"

    • curl -X GET "http://www.nacos.com/nacos/v1/ns/instance/list?serviceName=nacos.naming.serviceName" | python -m json.tool

  • Nacos中临时实例基于心跳上报方式维持活性,基本的健康检查流程基本如下:Nacos客户端会维护一个定时任务,每隔5秒发送一次心跳请求,以确保自己处于活跃状态。Nacos服务端在15秒内如果没收到客户端的心跳请求,会将该实例设置为不健康,在30秒内没收到心跳,会将这个临时实例摘除

    • “instanceHeartBeatInterval”: 5000, 心跳间隔
    • “instanceHeartBeatTimeOut”: 15000, 心跳超时,超过这个时间将服务置不健康状态
    • “ipDeleteTimeout”: 30000, 超过这个时间将服务移除

服务发现的好处

  • 快速水平伸缩,而不是垂直伸缩,不影响客户端
  • 提高应用程序的弹性

服务部署

image-20230408140342608

注: nacos 不负责转发请求, 仅用于存储各服务的访问地址

2. Spring Cloud家族

image-20230408140455307

Spring Cloud Alibaba

image-20230408140757600

image-20230408140830205

3. nacos实现服务注册与发现

使用到的starter依赖

  • 服务配置:com.alibaba.cloud,spring-cloud-starter-alibaba-nacos-config
  • 服务注册:com.alibaba.cloud,spring-cloud-starter-alibaba-nacos-discovery
  • 客户端负载均衡:org.springframework.cloud,spring-cloud-starter-loadbalancer
  • 简化客户端调用:org.springframework.cloud,spring-cloud-starter-openfeign

bootstrap.yml配置nacos

1
2
3
4
5
6
7
8
spring:
cloud:
nacos:
config:
server-addr: nacos-headless:8848
file-extension: yml
discovery:
server-addr: nacos-headless:8848

使用到的注解

  • @EnableDiscoveryClient
  • @EnableFeignClients
  • @LoadBalanced

4. 调用服务的三种方式

  • Spring DiscoveryClient
  • 使用支持LoadBalanced的RestTemplate
  • 使用OpenFeign(@FeignClient)
    • OpenFeign是一款声明式、模板化的HTTP客户端,Feign可以帮助我们更快捷、优雅地调用HTTP API

Spring DiscoveryClient

  • 启动类加 @EnableDiscoveryClient
  • 注入:private DiscoveryClient discoveryClient;
    • discoveryClient.getInstances
    • new RestTemplate
    • restTemplate.exchange

使用支持LoadBalanced的RestTemplate

  • @LoadBalanced
  • 注入: RestTemplate restTemplate;
  • restTemplate.exchange,指定要调用的服务名,而不是IP

使用OpenFeign(@FeignClient

  • 启动类加注解:@EnableFeignClients
  • 定义接口
  • 接口加注解:@FeignClient("organizationservice")

有用的命令

  • 查看日志:kubectl logs -f -l app=organizationservice --all-containers=true
  • 重部署:kubectl rollout restart deployment organizationservice
  • 扩容:kubectl scale deployment organizationservice --replicas 5

5. 健康检查

  1. 临时实例的客户端主动上报机制,临时实例每隔 5s 发送一个心跳包给 Nacos 服务器端
  2. 永久实例的服务端反向探测机制,永久实例支持 3 种探测协议,TCP、HTTP 和 MySQL,默认探测协议为 TCP, 也就是通过不断 ping 的方式来判断实例是否健康。

image-20230408143113182

6. 负载均衡策略

  • roundLoadBalancer
  • randomLoadBalancer
  • @LoadBalancerClient(name = "organizationservice", configuration = Application.class)
  • 对第二、三种调用都有效