本文目录导读:

我来详细介绍如何实现服务发现脚本,包括几种常见的方法和实现方案。
基于DNS的服务发现
Python实现示例
#!/usr/bin/env python3
import socket
import dns.resolver
import json
from typing import Dict, List, Optional
class DNSDiscovery:
"""基于DNS的服务发现"""
def __init__(self, domain: str):
self.domain = domain
self.resolver = dns.resolver.Resolver()
def discover_services(self, service_type: str = "_http") -> List[str]:
"""发现服务实例"""
try:
# SRV记录查询
srv_record = f"{service_type}._tcp.{self.domain}"
answers = self.resolver.resolve(srv_record, 'SRV')
services = []
for rdata in answers:
# TXT记录查询(获取元数据)
txt_records = self.get_txt_records(rdata.target.to_text())
services.append({
'host': str(rdata.target).rstrip('.'),
'port': rdata.port,
'priority': rdata.priority,
'weight': rdata.weight,
'metadata': txt_records
})
return services
except Exception as e:
print(f"服务发现失败: {e}")
return []
def get_txt_records(self, hostname: str) -> Dict:
"""获取TXT记录"""
try:
answers = self.resolver.resolve(hostname, 'TXT')
metadata = {}
for rdata in answers:
for txt_string in rdata.strings:
if '=' in txt_string.decode():
key, value = txt_string.decode().split('=', 1)
metadata[key] = value
return metadata
except:
return {}
# 使用示例
discoverer = DNSDiscovery("example.com")
services = discoverer.discover_services("_http")
print(json.dumps(services, indent=2))
基于Consul的服务发现
#!/usr/bin/env python3
import requests
import json
import os
from typing import Dict, List, Optional
class ConsulDiscovery:
"""基于Consul的服务发现"""
def __init__(self, consul_host: str = "localhost", consul_port: int = 8500):
self.consul_url = f"http://{consul_host}:{consul_port}"
def register_service(self,
service_name: str,
service_id: str,
address: str,
port: int,
tags: List[str] = None,
check: Dict = None) -> bool:
"""注册服务"""
service = {
"ID": service_id,
"Name": service_name,
"Address": address,
"Port": port,
"Tags": tags or [],
"Check": check or {
"TCP": f"{address}:{port}",
"Interval": "10s",
"Timeout": "5s"
}
}
try:
response = requests.put(
f"{self.consul_url}/v1/agent/service/register",
json=service
)
return response.status_code == 200
except Exception as e:
print(f"服务注册失败: {e}")
return False
def discover_service(self, service_name: str, healthy_only: bool = True) -> List[Dict]:
"""发现服务实例"""
try:
url = f"{self.consul_url}/v1/health/service/{service_name}"
if healthy_only:
url += "?passing"
response = requests.get(url)
if response.status_code != 200:
return []
services = []
data = response.json()
for service_info in data:
service = service_info.get('Service', {})
services.append({
'id': service.get('ID'),
'name': service.get('Service'),
'address': service.get('Address'),
'port': service.get('Port'),
'tags': service.get('Tags', []),
'node': service_info.get('Node', {}).get('Node'),
'health_status': self._get_health_status(service_info)
})
return services
except Exception as e:
print(f"服务发现失败: {e}")
return []
def _get_health_status(self, service_info: Dict) -> str:
"""获取健康状态"""
checks = service_info.get('Checks', [])
for check in checks:
if check.get('CheckID') != 'serfHealth':
if check.get('Status') != 'passing':
return check.get('Status', 'unknown')
return 'passing'
def deregister_service(self, service_id: str) -> bool:
"""注销服务"""
try:
response = requests.put(
f"{self.consul_url}/v1/agent/service/deregister/{service_id}"
)
return response.status_code == 200
except:
return False
# 使用示例
consul = ConsulDiscovery()
consul.register_service(
"web-app",
"web-app-1",
"192.168.1.100",
8080,
tags=["production", "v1.0"]
)
services = consul.discover_service("web-app")
print(json.dumps(services, indent=2))
基于Eureka的服务发现
#!/usr/bin/env python3
import requests
import json
from typing import Dict, List, Optional
class EurekaDiscovery:
"""基于Eureka的服务发现"""
def __init__(self, eureka_url: str = "http://localhost:8761/eureka"):
self.eureka_url = eureka_url.rstrip('/')
self.headers = {
'Content-Type': 'application/json',
'Accept': 'application/json'
}
def register_service(self,
app_name: str,
instance_id: str,
hostname: str,
ip_addr: str,
port: int,
vip_address: str = None,
secure_vip_address: str = None) -> bool:
"""注册服务实例"""
instance = {
"instance": {
"instanceId": instance_id,
"hostName": hostname,
"app": app_name.upper(),
"ipAddr": ip_addr,
"status": "UP",
"port": {
"$": port,
"@enabled": "true"
},
"vipAddress": vip_address or hostname,
"secureVipAddress": secure_vip_address or hostname,
"dataCenterInfo": {
"@class": "com.netflix.appinfo.InstanceInfo$DefaultDataCenterInfo",
"name": "MyOwn"
}
}
}
try:
url = f"{self.eureka_url}/apps/{app_name.upper()}"
response = requests.post(
url,
json=instance,
headers=self.headers
)
return response.status_code == 204
except Exception as e:
print(f"服务注册失败: {e}")
return False
def discover_service(self, app_name: str) -> List[Dict]:
"""发现服务实例"""
try:
url = f"{self.eureka_url}/apps/{app_name.upper()}"
response = requests.get(url, headers=self.headers)
if response.status_code != 200:
return []
data = response.json()
apps = data.get('application', {})
instances = apps.get('instance', [])
if not isinstance(instances, list):
instances = [instances]
services = []
for instance in instances:
services.append({
'instance_id': instance.get('instanceId'),
'hostname': instance.get('hostName'),
'ip': instance.get('ipAddr'),
'port': instance.get('port', {}).get('$'),
'status': instance.get('status'),
'app': instance.get('app')
})
return services
except Exception as e:
print(f"服务发现失败: {e}")
return []
def send_heartbeat(self, app_name: str, instance_id: str) -> bool:
"""发送心跳"""
try:
url = f"{self.eureka_url}/apps/{app_name.upper()}/{instance_id}"
response = requests.put(url, headers=self.headers)
return response.status_code == 200
except:
return False
# 使用示例
eureka = EurekaDiscovery()
eureka.register_service(
"user-service",
"user-service-1",
"node1.example.com",
"192.168.1.101",
8081
)
services = eureka.discover_service("user-service")
print(json.dumps(services, indent=2))
基于etcd的服务发现
#!/usr/bin/env python3
import etcd3
import json
import time
from typing import Dict, List, Optional
class EtcdDiscovery:
"""基于etcd的服务发现"""
def __init__(self, host: str = "localhost", port: int = 2379):
self.client = etcd3.client(host=host, port=port)
self.base_path = "/services"
def register_service(self,
name: str,
instance_id: str,
address: str,
port: int,
metadata: Dict = None,
ttl: int = 60) -> bool:
"""注册服务实例"""
service_path = f"{self.base_path}/{name}/{instance_id}"
service_info = {
"name": name,
"id": instance_id,
"address": address,
"port": port,
"metadata": metadata or {},
"timestamp": time.time()
}
try:
# 设置带TTL的key
self.client.put(
service_path,
json.dumps(service_info).encode(),
lease=self.client.lease(ttl)
)
return True
except Exception as e:
print(f"服务注册失败: {e}")
return False
def discover_service(self, name: str) -> List[Dict]:
"""发现服务实例"""
service_path = f"{self.base_path}/{name}/"
try:
instances = []
for item in self.client.get_prefix(service_path):
key, value = item
service_info = json.loads(value.decode())
instances.append(service_info)
return instances
except Exception as e:
print(f"服务发现失败: {e}")
return []
def watch_service_changes(self, name: str, callback):
"""监听服务变化"""
service_path = f"{self.base_path}/{name}/"
events_iterator, cancel = self.client.watch_prefix(service_path)
for event in events_iterator:
if event.key:
service_info = json.loads(event.value.decode())
callback(event.key.decode(), event.type, service_info)
def deregister_service(self, name: str, instance_id: str) -> bool:
"""注销服务实例"""
service_path = f"{self.base_path}/{name}/{instance_id}"
try:
self.client.delete(service_path)
return True
except:
return False
def get_all_services(self) -> Dict[str, List[Dict]]:
"""获取所有服务"""
try:
services = {}
for item in self.client.get_prefix(self.base_path):
key, value = item
key_str = key.decode()
service_name = key_str.split('/')[2]
if service_name not in services:
services[service_name] = []
services[service_name].append(json.loads(value.decode()))
return services
except Exception as e:
print(f"获取服务列表失败: {e}")
return {}
# 使用示例
etcd = EtcdDiscovery()
etcd.register_service(
"api-gateway",
"gateway-1",
"192.168.1.200",
3000,
metadata={"version": "1.0", "environment": "production"}
)
services = etcd.discover_service("api-gateway")
print(json.dumps(services, indent=2))
Shell脚本实现(简单版)
#!/bin/bash
# service_discovery.sh - 简单的服务发现脚本
# 服务注册
register_service() {
local service_name=$1
local service_host=$2
local service_port=$3
local service_id="${service_name}-${service_host}:${service_port}"
# 简单文件存储
echo "${service_host}:${service_port}" > "/tmp/services/${service_name}/${service_id}"
echo "服务 ${service_id} 注册成功"
}
# 服务发现
discover_service() {
local service_name=$1
echo "发现服务: ${service_name}"
if [ -d "/tmp/services/${service_name}" ]; then
for instance in /tmp/services/${service_name}/*; do
if [ -f "$instance" ]; then
cat "$instance"
fi
done
else
echo "未找到服务: ${service_name}"
fi
}
# 健康检查
health_check() {
local host=$1
local port=$2
if timeout 2 bash -c "echo > /dev/tcp/${host}/${port}" 2>/dev/null; then
return 0
else
return 1
fi
}
# 主函数
main() {
case "$1" in
register)
register_service "$2" "$3" "$4"
;;
discover)
discover_service "$2"
;;
health)
health_check "$2" "$3"
;;
*)
echo "用法: $0 {register|discover|health} [参数...]"
exit 1
;;
esac
}
main "$@"
使用建议
-
选择合适的方案:
- DNS方案:适合简单场景
- Consul/Eureka:适合微服务架构
- etcd:适合需要强一致性的场景
- Shell脚本:适合快速原型测试
-
配置健康检查:
- 定期检查服务健康状态
- 自动移除不健康的实例
-
负载均衡:
- 客户端负载均衡(如Ribbon)
- 服务端负载均衡(如Nginx)
-
缓存机制:
- 本地缓存服务列表
- 定期刷新缓存
-
容错处理:
- 熔断机制
- 重试策略
- 降级方案
这些脚本可以根据具体需求进行修改和扩展,实现更适合自己业务场景的服务发现机制。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播