Nacos在Python微服务中的应用:构建配置中心与实时监听配置变更

616 阅读8分钟

在微服务架构中,配置管理是一个至关重要的环节。Nacos(Naming and Configuration Service)作为一款优秀的配置中心和服务管理平台,为微服务提供了动态配置服务。本文将介绍如何使用 Nacos 作为 Python 微服务的配置中心,以及如何实现配置的实时监听与自动重启功能。

NACOS

NACOS

一、Nacos 集群搭建

在微服务架构中,Nacos 作为核心的服务发现和配置管理组件,其稳定性和可用性至关重要。

NACOS集群

NACOS集群

为什么需要搭建 Nacos 集群?

  1. 单点故障风险:单节点的 Nacos 部署存在单点故障的风险。如果该节点发生故障,所有依赖 Nacos 的微服务将无法进行配置拉取、服务注册与发现,导致整个系统不可用。
  2. 性能瓶颈:在单节点模式下,Nacos 无法有效处理大量请求。在高并发或大数据量的场景中,容易导致响应延迟或系统崩溃。
  3. 扩展性差:单节点无法根据流量需求进行水平扩展,当流量激增时,系统难以应对。

通过集群部署,Nacos 可以实现高可用性和负载均衡,提高系统的稳定性、扩展性和容错能力。

在 NACOS 集群架构中加入 NGINX 是出于什么考虑?

  1. 负载均衡:Nginx 作为反向代理服务器,可以均匀地分发客户端请求到多个 Nacos Server 实例上,从而实现负载均衡,提高系统的处理能力和响应速度。
  2. 高可用性:通过 Nginx 可以实现故障转移和高可用性。如果一个 Nacos Server 节点发生故障,Nginx 可以将流量自动转移到其他可用的 Server 节点上,确保服务的不间断运行。
  3. 安全性增强:Nginx 可以作为第一道防线,对进入 Nacos 集群的所有请求进行过滤和处理,如 SSL/TLS 加密、IP 限制等,增加系统的安全性。
  4. 性能优化:Nginx 具有高性能的网络模型和缓存机制,能够有效提升系统整体性能,减少延迟。
  5. 简化部署和管理:通过集中管理 Nginx 配置,可以更方便地对整个 Nacos 集群进行管理和维护。
  6. 动态路由:Nginx 支持根据不同的条件(如 URL、HTTP 头信息)来决定如何转发请求,这为灵活的路由策略提供了可能。
  7. 访问控制:可以通过 Nginx 设置访问控制策略,比如限制某些 IP 地址或域名的访问权限。
  8. 日志记录和分析:Nginx 可以记录详细的访问日志,便于监控和分析网络活动。

加入 Nginx 不仅提升了 Nacos 集群的性能和可靠性,还增强了其安全性和管理的灵活性。

使用 docker-compose 来搭建 NACOS 集群

使用Docker Compose来搭建 Nacos 集群是可行的。Docker Compose 允许通过定义一个 yaml 文件来配置应用程序的服务,从而简化了 Nacos 集群的部署过程。使用 Docker Compose,可以方便地管理多个 Nacos 实例,实现集群的快速部署和扩展。

