Nacos 集群成员发现机制与自定义实现

前言:Nacos 可作为注册中心、配置中心,其组成集群对外提供一致的服务,类似于 Zookeeper;zk 的集群成员列表是通过其配置文件 zoo.cfg 维护的 ,其它类似的组件不再讨论,那么 nacos 的集群成员是通过什么机制发现的呢?

Nacos 集群成员发现

MemberLookup

逻辑说明

Nacos 在启动时创建 ServerMemberManager(核心的集群成员操作类),它会调用 LookupFactory.createLookup() 通过 nacos.core.member.lookup.type 指定的类别初始化 MemberLookup 实现类;后续的成员发现和变更由 MemberLookup.afterLookup() 通知到 ServerMemberManager,此后"配置管理模块"、"注册中心模块"所感知的集群成员都由 ServerMemberManager 取得。

源码关注
  • ServerMemberManager **集群成员的所有操作都汇聚于此类,初始化、成员变更、成员列表、集群间汇报等。 **
    • LookupFactoty.createLookup()
  • AbstractMemberLookup
    • StandaloneMemberLookup only self
    • FileConfigMemberLookup watch conf/cluster.conf
    • AddressServerMemberLookup http get from address server

在 k8s 部署 Nacos 集群

nacos 官方提供 docker 镜像,并结合 nacos-k8s-yaml附录:peer-finder-cluster-demo.yaml)部署于 Kubernetes,以部署 nacos 三个节点为例。
查看 yaml 可看到其包含了一个 initContainer: peer-finder-plugin-install,用来干嘛?其实 peer-finder 插件是用于不断地监听 nacos-headless 的服务列表变更,若列表有变更则写入 conf/cluster.conf,如下:

nacos-0.nacos-headless.default.svc.cluster.local:8848
nacos-1.nacos-headless.default.svc.cluster.local:8848
nacos-2.nacos-headless.default.svc.cluster.local:8848

在这里插入图片描述

所以该方案还是利用了上节所述 FileConfigMemberLookup 成员发现机制,conf/cluster.conf 的维护由一个脚本不断地更新,在集群扩缩节点时通过 nacos-headless 准实时获得变更成员,从而每个节点都能维持一致的成员列表。

上述方案有什么缺陷?

  • 有状态:StatefulSet
  • 无法跨 k8s 集群部署 nacos 集群:因为依赖 nacos-headless (k8s Service) ,k8s 集群内的 CoreDNS 域名。

