如果想在 Python 项目中利用 Nacos 动态配置服务该怎么做呢?
文章有什么不对的,请各位大佬热心指导,这个很重要
1、安装依赖
nacos-sdk-python 项目是 Nacos OpenAPI 的 Python 实现,可用于监听 Nacos 配置文件的数据变动
# 安装以来
pip3 install nacos-sdk-python
项目地址: github.com/nacos-group…
2、配置文件 app.conf
[Nacos]
serverAddr = 127.0.0.1:8848
namespace = dev
serverName = my-server
username = nacos
password = nacos
3、读取配置文件
import configparser
import os
#检测配置文件是否存在
if not os.path.isfile('app.conf'):
print("配置文件 app.conf 不存在,程序退出。")
input("按下任意键退出...")
exit()
try:
# 读取配置文件
config = configparser.ConfigParser()
config.read('app.conf')
# 从配置文件获取配置参数
serverAddr = config.get('Nacos', 'serverAddr')
namespace = config.get('Nacos', 'namespace')
serverName = config.get('Nacos', 'serverName')
username = config.get('Nacos', 'username')
password = config.get('Nacos', 'password')
gPort = config.get('Nacos', 'gPort')
except:
print("配置文件数据不正确,请检查配置文件!")
input("按下任意键退出...")
exit()
Properties与 YAML 配置文件的区别是
- YAML 使用缩进和冒号来表示层次结构
- Properties 使用等号连接键值对
4、构建nacos的客户端
client = NacosClient(server_addresses=serverAddr, namespace=namespace, username=username, password=password)
5、服务注册到nacos
import time
import threading
def __ref_nacos_listener():
metadata = {"gRPC.port": 10253}
while True:
client.send_heartbeat(service_name=serverName, ip=HostIP, metadata=metadata, port=HostPort)
time.sleep(3)
def register_init():
t = threading.Thread(target=__ref_nacos_listener)
t.start()
# 启动心跳保证服务存活注册
register_init()
6、获取服务调用
import random
import requests
def __get_server_info(servername):
response = client.list_naming_instance(servername)
hosts = response["hosts"]
server_info = []
for host in hosts:
ip = host["ip"]
port = host["port"]
metadata = host["metadata"]
server_details = {
"ip": ip,
"port": port,
"metadata": metadata
}
server_info.append(server_details)
return random.choice(server_info)
def get_server(servername, path, params):
s1 = __get_server_info(servername)
url = f"http://{s1['ip']}:{s1['port']}/{path}"
response = requests.get(url, params)
if response.status_code == 200:
return response.text
else:
print("请求异常:", response.status_code)
return 999
def post_server(servername, path, json):
s1 = __get_server_info(servername)
url = f"http://{s1['ip']}:{s1['port']}/{path}"
# 参数里的 json 类似 以JSON 格式传递,data 以 form 表单的形式
response = requests.post(url, json=json)
# status_code 是个固定key
if response.status_code == 200:
data = response.text
return data
else:
print("请求异常:", response.status_code)
return 999
7、nacos 中 config 的配置加载
global nacos_data
nacos_data ={}
# 初始化,第一次获取
def config_init(data_id, group):
global nacos_data
config_list = client.get_config(data_id, group).split("\n")
properties = {}
for config_item in config_list:
# 过滤有用的键值对
if config_item.find('=') > 0:
strs = config_item.replace('\n', '').split('=')
properties[strs[0].replace(' ', '')] = strs[1].replace(' ', '')
nacos_data = properties
# Nacos数据变动时触发
def __nacos_data_change_callback(config):
global nacos_data
# 数据解析,
config_list = config['content'].split("\n")
properties = {}
for config_item in config_list:
# 过滤有用部分
if config_item.find('=') > 0:
strs = config_item.replace('\n', '').split('=')
properties[strs[0].replace(' ', '')] = strs[1].replace(' ', '')
nacos_data = properties
# 监听Nacos数据变动
def add_nacos_listener():
group = "DEFAULT_GROUP"
# 初始化
config_init(serverName, group)
client.add_config_watcher(data_id=serverName, group=group, cb=__nacos_data_change_callback)
def get_value(key,defValue=None):
'''获得一个全局变量,不存在则返回默认值'''
try:
value = nacos_data[key]
return value
except KeyError:
return defValue
针对拿到数据后如何处理,更新的逻辑,大家自行完善
8、完整代码
import configparser
import os
import socket
import time
import random
import threading
import requests
from nacos import NacosClient
#检测配置文件是否存在
if not os.path.isfile('app.conf'):
print("配置文件 app.conf 不存在,程序退出。")
input("按下任意键退出...")
exit()
try:
# 读取配置文件
config = configparser.ConfigParser()
config.read('app.conf')
# 从配置文件获取配置参数
serverAddr = config.get('Nacos', 'serverAddr')
namespace = config.get('Nacos', 'namespace')
serverName = config.get('Nacos', 'serverName')
username = config.get('Nacos', 'username')
password = config.get('Nacos', 'password')
gPort = config.get('Nacos', 'gPort')
except:
print("配置文件数据不正确,请检查配置文件!")
input("按下任意键退出...")
exit()
def get_ip():
hostname = socket.gethostname()
ip = socket.gethostbyname(hostname)
return ip
HostIP = get_ip()
HostPort = 8099
# 创建一个连接对象
client = NacosClient(server_addresses=serverAddr, namespace=namespace, username=username, password=password)
def __ref_nacos_listener():
metadata = {"gRPC.port": f'{gPort}'}
while True:
client.send_heartbeat(service_name=serverName, ip=HostIP, metadata=metadata, port=HostPort)
time.sleep(3)
def __register_server():
data = {"serviceName": serverName, "ip": HostIP, "port": HostPort}
client._inject_auth_info(data=data, headers=None, params={f'{gPort}'})
def __get_server_info(servername):
response = client.list_naming_instance(servername)
hosts = response["hosts"]
server_info = []
for host in hosts:
ip = host["ip"]
port = host["port"]
metadata = host["metadata"]
server_details = {
"ip": ip,
"port": port,
"metadata": metadata
}
server_info.append(server_details)
return server_info
def get_server(servername, path, params):
server_info = __get_server_info(servername)
s1 = random.choice(server_info)
url = f"http://{s1['ip']}:{s1['port']}/{path}"
response = requests.get(url, params)
if response.status_code == 200:
#data = response.json()
return response.text
else:
print("请求异常:", response.status_code)
return 999
def post_server(servername, path, json):
server_info = __get_server_info(servername)
s1 = random.choice(server_info)
url = f"http://{s1['ip']}:{s1['port']}/{path}"
# 参数里的 json 类似 以JSON 格式传递,data 以 form 表单的形式
response = requests.post(url, json=json)
# status_code 是个固定key
if response.status_code == 200:
data = response.text
return data
else:
print("请求异常:", response.status_code)
return 999
def register_init():
t = threading.Thread(target=__ref_nacos_listener)
t.start()
global nacos_data
nacos_data ={}
# 初始化
def config_init(data_id, group):
global nacos_data
config_list = client.get_config(data_id, group).split("\n")
properties = {}
for config_item in config_list:
# 过滤有用的键值对
if config_item.find('=') > 0:
strs = config_item.replace('\n', '').split('=')
properties[strs[0].replace(' ', '')] = strs[1].replace(' ', '')
nacos_data = properties
# result = config_data['arg1']['arg2']
# print(result)
# Nacos数据变动时触发
def __nacos_data_change_callback(config):
global nacos_data
# 数据解析,
config_list = config['content'].split("\n")
properties = {}
for config_item in config_list:
# 过滤有用部分
if config_item.find('=') > 0:
strs = config_item.replace('\n', '').split('=')
properties[strs[0].replace(' ', '')] = strs[1].replace(' ', '')
nacos_data = properties
# 监听Nacos数据变动
def add_nacos_listener():
group = "DEFAULT_GROUP"
# 初始化
config_init(serverName, group)
client.add_config_watcher(data_id=serverName, group=group, cb=__nacos_data_change_callback)
def get_value(key,defValue=None):
'''获得一个全局变量,不存在则返回默认值'''
try:
value = nacos_data[key]
return value
except KeyError:
return defValue
9、以Flask作为服务启动
from nacos_client import get_server,HostPort,config_init,get_value
from flask import Flask
app = Flask(__name__)
@app.route('/test/query/<int:a>', methods=['GET'])
def get_sum(a):
params = {
"index": a
}
# 通过服务名调用
aa = get_server("server3", "userInfo/post", params)
return aa
@app.route('/test/query', methods=['GET'])
def query():
aa = get_value('aa')
return aa
if __name__ == '__main__':
# 获取配置
config_init()
# 服务被发现
# nacos_init()
app.run(host='0.0.0.0', port=HostPort)
注意 如 nacos-sdk-python 项目介绍,作者最高只对 Python3.7 及 Nacos 1.3.2做了兼容 在实际测试过程中,发现程序在 Windows 使用正常,放到 Mac 或 Linux 就报错,即 TypeE