version: "3.8"
services:
  nacos1:
    hostname: nacos1
    container_name: nacos1
    image: nacos/nacos-server:latest
    volumes:
      - ./cluster-logs/nacos1:/home/nacos/logs
    ports:
      - "7848:7848"
      - "18848:8848"
      - "9868:9848"
      - "9850:9849"
    env_file:
      PREFER_HOST_MODE=hostname
   NACOS_SERVERS=nacos1:8848 nacos2:8848 nacos3:8848
      SPRING_DATASOURCE_PLATFORM=mysql
      MYSQL_SERVICE_HOST=nacos-mysql
      MYSQL_SERVICE_DB_NAME=nacos_devtest
      MYSQL_SERVICE_PORT=3306
      MYSQL_SERVICE_USER=nacos
      MYSQL_SERVICE_PASSWORD=nacos
      MYSQL_SERVICE_DB_PARAM=characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useSSL=false&allowPublicKeyRetrieval=true
      NACOS_AUTH_IDENTITY_KEY=2222
      NACOS_AUTH_IDENTITY_VALUE=2xxx
      NACOS_AUTH_TOKEN=SecretKey012345678901234567890123456789012345678901234567890123456789
      NACOS_AUTH_ENABLE=true
      NACOS_AUTH_USER_AGENT_AUTH_WHITE_ENABLE=true
    restart: always
    depends_on:
      nacos-mysql:
        condition: service_healthy

  nacos2:
    hostname: nacos2
    image: nacos/nacos-server:latest
    container_name: nacos2
    volumes:
      - ./cluster-logs/nacos2:/home/nacos/logs
    ports:
      - "7849:7848"
      - "18849:8848"
      - "9869:9848"
      - "9851:9849"
    env_file:
      PREFER_HOST_MODE=hostname
   NACOS_SERVERS=nacos1:8848 nacos2:8848 nacos3:8848
      SPRING_DATASOURCE_PLATFORM=mysql
      MYSQL_SERVICE_HOST=nacos-mysql
      MYSQL_SERVICE_DB_NAME=nacos_devtest
      MYSQL_SERVICE_PORT=3306
      MYSQL_SERVICE_USER=nacos
      MYSQL_SERVICE_PASSWORD=nacos
      MYSQL_SERVICE_DB_PARAM=characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useSSL=false&allowPublicKeyRetrieval=true
      NACOS_AUTH_IDENTITY_KEY=2222
      NACOS_AUTH_IDENTITY_VALUE=2xxx
      NACOS_AUTH_TOKEN=SecretKey012345678901234567890123456789012345678901234567890123456789
      NACOS_AUTH_ENABLE=true
      NACOS_AUTH_USER_AGENT_AUTH_WHITE_ENABLE=true
    restart: always
    depends_on:
      nacos-mysql:
        condition: service_healthy
  nacos3:
    hostname: nacos3
    image: nacos/nacos-server:latest
    container_name: nacos3
    volumes:
      - ./cluster-logs/nacos3:/home/nacos/logs
    ports:
      - "7850:7848"
      - "18850:8848"
      - "9870:9848"
      - "9852:9849"
    env_file:
      PREFER_HOST_MODE=hostname
   NACOS_SERVERS=nacos1:8848 nacos2:8848 nacos3:8848
      SPRING_DATASOURCE_PLATFORM=mysql
      MYSQL_SERVICE_HOST=nacos-mysql
      MYSQL_SERVICE_DB_NAME=nacos_devtest
      MYSQL_SERVICE_PORT=3306
      MYSQL_SERVICE_USER=nacos
      MYSQL_SERVICE_PASSWORD=nacos
      MYSQL_SERVICE_DB_PARAM=characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useSSL=false&allowPublicKeyRetrieval=true
      NACOS_AUTH_IDENTITY_KEY=2222
      NACOS_AUTH_IDENTITY_VALUE=2xxx
      NACOS_AUTH_TOKEN=SecretKey012345678901234567890123456789012345678901234567890123456789
      NACOS_AUTH_ENABLE=true
      NACOS_AUTH_USER_AGENT_AUTH_WHITE_ENABLE=true
    restart: always
    depends_on:
      nacos-mysql:
        condition: service_healthy
  nacos-mysql:
    container_name: nacos-mysql
    build:
      context: .
      dockerfile: ./image/mysql/5.7/Dockerfile
    image: example/mysql:5.7
    env_file:
      MYSQL_ROOT_PASSWORD=root
      MYSQL_DATABASE=nacos_devtest
      MYSQL_USER=nacos
      MYSQL_PASSWORD=nacos
      LANG=C.UTF-8
    volumes:
      - ./nacos-mysql:/var/lib/mysql
    ports:
      - "13306:3306"
    healthcheck:
      test: [ "CMD", "mysqladmin" ,"ping", "-h", "localhost" ]
      interval: 5s
      timeout: 10s
      retries: 10