那有什么方法解决呢?可以清楚地知道,上述的 nacos 集群有状态就是与 cluster.conf 文件的维护有关,那么在不引入额外依赖的情况下能想到的唯一解决方案就是使用“配置管理模块”依赖的数据库。(注:注册中心模块不依赖数据库

在 k8s 部署无状态的 Nacos 集群 - Customize DatabaseMemberLookup

集群间成员的感知就是一个成员列表,各节点只要知道一致的成员列表就行;数据库是中心化的依赖,借鉴 AddressServerMemberLookup 实现类似的成员列表发现逻辑,实现基于数据库的集群成员发现:DatabaseMemberLookup
在这里插入图片描述

  • 节点启动
    • 清理超时的过期成员节点
    • (不断心跳)将自己维护到数据库
    • 从数据库获取所有成员列表(有变更则通知 ServerMemberManager)
  • 节点下线
    • 清理自己在数据库的记录
    • 将自己下线的事件实时告知其他成员(实时性很重要)

以此,Nacos 仅依赖数据库,不断维护自身心跳且节点下线时主动通知其他成员,各个节点均能准实时地获取一致的(在线)成员列表。

附录

peer-finder-cluster-demo.yaml
### Nacos ###
#### https://hub.docker.com/r/nacos/nacos-server
#### https://github.com/nacos-group/nacos-k8s
#### https://github.com/nacos-group/nacos-docker

---
apiVersion: v1
kind: Service
metadata:
  name: nacos-headless
  labels:
    app: nacos-headless
spec:
  selector:
    app: nacos
  type: ClusterIP
  clusterIP: None
  ports:
    - port: 8848
      name: server
      targetPort: 8848
    - port: 7848
      name: rpc
      targetPort: 7848

---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: nacos
spec:
  serviceName: nacos-headless
  selector:
      matchLabels:
        app: nacos
  replicas: 3
  template:
    metadata:
      labels:
        app: nacos
      annotations:
        pod.alpha.kubernetes.io/initialized: "true"
        prometheus.io/path: /nacos/actuator/prometheus
        prometheus.io/port: '8848'
        prometheus.io/scrape: 'true'
    spec:
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            - labelSelector:
                matchExpressions:
                  - key: "app"
                    operator: In
                    values:
                      - nacos
              topologyKey: "kubernetes.io/hostname"
      initContainers:
        - name: peer-finder-plugin-install
          image: nacos/nacos-peer-finder-plugin:1.1
          imagePullPolicy: Always
          volumeMounts:
            - name: plugin-dir
              mountPath: /home/nacos/plugins/peer-finder
      containers:
        - name: k8snacos
          imagePullPolicy: Always
          image: nacos/nacos-server:1.4.2
          resources:
            requests:
              memory: "8Gi"
              cpu: "4"
          ports:
            - containerPort: 8848
              name: client
            - containerPort: 7848
              name: rpc
          env:
            - name: JVM_XMS
              value: 6g
            - name: JVM_XMX
              value: 6g
            - name: JVM_XMN
              value: 3g
            - name: JVM_MS
              value: 128m
            - name: JVM_MMS
              value: 320m
            - name: SERVICE_NAME
              value: "nacos-headless"
            - name: DOMAIN_NAME
              value: "cluster.local"
            - name: POD_NAMESPACE
              valueFrom:
                fieldRef:
                  apiVersion: v1
                  fieldPath: metadata.namespace
            - name: NACOS_REPLICAS
              value: "3"
            - name: MYSQL_SERVICE_HOST
              valueFrom:
                configMapKeyRef:
                  name: nacos-cm
                  key: mysql.host
            - name: MYSQL_SERVICE_DB_NAME
              valueFrom:
                configMapKeyRef:
                  name: nacos-cm
                  key: mysql.db.name
            - name: MYSQL_SERVICE_PORT
              valueFrom:
                configMapKeyRef:
                  name: nacos-cm
                  key: mysql.port
            - name: MYSQL_SERVICE_USER
              valueFrom:
                configMapKeyRef:
                  name: nacos-cm
                  key: mysql.user
            - name: MYSQL_SERVICE_PASSWORD
              valueFrom:
                configMapKeyRef:
                  name: nacos-cm
                  key: mysql.password
            - name: MODE
              value: "cluster"
            - name: NACOS_SERVER_PORT
              value: "8848"
            - name: PREFER_HOST_MODE
              value: "hostname"
            - name: NACOS_SERVERS
              value: "nacos-0.nacos-headless.default.svc.cluster.local:8848 nacos-1.nacos-headless.default.svc.cluster.local:8848 nacos-2.nacos-headless.default.svc.cluster.local:8848"
            - name: NACOS_AUTH_ENABLE
              value: "true"
            - name: NACOS_AUTH_TOKEN
              value: "SecretKey012345678901234567890123456789012345678901234567890123456789TODO"
            - name: NACOS_AUTH_CACHE_ENABLE
              value: "true"
            - name: NACOS_AUTH_USER_AGENT_AUTH_WHITE_ENABLE
              value: "false"
            - name: NACOS_AUTH_IDENTITY_KEY
              value: serverIdentityTODO
            - name: NACOS_AUTH_IDENTITY_VALUE
              value: securityTODO
          volumeMounts:
            - name: plugin-dir
              mountPath: /home/nacos/plugins/peer-finder
      volumes:
        - name: plugin-dir
          emptyDir: {}


---
apiVersion: v1
kind: ConfigMap
metadata:
  name: nacos-cm
data:
  mysql.host: "TODO"
  mysql.db.name: "TODO"
  mysql.port: "3306"
  mysql.user: "TODO"
  mysql.password: "TODO"


# ---
# ------------------- App Ingress ------------------- #
# apiVersion: extensions/v1beta1
# kind: Ingress
# metadata:
#   name: nacos-headless
# #  namespace: default
# spec:
#   rules:
#   - host: TODO
#     http:
#       paths:
#       - path: /
#         backend:
#           serviceName: nacos-headless
#           servicePort: server
参考文献
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值