本地通知与健康数据的隐私保护方案
关键词:本地通知、健康数据、隐私保护、数据加密、访问控制、差分隐私、联邦学习
摘要:本文深入探讨了移动应用中本地通知与健康数据的隐私保护方案。我们将从技术原理、算法实现到实际应用场景,全面分析如何在保证功能完整性的同时确保用户数据安全。文章将介绍多种隐私保护技术,包括数据加密、访问控制、差分隐私和联邦学习等,并提供具体的代码实现和数学建模。最后,我们将讨论该领域的未来发展趋势和面临的挑战。
1. 背景介绍
1.1 目的和范围
随着移动健康(mHealth)应用的普及,本地通知与健康数据的结合为用户提供了更加个性化的健康管理体验。然而,这种便利性也带来了严峻的隐私保护挑战。本文旨在探讨如何在移动应用中实现本地通知功能的同时,确保用户健康数据的隐私安全。
本文的范围包括:
- 本地通知与健康数据结合的技术架构
- 隐私保护的核心技术方案
- 具体算法实现与数学模型
- 实际应用案例分析
1.2 预期读者
本文适合以下读者:
- 移动应用开发人员
- 健康科技产品经理
- 数据隐私与安全专家
- 医疗健康领域的技术决策者
- 对隐私保护技术感兴趣的研究人员
1.3 文档结构概述
本文首先介绍背景知识和核心概念,然后深入探讨隐私保护的技术方案,包括算法原理和数学模型。接着提供实际代码实现和应用场景分析,最后讨论未来发展趋势和挑战。
1.4 术语表
1.4.1 核心术语定义
- 本地通知(Local Notification):由移动应用在本地生成并显示的通知,无需服务器推送。
- 健康数据(Health Data):与用户健康状况相关的数据,包括生理指标、活动数据、医疗记录等。
- 隐私保护(Privacy Protection):保护个人数据不被未经授权访问或滥用的技术和策略。
- 数据加密(Data Encryption):将数据转换为密文以防止未经授权访问的过程。
- 访问控制(Access Control):限制谁可以访问特定数据或资源的机制。
1.4.2 相关概念解释
- 差分隐私(Differential Privacy):一种数学框架,用于在统计分析中保护个人隐私。
- 联邦学习(Federated Learning):一种分布式机器学习方法,数据保留在本地设备上,只共享模型更新。
- 同态加密(Homomorphic Encryption):允许在加密数据上直接进行计算的特殊加密方法。
1.4.3 缩略词列表
- mHealth: Mobile Health
- API: Application Programming Interface
- SDK: Software Development Kit
- HIPAA: Health Insurance Portability and Accountability Act
- GDPR: General Data Protection Regulation
2. 核心概念与联系
本地通知与健康数据的隐私保护涉及多个技术层面的整合。下图展示了核心概念之间的关系:
在这个架构中,健康数据从采集到最终生成通知,需要经过多个隐私保护环节。每个环节都需要考虑数据的最小化原则和隐私保护措施。
2.1 本地通知系统架构
现代移动平台的本地通知系统通常包含以下组件:
- 通知调度器:负责安排通知的触发时间和条件
- 内容生成器:根据健康数据生成通知内容
- 权限管理器:控制对健康数据的访问权限
- 隐私过滤器:在数据使用前进行匿名化或脱敏处理
2.2 健康数据类型与敏感度分级
健康数据可以根据敏感程度分为以下几类:
敏感级别 | 数据类型示例 | 隐私保护要求 |
---|---|---|
高敏感 | 疾病诊断、用药记录 | 强加密、严格访问控制 |
中敏感 | 心率、血压、步数 | 匿名化、差分隐私 |
低敏感 | 运动时长、卡路里消耗 | 基本访问控制 |
3. 核心算法原理 & 具体操作步骤
3.1 基于属性的访问控制(ABAC)算法
在健康数据隐私保护中,基于属性的访问控制(Attribute-Based Access Control)比传统角色控制更灵活。以下是Python实现示例:
from datetime import datetime
from enum import Enum
class HealthDataType(Enum):
HEART_RATE = 1
BLOOD_PRESSURE = 2
MEDICATION = 3
class UserRole(Enum):
PATIENT = 1
DOCTOR = 2
RESEARCHER = 3
class AccessPolicy:
def __init__(self):
self.policies = {
HealthDataType.HEART_RATE: {
'min_role': UserRole.PATIENT,
'time_restricted': False
},
HealthDataType.BLOOD_PRESSURE: {
'min_role': UserRole.DOCTOR,
'time_restricted': True,
'allowed_hours': (8, 20)
},
HealthDataType.MEDICATION: {
'min_role': UserRole.DOCTOR,
'time_restricted': True,
'allowed_hours': (9, 17)
}
}
def check_access(self, data_type, user_role, access_time=None):
policy = self.policies.get(data_type)
if not policy:
return False
if user_role.value < policy['min_role'].value:
return False
if policy['time_restricted']:
if not access_time:
access_time = datetime.now().hour
allowed_start, allowed_end = policy['allowed_hours']
if not (allowed_start <= access_time < allowed_end):
return False
return True
# 使用示例
policy = AccessPolicy()
print(policy.check_access(HealthDataType.BLOOD_PRESSURE, UserRole.DOCTOR, 10)) # True
print(policy.check_access(HealthDataType.MEDICATION, UserRole.RESEARCHER, 18)) # False
3.2 差分隐私实现算法
差分隐私可以在统计查询中保护个体隐私。以下是添加拉普拉斯噪声的Python实现:
import numpy as np
def laplace_mechanism(data, epsilon, sensitivity):
"""
拉普拉斯机制实现差分隐私
参数:
data: 原始数据
epsilon: 隐私预算(越小隐私保护越强)
sensitivity: 查询敏感度
返回:
满足差分隐私的结果
"""
scale = sensitivity / epsilon
noise = np.random.laplace(0, scale, len(data))
return data + noise
# 示例: 保护平均心率数据
heart_rates = np.array([72, 75, 68, 80, 77]) # 原始心率数据
epsilon = 0.5 # 隐私预算
sensitivity = 10 # 最大可能的心率变化
private_rates = laplace_mechanism(heart_rates, epsilon, sensitivity)
print(f"原始数据: {heart_rates}")
print(f"隐私保护后数据: {private_rates}")
print(f"原始平均值: {np.mean(heart_rates):.2f}")
print(f"隐私保护后平均值: {np.mean(private_rates):.2f}")
3.3 本地通知触发逻辑
结合健康数据的本地通知触发需要考虑隐私保护。以下是智能通知触发算法的Python伪代码:
class HealthNotificationSystem:
def __init__(self, privacy_level='medium'):
self.privacy_level = privacy_level
self.data_cache = {}
self.notification_history = []
def update_health_data(self, data_type, value):
"""更新健康数据并应用隐私保护"""
if self.privacy_level == 'high':
# 应用强隐私保护
processed_value = self._apply_differential_privacy(value)
elif self.privacy_level == 'medium':
# 应用中等隐私保护
processed_value = self._apply_generalization(value)
else:
# 基本隐私保护
processed_value = value
self.data_cache[data_type] = processed_value
self._check_notification_rules(data_type)
def _apply_differential_privacy(self, value):
"""应用差分隐私"""
epsilon = 0.3
sensitivity = 5
noise = np.random.laplace(0, sensitivity/epsilon)
return value + noise
def _apply_generalization(self, value):
"""应用泛化技术"""
# 将精确值转换为范围
if isinstance(value, (int, float)):
return round(value / 5) * 5 # 四舍五入到最近的5的倍数
return value
def _check_notification_rules(self, data_type):
"""检查是否满足通知触发条件"""
rules = self._get_rules_for_type(data_type)
current_value = self.data_cache.get(data_type)
if not current_value or not rules:
return
for rule in rules:
if rule['condition'](current_value):
self._trigger_notification(rule['message'])
def _get_rules_for_type(self, data_type):
"""获取特定数据类型的通知规则"""
# 实际应用中这些规则可以存储在配置文件中
if data_type == 'heart_rate':
return [
{
'condition': lambda x: x > 100,
'message': '您的心率偏高,建议休息'
},
{
'condition': lambda x: x < 50,
'message': '您的心率偏低,如有不适请咨询医生'
}
]
elif data_type == 'blood_pressure':
return [
{
'condition': lambda x: x[0] > 140 or x[1] > 90,
'message': '您的血压偏高,建议监测'
}
]
return []
def _trigger_notification(self, message):
"""触发本地通知"""
# 在实际应用中,这里会调用平台特定的通知API
print(f"[通知触发]: {message}")
self.notification_history.append({
'timestamp': datetime.now(),
'message': message
})
# 使用示例
system = HealthNotificationSystem(privacy_level='medium')
system.update_health_data('heart_rate', 102) # 会触发高心率通知
system.update_health_data('heart_rate', 45) # 会触发低心率通知
4. 数学模型和公式 & 详细讲解 & 举例说明
4.1 差分隐私的数学基础
差分隐私的核心数学概念是隐私预算(ε)和敏感度(Δf)。一个算法M满足ε-差分隐私,当且仅当对于所有相邻数据集D和D’(相差一个记录),以及所有输出S ⊆ Range(M):
P r [ M ( D ) ∈ S ] ≤ e ε × P r [ M ( D ′ ) ∈ S ] Pr[M(D) ∈ S] ≤ e^ε × Pr[M(D') ∈ S] Pr[M(D)∈S]≤eε×Pr[M(D′)∈S]
其中,拉普拉斯机制的噪声规模与敏感度和隐私预算的关系为:
s c a l e = Δ f ε scale = \frac{Δf}{ε} scale=εΔf
敏感度计算示例:
对于平均心率查询,假设最大可能的心率变化为20 bpm,数据集包含n条记录,则敏感度为:
Δ f = 20 n Δf = \frac{20}{n} Δf=n20
4.2 同态加密的数学原理
同态加密允许在加密数据上直接进行计算。部分同态加密(如Paillier)的加密和解密过程:
密钥生成:
- 选择两个大素数p和q,计算n = p×q
- 选择整数g满足g ∈ Z n 2 ∗ \mathbb{Z}_{n^2}^* Zn2∗
- 公钥为(n, g),私钥为(p, q)
加密过程:
对于明文m ∈
Z
n
\mathbb{Z}_n
Zn,随机选择r ∈
Z
n
∗
\mathbb{Z}_n^*
Zn∗:
c = g m ⋅ r n m o d n 2 c = g^m \cdot r^n \mod n^2 c=gm⋅rnmodn2
解密过程:
使用私钥(p, q)计算:
m = L ( c λ m o d n 2 ) L ( g λ m o d n 2 ) m o d n m = \frac{L(c^λ \mod n^2)}{L(g^λ \mod n^2)} \mod n m=L(gλmodn2)L(cλmodn2)modn
其中 λ = lcm ( p − 1 , q − 1 ) λ = \text{lcm}(p-1, q-1) λ=lcm(p−1,q−1), L ( x ) = x − 1 n L(x) = \frac{x-1}{n} L(x)=nx−1
4.3 联邦学习的聚合算法
联邦平均(Federated Averaging)算法的权重更新公式:
w g l o b a l t + 1 = ∑ k = 1 K n k N w k t w_{global}^{t+1} = \sum_{k=1}^K \frac{n_k}{N} w_k^t wglobalt+1=k=1∑KNnkwkt
其中:
- w g l o b a l t + 1 w_{global}^{t+1} wglobalt+1: 第t+1轮全局模型参数
- w k t w_k^t wkt: 第k个客户端在第t轮的模型参数
- n k n_k nk: 第k个客户端的数据量
- N N N: 所有客户端数据总量
- K K K: 参与本轮训练的客户端数量
5. 项目实战:代码实际案例和详细解释说明
5.1 开发环境搭建
5.1.1 Android平台实现
- 安装Android Studio和必要的SDK
- 配置Health Connect API权限
- 添加隐私保护库依赖:
dependencies {
implementation 'androidx.health:health-connect-client:1.0.0'
implementation 'com.google.crypto.tink:tink-android:1.7.0'
implementation 'org.tensorflow:tensorflow-lite:2.10.0'
}
5.1.2 iOS平台实现
- 安装Xcode和Swift开发环境
- 配置HealthKit权限
- 添加隐私保护库:
// Package.swift
dependencies: [
.package(url: "https://github.com/keefertaylor/LaplacianSwift", from: "1.0.0"),
.package(url: "https://github.com/krzyzanowskim/CryptoSwift", from: "1.5.1")
]
5.2 源代码详细实现和代码解读
5.2.1 Android健康数据加密模块
// HealthDataEncryptor.kt
class HealthDataEncryptor(context: Context) {
private val keysetHandle: KeysetHandle
init {
// 初始化Tink加密库
TinkConfig.register()
keysetHandle = KeysetHandle.generateNew(KeyTemplates.get("AES256_GCM"))
}
fun encryptHealthData(data: HealthData): ByteArray {
val primitive = keysetHandle.getPrimitive(Aead::class.java)
val jsonData = Gson().toJson(data).toByteArray(Charsets.UTF_8)
return primitive.encrypt(jsonData, null)
}
fun decryptHealthData(encryptedData: ByteArray): HealthData {
val primitive = keysetHandle.getPrimitive(Aead::class.java)
val decrypted = primitive.decrypt(encryptedData, null)
return Gson().fromJson(String(decrypted, Charsets.UTF_8), HealthData::class.java)
}
fun applyDifferentialPrivacy(values: List<Double>, epsilon: Double): List<Double> {
val sensitivity = calculateSensitivity(values)
return values.map { value ->
value + laplaceNoise(sensitivity, epsilon)
}
}
private fun calculateSensitivity(values: List<Double>): Double {
// 基于数据范围和查询类型计算敏感度
return if (values.isEmpty()) 0.0 else (values.maxOrNull()!! - values.minOrNull()!!) / values.size
}
private fun laplaceNoise(sensitivity: Double, epsilon: Double): Double {
val random = SecureRandom()
val scale = sensitivity / epsilon
val u = random.nextDouble() - 0.5
return -scale * signum(u) * ln(1 - 2 * abs(u))
}
}
5.2.2 iOS本地通知与隐私保护集成
// HealthNotificationManager.swift
import HealthKit
import UserNotifications
import LaplacianSwift
class HealthNotificationManager: NSObject {
private let healthStore = HKHealthStore()
private let notificationCenter = UNUserNotificationCenter.current()
private var privacyLevel: PrivacyLevel = .medium
enum PrivacyLevel {
case low, medium, high
}
override init() {
super.init()
notificationCenter.delegate = self
}
func requestAuthorization(completion: @escaping (Bool) -> Void) {
let typesToRead: Set<HKObjectType> = [
HKObjectType.quantityType(forIdentifier: .heartRate)!,
HKObjectType.quantityType(forIdentifier: .bloodPressureSystolic)!,
HKObjectType.quantityType(forIdentifier: .bloodPressureDiastolic)!
]
healthStore.requestAuthorization(toShare: nil, read: typesToRead) { success, error in
if !success {
completion(false)
return
}
self.notificationCenter.requestAuthorization(options: [.alert, .sound]) { granted, _ in
completion(granted)
}
}
}
func startMonitoringHealthData() {
let heartRateType = HKObjectType.quantityType(forIdentifier: .heartRate)!
let query = HKObserverQuery(sampleType: heartRateType, predicate: nil) { [weak self] query, completion, error in
self?.checkHeartRateForNotifications()
completion()
}
healthStore.execute(query)
}
private func checkHeartRateForNotifications() {
let heartRateType = HKQuantityType.quantityType(forIdentifier: .heartRate)!
let now = Date()
let oneHourAgo = Calendar.current.date(byAdding: .hour, value: -1, to: now)!
let predicate = HKQuery.predicateForSamples(withStart: oneHourAgo, end: now, options: .strictStartDate)
let query = HKSampleQuery(sampleType: heartRateType, predicate: predicate, limit: HKObjectQueryNoLimit, sortDescriptors: nil) { [weak self] _, samples, _ in
guard let self = self, let samples = samples as? [HKQuantitySample] else { return }
let values = samples.map { $0.quantity.doubleValue(for: HKUnit(from: "count/min")) }
let processedValues = self.applyPrivacyProtection(values: values)
let average = processedValues.reduce(0, +) / Double(processedValues.count)
if average > 100 {
self.sendNotification(title: "心率提醒", body: "您的心率偏高,建议休息")
} else if average < 50 {
self.sendNotification(title: "心率提醒", body: "您的心率偏低,如有不适请咨询医生")
}
}
healthStore.execute(query)
}
private func applyPrivacyProtection(values: [Double]) -> [Double] {
switch privacyLevel {
case .high:
let epsilon = 0.5
let sensitivity = 10.0
return values.map { $0 + LaplacianNoise.generate(epsilon: epsilon, sensitivity: sensitivity) }
case .medium:
return values.map { round($0 / 5) * 5 } // 泛化为5的倍数
case .low:
return values
}
}
private func sendNotification(title: String, body: String) {
let content = UNMutableNotificationContent()
content.title = title
content.body = body
content.sound = .default
let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: nil)
notificationCenter.add(request)
}
}
extension HealthNotificationManager: UNUserNotificationCenterDelegate {
func userNotificationCenter(_ center: UNUserNotificationCenter,
willPresent notification: UNNotification,
withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
completionHandler([.banner, .sound])
}
}
5.3 代码解读与分析
上述代码展示了两个平台上的实现:
-
Android部分:
- 使用Google的Tink加密库实现健康数据的加密存储
- 实现了差分隐私保护的核心算法
- 采用AES-256-GCM加密算法,提供数据机密性和完整性保护
- 拉普拉斯噪声生成考虑了安全随机数生成
-
iOS部分:
- 集成HealthKit框架访问健康数据
- 使用UserNotifications框架实现本地通知
- 实现了三种隐私保护级别
- 采用观察者模式实时监测健康数据变化
关键设计决策:
- 分层隐私保护:根据数据敏感度提供不同级别的保护
- 最小权限原则:只请求必要的健康数据类型
- 数据最小化:只收集通知功能必需的健康数据
- 本地处理:所有隐私保护操作在设备本地完成
6. 实际应用场景
6.1 慢性病管理应用
对于糖尿病患者,应用可以:
- 本地分析血糖数据趋势
- 在血糖异常时触发通知提醒
- 使用差分隐私保护上传聚合数据用于研究
- 采用联邦学习改进预测模型而不共享原始数据
6.2 心理健康监测
通过分析用户的活动模式、睡眠质量和心率变异性:
- 检测可能的压力或焦虑状态
- 提供适时的正念练习建议
- 所有敏感数据加密存储在本地
- 仅分享匿名化统计信息
6.3 老年人健康监护
为独居老人设计:
- 监测日常活动模式和生命体征
- 异常情况通知紧急联系人
- 采用同态加密技术允许云端计算而不暴露原始数据
- 多因素认证保护数据访问
7. 工具和资源推荐
7.1 学习资源推荐
7.1.1 书籍推荐
- “The Algorithmic Foundations of Differential Privacy” - Cynthia Dwork, Aaron Roth
- “Privacy-Preserving Machine Learning” - J. Morris Chang等
- “Applied Cryptography” - Bruce Schneier
7.1.2 在线课程
- Coursera: “Privacy in the Digital Age” - University of Michigan
- edX: “Data Privacy and Security” - MIT
- Udacity: “Secure and Private AI” - Facebook AI
7.1.3 技术博客和网站
- Google AI Blog - 联邦学习研究
- Apple Machine Learning Journal - 设备端隐私保护
- IAPP (International Association of Privacy Professionals)
7.2 开发工具框架推荐
7.2.1 IDE和编辑器
- Android Studio - 集成Health Connect API支持
- Xcode - 内置HealthKit开发工具
- VS Code - 丰富的隐私保护扩展
7.2.2 调试和性能分析工具
- Android Profiler - 分析加密操作性能
- Instruments (iOS) - 监测健康数据访问
- Wireshark - 检查网络传输安全性
7.2.3 相关框架和库
- TensorFlow Privacy - 差分隐私机器学习
- PySyft - 联邦学习框架
- OpenMined - 隐私保护AI工具集
7.3 相关论文著作推荐
7.3.1 经典论文
- “Calibrating Noise to Sensitivity in Private Data Analysis” - Dwork等(2006)
- “Federated Learning: Challenges, Methods, and Future Directions” - Qiang Yang等(2019)
- “A Practical Guide to Implementing Federated Learning” - Kairouz等(2021)
7.3.2 最新研究成果
- “Differentially Private Health Tokens for Estimating COVID-19 Exposure” - NSDI 2022
- “Privacy-Preserving Federated Learning for Healthcare” - Nature Digital Medicine 2023
- “On-Device Personalization with Federated Learning” - Google AI 2023
7.3.3 应用案例分析
- Apple Heart Study - 大规模隐私保护健康研究
- Google Health Studies - 用户控制的数据共享平台
- Mayo Clinic’s Federated Learning Implementation
8. 总结:未来发展趋势与挑战
8.1 发展趋势
- 增强型设备端处理:随着移动设备算力提升,更多隐私保护算法将在本地运行
- 标准化隐私框架:行业将趋向统一的隐私保护标准和API
- 跨平台数据协作:安全多方计算等技术将实现跨机构数据协作而不共享原始数据
- 自适应隐私保护:基于上下文自动调整隐私保护级别
8.2 技术挑战
- 性能与隐私的平衡:强隐私保护往往带来计算开销
- 个性化与泛化的矛盾:如何在保护隐私的同时保持数据实用性
- 长期数据安全:量子计算对现有加密算法的潜在威胁
- 用户体验优化:简化复杂隐私设置的同时不牺牲安全性
8.3 法规与伦理考量
- 全球合规复杂性:满足GDPR、HIPAA等不同地区法规要求
- 知情同意的实现:让用户真正理解数据使用方式
- 算法透明度:在保护隐私的同时提供足够的算法可解释性
- 数据主权:用户对自身健康数据的控制权界定
9. 附录:常见问题与解答
Q1: 本地通知真的比服务器推送更安全吗?
A1: 本地通知在隐私保护方面确实具有优势:
- 不需要将敏感数据发送到服务器
- 触发逻辑完全在设备端执行
- 减少了网络传输环节的安全风险
- 用户对通知触发有完全的控制权
但需要注意设备本地的安全防护,如加密存储和访问控制。
Q2: 差分隐私会如何影响健康数据的准确性?
A2: 差分隐私确实会引入噪声,但通过合理配置可以达到平衡:
- 对于个体数据,噪声影响较大
- 对于统计量(如平均值),随着数据量增加,噪声影响减小
- 可以通过调整隐私预算(ε)控制噪声大小
- 在临床决策等关键场景,可以使用较小的ε值或原始数据(经用户明确授权)
Q3: 如何选择适合的隐私保护技术?
A3: 选择隐私保护技术应考虑以下因素:
- 数据类型和敏感度
- 使用场景(分析、共享、存储等)
- 性能要求和设备能力
- 合规要求
- 用户隐私偏好
一般建议采用分层保护策略,对不同敏感度数据应用不同技术。
Q4: 联邦学习真的能保护隐私吗?
A4: 联邦学习是隐私保护的重大进步,但仍需注意:
- 基础联邦学习只共享模型参数,不共享原始数据
- 仍可能通过模型参数推断原始数据(需结合差分隐私)
- 需要防范成员推断等攻击
- 实际部署需要考虑安全聚合等增强技术
Q5: 如何处理用户撤销同意后的数据?
A5: 用户撤销同意后应:
- 立即停止收集新数据
- 根据用户选择删除或匿名化已有数据
- 从分析模型中移除该用户贡献(对于联邦学习)
- 确保备份和日志中的相关数据也被处理
- 提供可验证的删除证明
10. 扩展阅读 & 参考资料
-
官方文档:
- Android Health Connect API文档
- Apple HealthKit开发指南
- Google Privacy-preserving技术文档
-
行业标准:
- ISO/IEC 27701:2019 (隐私信息管理体系)
- NIST Privacy Framework
- FHIR (Fast Healthcare Interoperability Resources)
-
开源项目:
- TensorFlow Federated (Google)
- FATE (Federated AI Technology Enabler)
- OpenDP (哈佛大学差分隐私项目)
-
研究数据集:
- MIMIC-III (MIT的匿名医疗数据集)
- UK Biobank (英国生物银行数据)
- Apple ResearchKit研究数据
-
社区资源:
- Privacy Tech Alliance
- International Society for Computational Biology (ISCB)
- Digital Health & Wellness Community
通过本文的全面探讨,我们深入了解了本地通知与健康数据隐私保护的技术方案、实现方法和未来方向。随着技术的不断发展和法规的完善,隐私保护将成为健康科技产品的核心竞争力而非制约因素。开发者需要在产品设计之初就将隐私保护纳入核心架构,才能在赢得用户信任的同时提供有价值的健康服务。