使用 compose 模式搭建 Nacos 集群,除了数据持久化之外,还需要关注

  1. 集群架构设计:合理规划集群的节点数量和拓扑结构,确保集群的高可用性和负载均衡
  2. 数据库准备:Nacos 集群需要使用数据库进行数据共享。选择合适的数据库(如 MySQL)并正确配置,确保集群中的 Nacos 实例可以访问和同步数据
  3. 配置文件修改:对于每个 Nacos 节点,需要修改配置文件以指定数据库信息和集群节点信息
  4. 网络配置:确保集群中的所有 Nacos 节点可以相互通信,网络配置是关键
  5. 集群管理:包括集群的启动、监控和维护,确保集群的稳定运行

搭建 Nacos 集群是提高微服务架构性能和可靠性的重要步骤,用 Docker Compose 可以简化集群部署过程,但在部署时还需要注意多个方面,以确保集群的稳定性和效率

二、配置中心搭建

微服务架构对配置中心的需求极为关键,它要求配置中心能够提供集中管理、动态更新、配置隔离、版本控制、高可用性、安全性、容错性、可扩展性、实时监控和环境区分等功能。这些特性确保了微服务配置的一致性、灵活性和系统稳定性,是微服务高效运行的重要保障。

录入配置到 Nacos

在 Nacos 配置列表中,开发人员需手动录入各个微服务的配置内容。配置以 JSON 格式存储,便于后端程序解析。

微服务拉取配置

    def load_config_func(self, group="default", tenant="public"):
        project_name = self.project_name
        if not all([self.username, self.nacos_password, self.nacos_host, self.nacos_port]):
            config_logger.error("Nacos credentials are not set in .env file.")
        config_logger.info(f"正在获取配置: dataId={project_name}; group={group}; tenant={tenant}")
        client = nacos.NacosClient(
            server_addresses=f"{self.nacos_host}:{self.nacos_port}",
            username=self.username,
            password=self.nacos_password
        )
        nacos_config = client.get_config(project_name, 'default')
        config_dict = json.loads(nacos_config)
        # 将内容写入到CONFIG_FILENAME中
        try:
            with open(CONFIG_FILENAME, 'w', encoding='utf-8'as f:
                json.dump(config_dict, f, indent=4, ensure_ascii=False)
            config_logger.info(f"配置中心自动LOAD配置:写入文件成功")
        except Exception as e:
            config_logger.error(f"配置中心自动LOAD配置:写入文件失败{str(e)}")
        return config_dict

实时监听配置变更

  1. 启动配置监听器,该函数创建一个守护线程,用于监听配置变更。
    def start_config_watcher(self):
        if not hasattr(self, '_watcher_thread'):
            self._watcher_thread = threading.Thread(
                target=self._start_config_watcher,
                daemon=True
            )
            self._watcher_thread.start()
    # 监听器
    def _start_config_watcher(self):
        project_name = self.project_name
        client = nacos.NacosClient(
            server_addresses=f"{self.nacos_host}:{self.nacos_port}",
            username=self.username,
            password=self.nacos_password
        )
        client.add_config_watcher(project_name, 'default', self.config_change_callback)
        config_logger.info("配置监听器已启动")

2. 配置变更回调函数,当配置发生变化时,以下回调函数将被触发,该函数将新的变更配置内容写入本地文件,并调用重启后端的函数 3. 自动重启后端

    def restart_django_runserver(self):
        config_logger.info(f"监听到{self.project_name}的配置发生变化,准备自动重载后端")
        try:
            if os.name == 'nt':  # 如果是Windows系统
                config_logger.info("请手动重启服务")
            else:
                subprocess.run(
                    ['supervisorctl''-c''/app/supervisord_prd.conf''restart''uwsgi'],
                    check=True
                )
                config_logger.info("后端自动重启成功")
        except subprocess.CalledProcessError as e:
            config_logger.error(f"后端重启失败: {e}")

通过整合python与nacos-python-sdk,我们初步构建了一个基于Nacos的微服务配置中心,实现了配置的集中管控、实时监控以及服务的自动重启机制。这一方案显著提升了微服务的稳定性和可维护性,为微服务架构的持续迭代和扩展奠定了坚实的基础。在项目实践中,开发团队可根据具体场景和需求,对配置管理策略进行细化和优化。虽然当前实现的是一个基础版本,但留有广阔的改进空间,未来我们将持续对其进行精雕细琢。