Apache flink 在ApacheFlink中是否可以延迟事件流?

我将在我的RichMapFunctions中查询一个外部服务。外部服务在提供我的值时有一些延迟,我应该尝试,延迟,然后再次尝试以获取我的值(当然是有限的计数)!我知道我可以使用Thread.sleep加上一个简单的易断循环;但我希望我能找到更好的方法。这听起来像是Flink的异步函数的主要用例 AsyncFunction可以向外部服务发送多个异步请求,同时保留正确的检查点和水印语义。这可以显著提高流应用程序的延迟和吞吐量,从而无需延迟流 请查看详细信息

Apache flink 由于Avro数组类型,Flink抛出Kryo错误

我从Flink反序列化程序中的getProducedType方法中得到以下错误: com.esotericsoftware.kryo.KryoException: java.lang.NullPointerException Serialization trace: values (org.apache.avro.generic.GenericData$Record) at com.esotericsoftware.kryo.serializers.ObjectField.read(Ob

Apache flink Flink作业在第二次提交后崩溃

我想从Flink job将数据流传输到AWS S3。下面是指向将数据流传输到S3的简单测试应用程序的链接 IntelliJ的代码在jar提交到我的机器上的Flink集群时也能工作。问题是这项工作只能工作一次。如果第二次提交作业,则会生成堆栈跟踪。如果我重新启动群集作业,则该作业将正常工作,但仅限于第一次 org.apache.commons.logging.logonfigurationexception:java.lang.IllegalAccessError:试图从类org.apache.c

Apache flink 如何将FLINK程序的每个滑动窗口的结果写入新文件,而不是将所有窗口的结果追加到一个文件中

下面是一个flink程序(Java),它从文件中读取推文,提取哈希标记,计算每个哈希标记的重复次数,最后写入文件 现在在这个程序中有一个20秒大小的滑动窗口,可以滑动5秒。在接收器中,所有输出数据都将写入名为outfile的文件中。意味着每5秒就会触发一个窗口,并将数据写入outfile 我的问题: <!-- language: lang-java --> StreamExecutionEnvironment env = StreamExecutionEnvironment.ge

Apache flink Flink SQL:连接表的内存不足

我有一个经常更新的MySql表。我想为过去20秒内更新的每个id拍摄快照,并将值写入redis。我使用binlog作为流式输入,并将数据流转换为Flink表。我运行以下sql SELECT id, ts, val FROM my_tbl WHERE (id, ts) IN ( SELECT id, MAX(ts) FROM my_tbl GROUP BY TUMBLE(proctime, INTERVAL '20' SECOND), id ) 正如我所知,表联接会产生过大的状

Apache flink Flink任务管理器超时?

我正在运行一个Flink应用程序(通过Thread),任务管理器有时会随机超时,错误如下: java.util.concurrent.TimeoutException: Heartbeat of TaskManager with id someId timed out. at org.apache.flink.runtime.jobmaster.JobMaster$TaskManagerHeartbeatListener.notifyHeartbeatTimeout(JobMaster.

Apache flink 如何将avro文件写入Flink中的S3?

我想从卡夫卡主题中读取流数据,并以avro或拼花格式写入S3。数据流看起来像json字符串,但我无法以avro或parquet格式转换和写入S3 我找到了一些代码片段并尝试了 val sink=StreamingFileSink .forBulkFormat(新路径(outputS3Path),ParquetAvroWriters.forReflectRecord(classOf[myClass])) .build() 但我在addSink上得到了“类型不匹配,预期SinkFunction[St

Apache flink Flink配置可避免每次提交作业时上载扩展jar

Flink是否有避免每次提交作业时上传扩展罐的配置,如spark submit中的spark.Thread.archive 我知道处理外部jar的方法,如:中的答案。例如fat jar,将jar复制到$FLINK/lib,-yt配置,但它们不够灵活或方便。我注意到FLINK有一个问题需要解决,并且改进已经在最新版本1.11.0中合并 最终提交命令可以如下所示发出 ./bin/flink run -m yarn-cluster -d \ -yD yarn.provided.lib.dirs=hdf

Apache flink 阿帕奇·弗林克和阿帕奇脉冲星

我正在使用Flink从Apache Pulsar读取数据。 我在pulsar中有一个分区主题,有8个分区。 在本主题中,我生成了1000条消息,分布在8个分区中。 我的笔记本电脑中有8个内核,因此我有8个子任务(默认情况下,并行度=#个内核)。 在执行Eclipse中的代码后,我打开了Flink UI,发现一些子任务没有收到任何记录(空闲)。 我希望所有8个子任务都能得到利用(我希望每个子任务都映射到我的主题中的一个分区) 重新启动作业后,我发现有时使用3个子任务,有时使用4个任务,而其余子任务

Apache flink Flink StreamSink和检查点理解

我写了一份工作,在一个应用程序中有5个不同的源和接收器。我正在使用stream sink以拼花格式写入数据。作为拼花地板接收器,在检查点上写入数据。若其中一个源获得了一些错误的记录,那个么我将在接收器中得到异常。 但这导致我所有的消费者都被阻止了。我也无法通过其他接收器写入任何数据 例如: 资料来源1(卡夫卡)--sink1(s3) 资料来源2(卡夫卡)-新卡2(s3) 资料来源3(卡夫卡)-3(s3) 我需要理解为什么一个接收器发生故障,导致所有消费者停止,S3中没有数据写入。请有人帮我理解这

Apache flink 如何将数据保存在内存中以动态查询下一个数据

我正在用DataStream API在Flink中进行时间序列数据分析。每50个事件(数据收入)我想对它们进行一次转换,保存结果并将其与下50个事件的转换结果进行比较。等等等等。 我的问题是,在完成转换后,Flink中是否有方法保存结果,并使用以前的结果查询接下来50个事件的下一次转换?是的,有两种方法可以做到这一点,都是利用Flink状态 (1) 您可以在ProcessAllWindowFunction.Context中使用globalState()的计数窗口来记住有关上一个窗口的信息。()

Apache flink Flink:清除过程窗口功能数据

我需要在弗林克有一个聚集窗口。 我不能使用聚合函数。因为getResult计算需要me状态访问。 因此,我尝试将聚合与过程结合使用: .aggregate( new AggregateFunction<Entry, Double, Double>() { ........... }; , new ProcessWindowFunction<Double,

Apache flink 会话windows flink

有人能帮我理解flink的窗口(会话)是何时以及如何发生的吗?或者样本是如何处理的 例如,如果有一个连续的事件流流入,则事件是应用程序中的请求和应用程序提供的响应。 作为flink处理的一部分,我们需要了解服务请求需要多少时间 据我所知,存在每n秒触发一次的时间翻转窗口,一旦时间流逝,该时间窗口中的所有事件都将聚合 例如: 假设定义的时间窗口为30秒,如果一个事件在t时间到达,另一个事件在t+30到达,则这两个事件都将被处理,但在t+31到达的事件将被忽略 如果我说上述陈述不正确,请更正 上面的

Apache flink “什么是”呢;“外部状态”;在弗林克?

虽然Flink站点上的所有文档都没有提到“外部状态”,但我们在一篇论文中发现了这个概念(第4.1节)。我们如何实现这一点?曾经有一两次使用外部数据库作为Flink的状态后端的实验,但在开源项目中没有这样的尝试。这篇论文发表于2017年,我认为外部状态的想法实际上没有具体实现。

Apache flink Flink故障恢复:如果无状态运算符失败怎么办

我们知道,Flink定期为每个有状态的操作员创建检查点,当崩溃发生时,它可以使用检查点来恢复系统。但是我找不到任何关于这些过程中的无状态运算符的论文或文档--“检查点的创建”和“故障的恢复”。感谢您的帮助。无状态运算符没有状态,因此没有任何检查点或恢复,所以在检查点创建或恢复的上下文中不讨论它们

Apache flink 我们可以在Flink中同时计算和处理时间触发器吗?

我想在计数达到100后或翻滚过程时间每5秒完成一次窗口?也就是说,当元素达到100时,触发Windows计算,但是如果元素没有达到100,但时间经过5秒,它也会触发Windows计算,就像下面两个触发器的组合一样: .countWindow(100) .window(TumblingProcessingTimeWindows.of(Time.seconds(5))使用当前的Flink API没有超简单的方法来实现这一点 您的用例需要状态(用于计数)和计时器的组合。您可以使用自定义的windows

Apache flink Apache Flink检查点是否需要与有状态函数一起使用?

Apache Flink检查点功能是否需要与有状态函数一起使用?您不需要这样做。如果函数没有状态,则不会检查任何内容。但是请注意,某些内置函数本身具有状态,例如,FlinkKafkaConsumer,但是如果我有一个流。。。。地图,平面地图,地图。。。这是否意味着我已经计算过的全部都被处理掉了?或者也保存在检查点?如果它没有存储在某个接收器中,则这些计算将被处理,并且流将从经过整个DAG的最后一个元素重新播放。

Apache flink 如何使用Flink计算时间窗口流中的唯一单词?

有没有办法用Flink流计算时间窗口流中的唯一单词数?我看到了这个问题,但我不知道如何实现时间窗口。当然,这很简单。如果您希望在每个时间窗口中对所有输入记录进行聚合,则需要使用windowAll()的一种风格,这意味着您将不会使用keyedstream,并且无法并行操作 您需要决定是否需要,以及您是否正在运营 但粗略地说,你会这样做: StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironme

Apache flink 跨Flink数据流的多个步骤在节点内进行任务本地处理

节点内的任务本地处理: Flink数据流管道中是否有方法确保数据流的第一步和第二步发生在同一本地任务槽/本地机器上 用例: 是否需要实时视频处理,其中第一步的图像需要在第二步的同一台机器上本地使用?这减轻了从第二个节点中的另一个节点获取巨大映像的负担(Hadoop时代的基本位置要求)。 TaskManager可以将本地状态存储在内存或本地磁盘上。如何使JobManager将第二步路由到同一个任务管理器?是否基于.keyBy(sameKeyId)将其推送到同一分区? 我是否可以通过.keyBy(.

Apache flink 具有多重并行性的Flink映射函数,以及如何确定最终接收器的顺序

管道简单代码如下所示: source = env.addSource(kafkaConsumer) .map(func).setParallelism(2).sink() 如何确保out的顺序?首先,假设示例中的所有其他内容都具有1的并行性,并且只有map函数将并行运行。(尽管要真正实现这一点,必须在某个地方进行配置;默认并行度高于1。) 我们还假设您的Kafka使用者正在使用一个分区阅读单个主题,并且您正在询问如何实现并行转换以保留输入中存在的顺序 根据这些假设,答案是你能做的不多。map操

Apache flink 有什么理由喜欢增加任务管理器的数量而不是每个任务管理器的任务槽?

根据,影响任务可用资源量的因素有两个方面: 任务管理器的数量 任务管理器可用的任务插槽数 每个TaskManager有一个插槽意味着每个任务组在单独的JVM中运行(例如,可以在单独的容器中启动)。拥有多个插槽意味着更多的子任务共享同一个JVM。同一JVM中的任务共享TCP连接(通过多路复用)和心跳消息他们还可以共享数据集和数据结构,从而减少每项任务的开销。 使用文档中的这一行,您似乎总是错误地增加每个任务管理器的任务槽数量,而不是增加任务管理器的数量 一个具体的场景:如果我在Kubernetes

Apache flink ApacheFlink:RESTAPI检索度量值

我开始了延迟跟踪,并通过RESTAPI的/jobs/metrics。获得以下信息: {“id”:“latency.source_id.cbc357ccb763df2852fee8c4fc7d55f2.operator_id.e5ebb093256018a0621f548fbe118f8a.operator_子任务_index.0.latency_p75”, {“id”:“lastCheckpointExternalPath”},{“id”:“lastCheckpointExternalPath”

Apache flink Flink如何使用从Avro输入数据推断的模式创建表

我已将Avro文件加载到Flink数据集中: AvroInputFormat测试=新的AvroInputFormat( 新路径(“PathToAvroFile”) ,genericord.class); 数据集DS=env.createInput(测试); usersDS.print(); 以下是打印DS的结果: {“N_NATIONKEY”:14,“N_NAME”:“肯尼亚”,“N_REGIONKEY”:0,“N_评论”:“未决的借口激烈地讨价还价。未决的,快速的平托豆从t身边飘过”} {“

Apache flink 在计数窗口中合并/放弃事件

我刚开始使用Flink,有一个问题我不知道如何解决。我从卡夫卡主题中获取事件,这些事件表示来自移动设备的“信标”信号。设备每10秒发送一次事件 我有一个外部客户要求我们的设备提供一个信标,但每60秒一次。由于我们已经在使用Flink处理其他事件,我想我可以使用计数窗口来解决这个问题,但我很难理解如何“丢弃”前5个事件,而只发射最后一个事件。有什么想法吗?有一些方法可以做到这一点。据我所知,这个想法如下:您每10秒接收一次信标信号,但实际上您只需要最实际的一个,而不需要其他的,因为客户机每60秒请

Apache flink 将JDBCTableSource与StreamTableEnvironment一起使用会产生ClassCastException

我正在尝试使用JDBC postgresql db的源连接实现一个流应用程序。首先,我尝试了一个基本查询,但由于强制转换异常,我无法执行它 这是个例外 Caused by: org.apache.flink.streaming.runtime.tasks.ExceptionInChainedOperatorException: Could not forward element to next operator at org.apache.flink.streaming.runtime.task

Apache flink 使用onTimer和processElement的Apache Flink超时

我使用ApacheFlinkProcessElement1、processElement2和onTimer流设计模式来实现超时用例。我观察到,当我加入超时功能时,系统的吞吐量下降了几个数量级 关于Flink中onTimer内部实现的任何提示:是每个密钥流一个线程(不太可能),还是池/单执行线程持续轮询缓冲回调并拾取超时回调以执行 据我所知,Flink基于actor模型和反应模式(AKKA),它鼓励明智地使用少数非阻塞线程,因此onTimer的每个密钥流一个线程或任何其他模式通常不使用 Flink

Apache flink 带时间戳的弗林克计数器

我正在阅读Flink示例CountWithTimestamp,下面是示例中的代码片段: @Override public void processElement(Tuple2<String, String> value, Context ctx, Collector<Tuple2<String, Long>> out) throws Exception { // retrieve the current c

Apache flink pyflink(flink)1.12.0通过to_append_流将表转换为数据流时出现的错误(java api为:toAppendStream)

非常感谢您的帮助 代码: 从pyflink.common.typeinfo导入行类型信息、类型、基本类型信息、TupleTypeInfo 从pyflink.table导入环境设置,StreamTableEnvironment #溪流模式的环境创建 env_settings_stream=EnvironmentSettings.new_instance()。使用_blink_planner()。在_streaming_mode()中。生成() env\u stream=StreamTableEnv

Apache flink Flink:如何使用键/值存储转换数据流?

我想使用Flink连续接收来自输入Kafka主题的消息,对于每条消息,从消息中获取一个键字段,在键/值存储中进行查找,创建具有该值的消息的修改版本,并将结果消息输出到不同的Kafka主题。这是相当标准的流处理功能 密钥/值存储的实现仍在决定之中,可以通过Redis或Aerospike或SQL数据库或Kafka主题或其他方式实现 在弗林克我该怎么做?我使用DataStream API读/写Kafka主题。如何进行键/值查找?我会使用表API吗?数据流API 在其他工具集中,这将被视为流到表的连接?

Apache flink 使用hibench测试Flink时,如何获得吞吐量和处理延迟?

使用hibench测试Flink时,提交的作业是hibench的内置应用程序,即wordcount等程序的代码逻辑无法更改 如何获得Flink的吞吐量和处理延迟 此外,在hibench的/report/hibench.report文件中,我们无法获得Flink的吞吐量信息。 /report/hibench.report的内容如下: 类型 日期 时间 输入数据大小 持续时间(秒) Throunghput(字节/秒) Throunghput/节点 FlinkFixWindow 2021-05-17

Apache flink 不带数据接收器且打开检查点的Flink管道

我正在研究建造一条没有数据接收器的flink管道。i、 e我的管道在成功调用数据存储时结束 在这种情况下,如果我们不使用sink操作符,检查点将如何工作 因为检查点是基于检查点前历元(所有保持在状态或发射到接收器中的事件)和检查点后历元的概念。flink管道是否需要水槽?是的,水槽是flink执行模型的一部分: Flink中的数据流程序是实现 数据流上的转换(例如,过滤、更新状态、, 定义窗口、聚合)。数据流最初是创建的 来自各种来源(例如,消息队列、套接字流、文件)。 结果通过接收器返回,例如

Apache flink 如何从另一个flink程序向群集提交flink程序?

我想按需运行flink程序,在条件允许时提交。如何在flink 1.3.0版本中从java代码运行flink作业?您可以使用flink的REST API从另一个运行的flink作业提交作业。有关更多详细信息,请参阅。我只是在运行查询中将多个参数传递给程序时遇到问题。你能给我举个例子吗?你能用多个参数解决你的问题吗?否则,为它打开一个问题可能是有意义的。

Apache flink 如何在flink中设置rocksdb内存表大小?

我想限制rocsdb的内存表大小。我有几个问题: 1、taskmanager.memory.size配置是否包括rocksdb memtable的内存量? 2、是否有任何配置可以设置rocksdb memtable大小 Flink的内存参数中不包括RocksDB内存。你必须确保Flink为RocksDB留下足够的内存。然而,这并不简单,因为Flink将为有状态运算符的每个实例使用一个RocksDB实例。这意味着每个TaskManager的RocksDB实例数量取决于作业中有状态运算符的数量以及这

Apache flink Flink DataStream-在窗口上执行SQL查询,执行orderBy

因此,我正在使用Flink DataStream模拟一个流任务,并希望在每个窗口上执行一个SQL查询 假设这就是问题所在 SELECT name, age, sum(days), avg(salary) FROM employees WHERE age > 25 GROUP BY name, age ORDER BY name, age 我很难把它翻译成弗林克。据我所知,要计算平均值,我需要使用.apply()和WindowFunction手动计算。那我怎么计算总数呢?是否也在同一窗口功

Apache flink 弗林克计算中位数

我需要计算15分钟时间窗口内从卡夫卡流接收到的许多参数的中值 我找不到任何内置函数,但我找到了一种使用自定义WindowFunction的方法 我的问题是: 这对弗林克来说是一项艰巨的任务吗?数据可能非常大 如果数据达到千兆字节,flink会将所有数据存储在内存中直到时间窗口结束吗?(apply WindowFunction实现的一个参数是Iterable—时间窗口期间所有数据的集合) 谢谢你的问题包含几个方面,但让我回答最基本的一个: 这对Flink来说是一项艰巨的任务,为什么这不是一个标准示

Apache flink 弗林克什么时候到期;来自Queryablestate的s时间窗口结果?

我已经用翻滚窗口和QueryableState实现了Total WordCount示例 我使用了10秒时间窗口,当我打印结果时,它会显示正确的结果,但当我使用queryable状态并使用QueryableClient进行查询时,它会缓存时间窗口的最后一个结果,即使时间窗口发生更改 e、 g,对于时间窗口11:00:01到11:00:10,“Nirav”的字数为5 当我在时间11:00:50上查询“Nirav”时,它返回之前的计数5 所以我有两个问题: 这是Flink的QueryableState

Apache flink Apache Flink:每台机器的TaskManager数量

每台机器的CPU核心数是四个。在flink独立模式下,我应该如何设置每台机器上TaskManager的数量 1个TaskManager,每个TaskManager有4个插槽 2个TaskManager,每个TaskManager有2个插槽 4个TaskManager,每个TaskManager有1个插槽。此设置类似于apache storm 我想这取决于你的申请 在官方文件中,它说作为一个经验法则,一个好的默认任务槽数量应该是CPU核心的数量。使用“超线程”,每个插槽将占用2个或更多硬件线程上下

Apache flink 有没有关于动态缩放flink作业的想法?

如果有一个kafka主题有10个分区,我们想使用flink来使用这个主题。我们希望系统根据工作负载动态分配插槽,这意味着如果工作负载较低,flink作业可以使用较少的插槽(具有较少的并行性),如果工作负载较高,它可以以较高的并行性运行。有没有一个好的方法来实现这一点?首先停止作业似乎可以改变并行性。如果是,暂停时间是否会影响应用程序的实时功能?还有其他改变并行性的想法吗?多谢各位 有没有实现动态缩放的好方法 据我所知,目前的答案是否定的。然而,我们可以看出,这一点已在考虑中 暂停时间是否影响应用

Apache flink 弗林克工人任务分配不均

我有一个在大数据集上运行的Flink批处理作业。我的群集由25个节点组成,作为独立群集运行。其中一个关键步骤的并行度为70,我希望每个任务管理器在该步骤中获得2到3个插槽,相反,只使用了一半的工作人员,其中一些工作人员最多分配了8个插槽(这是他们可以获得的最大值) 除了对数据位置的影响外,另一个副作用是磁盘空间紧张。由于运行所有插槽的工作人员较少,因此与将插槽分布在集群的所有节点相比,每个插槽都必须存储更多的数据 我错过什么了吗?有没有办法强迫Flink在每个作业中尽可能多的TMs中分配插槽?目

Apache flink 弗林克翻滚窗标签

我有一个使用flink应用程序的场景,该应用程序接收以下格式的数据流: {“事件id”:“c1s2s34”,“事件创建时间戳”:“2019-03-07 11:11:23”,“金额”:“104.67”} 我使用下面的滚动窗口来查找过去60秒内输入流的总和、计数和平均值 keyValue.timeWindow(时间秒(60)) 但是,如何标记聚合结果,以便我可以说16:20和16:21之间的输出数据流聚合结果是x和、y计数和z平均值 任何帮助都是适当的。如果您查看Flink培训站点中的窗口示例---

Apache flink 在缓冲池被破坏的情况下,异步函数有用吗?

我正在ApacheFlink中做一个项目,我需要调用多个API来实现我的目标。每个API的结果都是下一个API工作所必需的。同样,当我在KeyedStream上执行此操作时,相同的流将同时适用于多个数据 下面挖。你能解释这个场景吗 /------API1---API2---- KeyedStream ----|------API1---API2---- \------API1---API2---- 当我执行所有这

Apache flink ApacheFlink:定期加载函数的配置

比方说,有一个动态配置存储在数据库中,用于从流中过滤黑名单事件 过滤器功能使用此配置,需要在一段时间间隔(10分钟)后重新加载/刷新新配置 可以在每次窗口调用中调用一个函数来重新加载配置并重新分配配置变量 注意:由于窗口中的此函数调用独立于流的事件数据,因此在触发窗口之前,不希望在内存中缓冲/保留流事件 有线索吗?您可以在窗口前面放一个ProcessFunction,让它进行过滤。我建议使用ProcessFunction,因为它可以有一个计时器,每10分钟触发一次,以触发配置数据的重新加载/刷新

Apache flink 使用Flink实现大时间窗的流连接

我需要根据密钥加入两个事件源。事件之间的间隔可能长达1年(即,id1的事件1可能在今天到达,第二个事件源的id1的相应事件2可能在一年后到达)。假设我只想输出连接的事件输出 我正在探索将Flink与RocksDB后端一起使用的选项(我遇到了一些表API,它们似乎适合我的用例)。我找不到进行这种长窗口连接的参考体系结构。我预计该系统每天处理大约2亿个事件 问题: 对于这种长窗连接,使用Flink是否存在明显的限制/陷阱 关于处理这种长窗口联接的任何建议 相关:我也在探索使用Lambda和Dynam

Apache flink 在弗林克提升内时旗

我正在浏览JobClient最近的API,我在方法stopWithSavepoint中看到了advanceToEndofettime标志。如果我理解正确,这将导致作业刷新基于时间的窗口。因此,如果我们从这个保存点开始,作业将从没有任何元素的windows开始。在我当前的用例中,我并不认为这是可取的——在我们所有的应用程序中,恢复重启后的状态是至关重要的。我想知道这样做的用例是什么?一种有用的情况是,您知道工作已经完成,并且不会有任何进一步的输入。如果源是有限的,比如文件,Flink会自动将当前水

Apache flink 基于POJO的状态模式演化

我将flink 1.11与Scala一起使用,我有一个关于使用POJO的模式演变的问题 在本文中,POJO支持状态模式演化(有一些限制) Scala案例类别是否也被视为POJO并因此得到支持 case class WordCount(word: String, count: Int) 或者我必须写这样的东西: class WordCount(var word: String, var count: Int) { def this() { this(null, -1)

Apache flink Flink json序列化时区问题

我使用JsonRowSerializationSchema将Flink的行序列化为JSON。SQL时间戳序列化存在时区问题 val row = new Row(1) row.setField(0, new Timestamp(0)) val tableSchema = TableSchema .builder .field("c", DataTypes.TIMESTAMP(3).bridgedTo(classOf[Timestamp]))

  1    2   3   4   5   6  ... 下一页 最后一页 共 50 页