




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
数据分析工具:ApacheDruid:Druid故障排查与性能监控1数据分析工具:ApacheDruid:Druid基础知识1.1Druid架构概览ApacheDruid是一个用于实时数据查询和分析的开源列式存储数据库。它被设计用于处理大规模的数据集,尤其擅长于实时数据流的处理和历史数据的查询。Druid的核心架构由以下几个关键组件构成:数据摄取(Ingestion):数据可以通过多种方式摄取到Druid中,包括批量导入和实时流处理。查询处理(QueryProcessing):Druid支持低延迟的查询处理,能够快速响应用户的查询请求。数据存储(DataStorage):数据以列式存储格式存储,优化了查询性能。数据分片(DataSharding):数据被分片存储在多个节点上,以实现水平扩展和高可用性。1.1.1Druid架构的关键特性实时性:Druid能够实时处理数据流,将数据快速索引并提供查询。可扩展性:通过数据分片和分布式架构,Druid可以轻松扩展以处理更大规模的数据。查询性能:Druid的列式存储和索引机制使其在查询性能上表现优异,尤其适合OLAP(在线分析处理)场景。1.2Druid组件介绍Druid的架构由多个组件组成,每个组件都有其特定的功能和职责:1.2.1数据摄取组件HistoricalServer功能:负责批量导入历史数据,并参与查询处理。交互:HistoricalServer与Coordinator和MiddleManager组件交互,接收数据导入任务和查询请求。Indexer功能:用于执行数据摄取任务,可以是实时或批量的。交互:Indexer接收来自Coordinator的指令,处理数据并将其导入HistoricalServer或Broker。Real-timeServer功能:处理实时数据流,将数据快速索引并提供查询。交互:Real-timeServer与Coordinator和Indexer组件交互,接收实时数据流和查询请求。1.2.2查询处理组件Broker功能:作为查询代理,接收用户的查询请求,优化查询并分发到HistoricalServer和Real-timeServer。交互:Broker与HistoricalServer和Real-timeServer交互,收集查询结果并返回给用户。QueryEngine功能:执行具体的查询逻辑,包括数据扫描、过滤和聚合。交互:QueryEngine与HistoricalServer和Real-timeServer交互,执行查询并返回结果。1.2.3管理组件Coordinator功能:管理数据摄取任务,确保数据在集群中的分布和负载均衡。交互:Coordinator与HistoricalServer和Real-timeServer交互,分配数据摄取任务和监控数据分布。Overlord功能:协调数据摄取任务,包括实时和批量任务的调度。交互:Overlord与Coordinator和Indexer交互,接收任务指令并执行数据摄取。MiddleManager功能:协助HistoricalServer和Real-timeServer进行数据摄取和查询处理。交互:MiddleManager与HistoricalServer和Real-timeServer交互,参与数据的导入和查询处理。1.2.4监控与故障排查组件Monitor功能:监控Druid集群的健康状态,包括节点状态和查询性能。交互:Monitor与所有Druid组件交互,收集监控数据并提供故障排查信息。故障排查工具功能:提供工具和接口,帮助管理员诊断和解决Druid集群中的问题。交互:故障排查工具与Monitor和Druid组件交互,分析监控数据并提供故障排查建议。1.2.5示例:Druid数据摄取#示例代码:使用Druid进行数据摄取
importrequests
importjson
#DruidOverlord的URL
overlord_url="http://localhost:8081/druid/indexer/v1/task"
#定义数据摄取任务
task={
"type":"index",
"spec":{
"dataSchema":{
"dataSource":"example_data_source",
"parser":{
"type":"string",
"parseSpec":{
"format":"json",
"timestampSpec":{
"column":"timestamp",
"format":"iso"
},
"dimensionsSpec":{
"dimensions":["dimension1","dimension2"],
"spatialDimensions":[]
},
"metricsSpec":[
{
"type":"count",
"name":"count"
}
],
"granularitySpec":{
"type":"uniform",
"segmentGranularity":"HOUR",
"queryGranularity":"MINUTE",
"rollup":True
}
}
},
"ioConfig":{
"type":"index",
"firehose":{
"type":"local",
"baseDir":"/path/to/data",
"filter":"example_data.json"
},
"appendToExisting":False
},
"tuningConfig":{
"type":"index",
"maxRowsInMemory":100000,
"maxRowsPerSegment":5000000,
"maxRowsInRollup":1000000
}
}
}
}
#发送POST请求以启动数据摄取任务
response=requests.post(overlord_url,data=json.dumps(task),headers={"Content-Type":"application/json"})
#检查响应状态
ifresponse.status_code==200:
print("数据摄取任务已成功启动")
else:
print("数据摄取任务启动失败,状态码:",response.status_code)1.2.6解释上述代码示例展示了如何使用Python向Druid的Overlord组件发送一个数据摄取任务。数据源被定义为example_data_source,数据格式为JSON,时间戳字段为timestamp,并定义了两个维度dimension1和dimension2以及一个计数指标count。数据摄取任务从本地文件系统读取数据,文件路径为/path/to/data,文件名为example_data.json。通过调整maxRowsInMemory、maxRowsPerSegment和maxRowsInRollup参数,可以优化数据摄取的性能和内存使用。通过这个示例,我们可以看到Druid数据摄取的基本流程和配置选项,这对于理解和操作Druid集群至关重要。2数据分析工具:ApacheDruid故障排查与性能监控2.1故障排查2.1.1日志分析技巧在ApacheDruid中,日志文件是诊断问题的第一手资料。Druid的每个组件(如Historical、MiddleManager、Broker、Coordinator、Overlord等)都会生成日志,这些日志包含了系统运行时的详细信息,包括但不限于查询执行、数据摄取、系统状态和错误信息。查看日志要查看Druid的组件日志,可以使用以下命令:#查看Historical节点日志
tail-f/var/log/druid/historical.log
#查看Coordinator节点日志
tail-f/var/log/druid/coordinator.log日志级别Druid支持不同的日志级别,包括DEBUG、INFO、WARN、ERROR和FATAL。在排查问题时,可能需要调整日志级别以获取更详细的系统信息。#将Historical节点的日志级别调整为DEBUG
curl-XPUThttp://localhost:8081/druid/node/v1/logLevel-H"Content-Type:application/json"-d'{"component":"historical","level":"DEBUG"}'日志分析查询失败分析:当查询失败时,检查Broker和Historical节点的日志,寻找与查询相关的错误信息。数据摄取问题:MiddleManager和Overlord的日志可以帮助诊断数据摄取过程中的问题,如数据格式错误、数据源不可达等。系统状态监控:Coordinator的日志可以提供关于数据段分配、任务调度等系统状态的信息。2.1.2常见错误代码解读ApacheDruid在运行过程中可能会遇到各种错误,这些错误通常会伴随着错误代码。理解这些错误代码对于快速定位问题至关重要。错误代码示例400BadRequest:这通常意味着客户端发送的请求有误,如查询参数不正确。500InternalServerError:服务器端错误,可能是因为数据段加载失败、查询执行错误等。503ServiceUnavailable:服务不可用,可能是因为节点重启、网络问题或资源不足。解读与处理400BadRequest:检查查询语句,确保所有参数正确无误。例如,如果使用SQL查询,确保SQL语法正确。500InternalServerError:查看Historical或MiddleManager的日志,寻找具体的错误信息。例如,如果数据段加载失败,可能是因为数据格式不匹配。503ServiceUnavailable:检查节点状态,确保所有节点正常运行。使用Druid的监控工具,如Grafana,来查看节点的健康状态和资源使用情况。2.1.3网络与配置问题排查网络问题和配置错误是ApacheDruid运行中常见的故障来源。确保网络通畅和配置正确是维护系统稳定性的关键。网络问题节点间通信失败:检查网络连接,确保所有Druid节点可以互相通信。使用ping或telnet命令测试节点间的网络连通性。外部数据源不可达:如果Druid需要从外部数据源摄取数据,确保这些数据源的网络连接正常。配置问题数据摄取配置错误:检查overlord和middleManager的配置文件,确保数据摄取的路径、格式和时间间隔正确。查询配置错误:Broker和Historical节点的配置文件中,查询的超时时间、并发度等参数需要根据实际需求进行调整。2.2性能监控ApacheDruid提供了多种工具和接口来监控系统的性能,包括JMX、Prometheus和Grafana。2.2.1JMX监控JMX(JavaManagementExtensions)是Java平台的标准管理接口,可以用来监控和管理运行在JVM上的应用。Druid的每个组件都支持JMX监控。JMX示例使用jconsole或VisualVM等工具连接到Druid节点,查看JVM的内存使用、线程状态和垃圾回收情况。#使用jconsole连接到Historical节点
jconsolelocalhost:71992.2.2Prometheus监控Prometheus是一个开源的监控系统和时间序列数据库,可以与Druid集成,提供详细的性能指标。Prometheus配置在Druid的配置文件中,启用Prometheus监控接口:{
"druid":{
"metrics":{
"prometheus":{
"enabled":true,
"port":8080
}
}
}
}Prometheus指标Prometheus会收集Druid的查询时间、数据段大小、节点状态等指标,这些指标可以用来分析系统的性能瓶颈。2.2.3Grafana可视化Grafana是一个开源的度量分析和可视化套件,可以与Prometheus集成,提供Druid性能的实时可视化。Grafana配置在Grafana中添加Prometheus数据源,然后创建仪表板来展示Druid的性能指标。Grafana示例创建一个仪表板,展示Historical节点的查询时间分布:{
"title":"HistoricalQueryTime",
"targets":[
{
"expr":"druid_historical_query_time",
"refId":"A"
}
]
}通过上述方法,可以有效地排查ApacheDruid的故障,并监控其性能,确保系统的稳定运行。3数据分析工具:ApacheDruid:性能监控3.1Druid监控工具使用在ApacheDruid中,监控工具是确保系统稳定性和优化性能的关键。Druid提供了多种监控工具,包括但不限于:DruidConsole:Druid的Web界面,用于查看集群状态、查询性能、数据摄入情况等。Prometheus:一个开源的系统监控和警报工具,可以与Druid集成,提供详细的性能指标。Grafana:与Prometheus配合使用,提供数据可视化,帮助用户理解Druid的性能趋势。3.1.1DruidConsoleDruidConsole是Druid自带的监控工具,通过Web界面展示集群的健康状态和性能指标。要访问DruidConsole,通常需要在Druid的配置中开启HTTP服务,并通过浏览器访问相应的URL。示例配置#在Druid的配置文件中,例如overlord的配置文件,开启HTTP服务
druid.overlord.http.service.enabled=true
druid.overlord.http.service.port=809查看集群状态在DruidConsole中,可以查看到集群的总体状态,包括:Broker节点:处理查询的节点。Historical节点:存储历史数据的节点。MiddleManager节点:负责数据摄入和实时查询的节点。Coordinator节点:管理数据段的分配和负载均衡。Overlord节点:管理数据摄入任务。3.1.2Prometheus和GrafanaDruid可以与Prometheus和Grafana集成,提供更详细的性能监控和可视化。首先,需要在Druid的配置中开启Prometheus的监控端点。示例配置#在Druid的配置文件中,例如broker的配置文件,开启Prometheus监控端点
metheus.enabled=true
metheus.port=9100然后,使用Grafana连接Prometheus,创建仪表板来监控Druid的性能指标,如查询延迟、吞吐量、CPU和内存使用情况等。3.2性能指标解读Druid的性能指标对于理解系统的健康状况和优化查询性能至关重要。以下是一些关键的性能指标:QueryLatency:查询延迟,即从接收查询到返回结果的时间。QueryThroughput:查询吞吐量,单位时间内处理的查询数量。SegmentLoadTime:数据段加载时间,数据段从存储加载到内存的时间。CPUUsage:CPU使用率,表示CPU的繁忙程度。MemoryUsage:内存使用情况,包括堆内存和非堆内存的使用。3.2.1示例:查询延迟监控在Prometheus中,可以使用以下查询来监控Druid的查询延迟:#查询延迟监控
druid_query_duration_seconds{quantile="0.99"}此查询返回99%的查询延迟,即99%的查询在多少秒内完成。3.3实时查询性能优化实时查询性能优化是ApacheDruid的一个重要方面,特别是在处理大量实时数据时。以下是一些优化实时查询性能的策略:数据分区:合理地对数据进行分区,可以减少查询时需要扫描的数据量。索引优化:使用更有效的索引类型,如Bitmap索引,可以显著提高查询速度。查询优化:避免使用复杂的查询,如多表连接,减少查询的复杂度。硬件升级:增加更多的节点或使用更强大的硬件,可以提高系统的整体性能。3.3.1示例:使用Bitmap索引优化查询在Druid中,可以为特定的维度字段创建Bitmap索引,以提高查询性能。以下是一个创建Bitmap索引的示例:{
"type":"index",
"spec":{
"dataSchema":{
"dataSource":"example",
"parser":{
"type":"string",
"parseSpec":{
"format":"json",
"timestampSpec":{
"column":"timestamp",
"format":"auto"
},
"dimensionsSpec":{
"dimensions":["dim1","dim2"],
"dimensionExclusions":[],
"spatialDimensions":[]
}
}
},
"metricsSpec":[
{
"type":"count",
"name":"count"
}
],
"granularitySpec":{
"type":"uniform",
"segmentGranularity":"HOUR",
"queryGranularity":"MINUTE",
"rollup":true,
"intervals":[
"2021-01-01T00:00:00.000Z/2021-01-02T00:00:00.000Z"
]
}
},
"tuningConfig":{
"type":"index",
"indexSpec":{
"bitmap":{
"type":"roaring"
}
}
}
}
}在这个示例中,我们为数据源example创建了一个索引任务,并指定了使用RoaringBitmap类型的索引。RoaringBitmap是一种高效的Bitmap实现,可以显著减少内存使用并提高查询速度。通过上述配置和监控工具的使用,可以有效地监控和优化ApacheDruid的性能,确保数据查询的高效和稳定。4数据分析工具:ApacheDruid性能调优4.1数据索引优化策略4.1.1理解数据索引在ApacheDruid中,数据索引是其高效查询和分析能力的核心。Druid使用列式存储,这意味着数据按列存储,而不是按行。这种存储方式非常适合于快速聚合和过滤操作,但需要正确的索引策略来确保最佳性能。4.1.2索引优化策略选择合适的分段粒度:Druid的数据被分割成多个段(segments),每个段可以独立查询。选择合适的分段粒度可以平衡查询性能和存储成本。例如,如果数据量大且查询频繁,可以使用更小的分段粒度以提高查询速度。使用高效的数据类型:Druid支持多种数据类型,包括字符串、整数、浮点数等。选择正确的数据类型可以减少存储空间,提高查询速度。例如,对于数值型数据,使用整数或浮点数类型比字符串类型更高效。合理使用维度压缩:维度压缩可以减少存储空间,提高查询速度。Druid提供了多种压缩算法,如DictionaryCompression,可以将常见的字符串值映射到更短的整数值,从而减少存储空间。4.1.3示例:使用Druid的DictionaryCompression//创建数据源时,指定维度压缩策略
DataSourcedataSource=newDataSource("exampleDataSource");
dataSource.setSpec(newMapSpec(
ImmutableMap.of(
"type","index",
"spec",newMapSpec(
ImmutableMap.of(
"dataSchema",newMapSpec(
ImmutableMap.of(
"dataSource","exampleDataSource",
"granularitySpec",newMapSpec(
ImmutableMap.of(
"type","uniform",
"segmentGranularity","HOUR",
"queryGranularity","MINUTE"
)
),
"dimensionsSpec",newMapSpec(
ImmutableMap.of(
"dimensions",Arrays.asList("dim1","dim2"),
"dimensionExclusions",Arrays.asList(),
"spatialDimensions",Arrays.asList(),
"dimensionCompression","lz4",
"dimensionCompressionDictionary","global"
)
),
"metricsSpec",Arrays.asList(
newMapSpec(
ImmutableMap.of(
"name","count",
"type","count"
)
),
newMapSpec(
ImmutableMap.of(
"name","sum",
"type","longSum",
"fieldName","value"
)
)
),
"parser",newMapSpec(
ImmutableMap.of(
"type","string",
"parseSpec",newMapSpec(
ImmutableMap.of(
"format","json",
"timestampSpec",newMapSpec(
ImmutableMap.of(
"column","timestamp",
"format","iso"
)
),
"dimensionsSpec",newMapSpec(
ImmutableMap.of(
"dimensions",Arrays.asList("dim1","dim2"),
"dimensionExclusions",Arrays.asList(),
"spatialDimensions",Arrays.asList()
)
)
)
)
)
),
"ioConfig",newMapSpec(
ImmutableMap.of(
"type","index",
"firehose",newMapSpec(
ImmutableMap.of(
"type","local",
"baseDir","/path/to/data",
"filter","example.json"
)
),
"appendToExisting",false
)
),
"tuningConfig",newMapSpec(
ImmutableMap.of(
"type","index",
"maxRowsInMemory",100000,
"maxRowsPerSegment",5000000,
"maxRowsInRollup",1000000
)
)
)
),
"ioConfig",newMapSpec(
ImmutableMap.of(
"type","index",
"firehose",newMapSpec(
ImmutableMap.of(
"type","local",
"baseDir","/path/to/data",
"filter","example.json"
)
),
"appendToExisting",false
)
),
"tuningConfig",newMapSpec(
ImmutableMap.of(
"type","index",
"maxRowsInMemory",100000,
"maxRowsPerSegment",5000000,
"maxRowsInRollup",1000000
)
)
)
)
)
);
//使用Druid的API或CLI工具来创建数据源
DruidCoordinatorcoordinator=newDruidCoordinator();
coordinator.createDataSource(dataSource);在上述示例中,我们创建了一个名为exampleDataSource的数据源,其中指定了使用lz4压缩算法和global字典压缩策略。这将帮助减少存储空间,同时保持查询性能。4.2缓存机制与调优4.2.1缓存机制Druid使用缓存来加速查询响应。缓存可以存储查询结果,当相同的查询再次执行时,可以直接从缓存中读取结果,而无需重新计算。Druid的缓存分为多个级别,包括Broker缓存和Historical缓存。4.2.2缓存调优调整缓存大小:根据系统的可用内存和查询模式,调整缓存大小可以显著提高查询性能。例如,如果查询模式是高度重复的,可以增加缓存大小以存储更多的查询结果。使用缓存预热:在系统启动时,可以预热缓存,将常见的查询结果加载到缓存中,以减少启动后的查询延迟。监控缓存命中率:通过监控缓存命中率,可以了解缓存的效率,并据此调整缓存策略。4.2.3示例:调整Broker缓存大小//配置Broker节点的缓存大小
{
"druid.broker.cache.size":"10GB",
"druid.broker.cache.type":"onheap",
"druid.broker.cache.ttl":"PT1H"
}在上述示例中,我们配置了Broker节点的缓存大小为10GB,缓存类型为onheap(在堆内存中),缓存的TTL(时间到活)为1小时。这意味着缓存中的数据将在1小时后过期,除非在此期间被重新访问。4.3资源分配与负载均衡4.3.1资源分配在Druid集群中,资源分配是指如何在不同的节点类型(如Historical、MiddleManager、Broker等)之间分配资源。合理分配资源可以确保系统的稳定性和性能。4.3.2负载均衡负载均衡是指如何在集群中的节点之间均匀分布查询和数据处理任务。Druid使用Zookeeper来管理集群状态,确保查询和任务可以被均匀分配。4.3.3示例:配置Historical节点的资源分配//配置Historical节点的资源分配
{
"druid.server.type":"historical",
"druid.historical.segment.maxSize":"10GB",
"druid.historical.memory.max":"20GB",
"druid.historical.numShards":10
}在上述示例中,我们配置了Historical节点的资源分配,包括每个段的最大大小为10GB,Historical节点的总内存限制为20GB,以及节点上的分片数量为10。这将帮助确保Historical节点可以有效地处理数据和查询,同时避免资源过度使用。通过上述策略和示例,可以有效地优化ApacheDruid的性能,包括数据索引、缓存机制和资源分配。这些优化将帮助确保Druid集群的稳定性和响应速度,从而提高数据分析的效率。5数据分析工具:ApacheDruid:高级主题详解5.1Druid集群扩展性5.1.1原理ApacheDruid是一个高性能、分布式的数据存储和查询系统,设计用于实时分析大规模数据集。其集群扩展性基于以下核心概念:数据分片:Druid将数据分割成多个段(Segment),每个段可以独立存储和查询,这使得数据可以分布在多个服务器上,从而提高查询性能和存储容量。水平扩展:Druid支持通过增加更多的服务器节点来扩展集群,包括数据服务器(Historical&MiddleTier)、查询服务器(Broker)和协调服务器(Coordinator),以应对不断增长的数据量和查询负载。负载均衡:Druid的查询负载通过Broker节点进行均衡,Broker节点会将查询分发到最合适的Historical或MiddleTier节点上,以优化查询性能。容错机制:Druid通过数据复制和故障检测机制确保高可用性,即使部分节点失效,集群仍能继续运行。5.1.2实践配置数据分片在Druid中,数据分片是通过配置perties文件实现的。例如,要将数据分割成每天一个段,可以设置:druid.segment.incrementalIndexSpec.granularity=HOUR
druid.segment.incrementalIndexSpec.rollup=true
druid.segment.incrementalIndexSpec.maxRowsInMemory=5000000
druid.segment.incrementalIndexSpec.maxRowsPerSegment=5000000扩展集群要扩展Druid集群,可以通过以下步骤:增加Historical或MiddleTier节点:在集群中添加更多Historical或MiddleTier节点,以增加数据存储和查询处理能力。更新集群配置:在perties文件中更新druid.coordinator.segmentPusher.httpUri和druid.coordinator.segmentPusher.httpUri.path,以指向新的Historical或MiddleTier节点。重启Coordinator:重启Coordinator节点,使其能够检测到新的节点并重新分配数据段。负载均衡Druid的负载均衡主要通过Broker节点实现。Broker节点会根据数据段的分布和节点的负载情况,智能地将查询分发到集群中的不同节点。为了优化负载均衡,可以调整druid.broker.selectStrategy配置,例如:druid.broker.selectStrategy=ROUND_ROBIN5.2故障恢复机制5.2.1原理Druid的故障恢复机制包括数据复制和故障检测两部分:数据复制:Druid支持数据段的复制,确保即使某个节点失效,数据仍然可访问。复制因子可以在druid.coordinator.loadQueue.capacity配置中设置。故障检测:Druid通过心跳机制检测节点状态,Coordinator节点会定期检查集群中所有节点的健康状况,一旦检测到故障节点,会自动将数据段重新分配到其他健康节点上。5.2.2实践配置数据复制在Druid的perties文件中,可以设置数据段的复制因子:druid.coordinator.loadQueue.capacity=3这表示每个数据段将被复制到集群中的三个不同节点
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- DB31/T 867-2014崇明水仙生产技术规程
- DB31/T 789-2014黄金珠宝饰品零售店经营服务规范
- DB31/T 762-2013食品零售商店服务规范
- DB31/T 668.12-2013节能技术改造及合同能源管理项目节能量审核与计算方法第12部分:配电变压器
- DB31/T 1356.1-2022公共数据资源目录第1部分:编制指南
- DB31/T 1219-2020节能技术评审方法和程序
- DB31/T 1101-2018液化石油气钢瓶延长使用期安全评定方法
- DB31/T 1046-2017家政服务从业人员基本要求
- DB31/T 1027-2017室内装饰装修材料挥发性有机化合物散发率测试系统技术要求
- DB31/ 590-2012变形铝及铝合金铸造锭、铸轧卷单位产品能源消耗限额
- 2024年版-生产作业指导书SOP模板
- 历年考研英语一真题及答案
- 宠物殡葬师理论知识考试题库50题
- 飞花令“水”的诗句100首含“水”字的诗句大全
- 门诊常见眼科病
- 保育师中级培训课件资源
- 心力衰竭病人的护理课件
- 教学机房规划方案
- 肿瘤患者全程管理
- 可行性研究报告编制服务投标方案
- 大学生如何处理学习与娱乐的平衡
评论
0/150
提交评论