应用办公生活信息教育商业
投稿投诉
商业财经
汽车智能
教育国际
房产环球
信息数码
热点科技
生活手机
晨报新闻
办公软件
科学动态
应用生物
体育时事

对Java中的几种Kafka客户端的浅析与使用建议

  介绍与分析
  在这篇文章中,会介绍了在Java中定义Kafka消费者的各种方法。
  Spring、Micronaut、Vert。x和AkkaStreams在引擎盖下使用kafkaclients库,并提供完整的功能集来消费Kafka消息。
  Kafka是一个著名的事件流量平台。我们在很多项目中使用它。没什么不寻常的工具很棒。各种框架和库提供与Kafka的集成。
  在这篇文章中,我想介绍一下其中一些Java语言,看看我们如何创建一个客户实例,用来读取Kafka消息:
  连接到Kafka的第一种方法是使用kafkaclients库中的KafkaConsumer类。其他的库或框架集成商通常使用该库。在本节中,我将重点介绍直接使用它。虽然它非常简单,但我们需要付出一些努力来提高效率。
  首先,我们希望我们的消费者能持续工作。因此,我们将在单独的线程中运行它,我们需要自己管理它。此外,我们需要将轮询放入不定式循环中。
  另一件事是关闭消费者,这可能很棘手。我们可以关闭线程并使用超时来关闭套接字和网络连接。然而,采用这种方法,我们错过了两个要点:
  显式关闭消费者会立即触发重新平衡,因为组协调员没有发现消费者因丢失心跳而离开。该操作也会完成待处理的偏移量提交。因此,在再次运行消费者之后,我们不会两次消费某些消息。
  接下来,如果我们想并行消费消息,我们需要提供一个自定义的解决方案来在同一个消费者组中运行特定数量的消费者。
  然而,每个消费者都需要两个线程一个用于轮询,另一个用于心跳。
  在消息的批量消费方面,我们在轮询一个队列后得到一个记录集合(可能为空)。
  因此,我们不必提供任何特定的配置或机制。
  当我们想要流式传输接收到的数据时,我们可以使用JDK的StreamAPI。但是如果我们想并行使用它们,情况就会变得复杂。更复杂的代码变得更容易出错。
  默认情况下,消费者会自动提交偏移量。但是,我们可以更改这一点并手动完成工作。API为我们提供了几种同步或异步调用操作的方法。此外,我们可以提交从队列上最后一次轮询收到的所有消息的所有偏移量,或者提供特定的主题分区值。
  使用普通的Kafka消费者,我们处理ConsumerRecord包含消息本身及其元数据的实例。它本身并不是一个缺点。但是,如果我们想解析它,我们需要提供我们的机制。
  所以,总的来说,我会谨慎使用这种方法,而是考虑其他可用的可能性。
  那么,让我们看看如何在一些框架或工具包中使用Kafka。
  SpringBoot
  当您在项目中使用SpringBoot时,您可以使用SpringforKafka集成。它提供了一种方便的监听器机制来实现对Kafka消息的消费。
  我们可以通过两种方式消费消息:使用消息侦听器的容器,或通过提供带有KafkaListener注释的类。
  当我们想使用消息侦听器方法时,我们需要提供两种类型的容器之一来运行我们的侦听器:
  KafkaMessageListenerContainer在单个线程上为容器配置中提供的所有主题提供消息消费,ConcurrentMessageListenerContainerKafkaMessageeListenerContainer允许在多线程环境中使用消息,为每个线程提供一个消息。
  容器具有丰富的API,允许我们设置各种配置参数(如线程、批处理、确认、错误处理程序等)。重要的是要设置一个监听器类一个消息驱动的POJO。MessageListener它是orBatchMessageListener接口的一个实例。两者都是基本的,允许我们使用类型化的ConsumerRecord实例。Spring还提供了其他更复杂的接口。
  然而,在Spring中使用Kafka消息最直接的方法是使用KafkaListener注解实现一个bean。处理接收到的消息的方法的签名可能会有所不同。您将使用的输入参数取决于您的需要,并且有很多可能性(有关详细信息,请查看注释javadocs)。在启动时,Spring会查找注解使用情况(带有注解的类必须是Spring组件)并创建运行在侦听器中定义的逻辑的Kafka消费者。
  ComponentpublicclassKafkaListenerConsumer{KafkaListener(topics{spring。kafka。consumer。topic},groupId{spring。kafka。consumer。groupid})publicvoidprocessMessage(ListMessageStringcontent){processinglogiccomeshere}}
  默认情况下,KafkaListener在单个线程中运行我们不会并行使用来自主题分区的消息。但是,我们可以通过两种方式改变这种行为。
  第一个是定义concurrency注解的参数,我们可以在其中设置给定侦听器正在使用的线程数。
  ComponentpublicclassKafkaListenerConsumer{KafkaListener(concurrency2,topics{spring。kafka。consumer。topic},groupId{spring。kafka。consumer。groupid})publicvoidprocessMessage(ListMessageStringcontent){processinglogiccomeshere}}
  第二个选项是为containerFactory参数提供一个值。它是生产用于运行侦听器逻辑的容器的容器工厂bean的名称。当工厂不是单线程时(并发设置为大于1的值),框架将容器线程分配给分区。
  BeanConcurrentKafkaListenerContainerFactoryString,StringmultiThreadedListenerContainerFactory(){ConcurrentKafkaListenerContainerFactoryString,StringfactorynewConcurrentKafkaListenerContainerFactory();factory。setConsumerFactory(consumerFactory());factory。setConcurrency(3);returnfactory;}
  在这两种情况下,如果我们的线程数多于分区数,则有些线程仍处于空闲状态。
  这还没有结束我们甚至可以使用topicPartitions参数为特定分区指定侦听器方法。有了这样的解决方案,Spring会自动在单独的线程中运行每一个。
  ComponentpublicclassPartitionedKafkaListenerConsumer{KafkaListener(clientIdPrefixpart0,topics{spring。kafka。consumer。topic},groupId{spring。kafka。consumer。groupid},topicPartitions{TopicPartition(topic{spring。kafka。consumer。topic},partitions{0})})publicvoidpartition0(ConsumerRecordString,Stringcontent){processinglogiccomeshere}KafkaListener(clientIdPrefixpart1,topics{spring。kafka。consumer。topic},groupId{spring。kafka。consumer。groupid},topicPartitions{TopicPartition(topic{spring。kafka。consumer。topic},partitions{1})})publicvoidpartition1(ConsumerRecordString,Stringcontent){processinglogiccomeshere}}
  SpringforKafka也提供了批量消费消息的功能。当然,我们也是有不止一种选择。
  第一个是容器工厂中批处理的配置开关。启用后,我们可以提供一个接受消息列表的侦听器。
  重要的是我们需要使用批处理容器作为KafkaListener注解中的containerFactory参数值。一个选项使用带有前缀的消息侦听器接口。Batch他们接受消费者记录列表而不是单个记录。
  当涉及到手动提交消息偏移量时,我们有同样丰富的选择。
  首先,我们有原始的Kafka设置,即enable。auto。commit。当它为真时,Kafka根据其配置提交所有消息。否则,将根据配置中设置的确认模式的值来选择负责提交的实体。对于ack设置为MANUALorMANUALIMMEDIATE,由开发人员提交偏移量。对于所有其他值,由容器来运行它。此外,我们可以指定提交操作的同步性。
  当我们使用手动提交时,我们可以Acknowledgment在框架的一些消息监听器中使用该类。该接口提供了调用已处理消息的提交操作或丢弃上次轮询的剩余记录的方法。
  SpringforKafka让我印象深刻的是设置工作Kafka消费者的方法的数量。我们可以通过多种方式做到这一点,这很好,因为框架的弹性。但是,当我们迷失在各种可用选项中时,它也可能是有害的。
  Micronaut
  与Spring一样,Micronaut框架与Kafka进行了专门的集成,并且也适用于消息驱动的POJO。消费者的配置甚至类似。
  我们从KafkaListener类级别的注释开始。这是我们定义一组消费者的地方。这样的组是基于为具有给定groupId的特定组提供默认值或值的配置文件内容配置的。我们可以使用注释参数覆盖这些值。
  侦听器类的每个公共或包私有方法,用Topic(提供强制性主题名称模式)注释,成为在后台运行的Kafka消费者。我们也可以将注释放在类级别,但所有公共或私有包方法都成为Kafka消费者。所以我们需要小心这个。KafkaListener(groupIdmicronautgroup,clientId{kafka。consumers。micronautgroup。clientid})publicclassMicronautListener{Topic({kafka。consumers。micronautgroup。topic})voidreceive(KafkaKeyStringkey,Stringvalue){processinglogiccomeshere}}
  要设置并发消息处理,我们可以将线程数定义为KafkaListener注释参数。如果我们提供的线程数少于分区数,一些消费者将处理来自两个或更多分区的消息。另一方面,如果我们设置更多它们,一些会保持闲置,什么也不做。这与Spring集成中的行为相同。
  KafkaListener(groupIdmicronautgroup,clientId{kafka。consumers。micronautgroup。clientid},threads5)publicclassMultithreadedMicronautListener{Topic({kafka。consumers。micronautgroup。topic})voidreceive(KafkaKeyStringkey,Stringvalue,intpartition){switch(partition){case0:processinglogiccomesherebreak;case1:processinglogiccomesherebreak;case2:processinglogiccomesherebreak;default:log。error(Message(key{},value{})fromunexpectedpartition({})received。,key,value,partition);}}}
  同样,我们可以使用注释上的batch参数启用批处理。
  然后我们可以在消费者方法中消费一个记录列表(或领域类)。
  KafkaListener(groupIdmicronautgroup,clientId{kafka。consumers。micronautgroup。clientid},batchtrue)publicclassBatchedMicronautListener{Topic({kafka。consumers。micronautgroup。topic})voidreceive(ListConsumerRecordString,Stringrecords){log。info(Batchreceived:{},records。size());records。forEach(recprocessinglogiccomeshere);}}
  偏移提交的Micronaut管理提供了一些选项。我们通过OffsetStrategy枚举定义使用哪一个。您可以在框架文档中找到对它的出色描述。这是处理记录后使用手动提交的示例:
  Micronaut中Kafka类的配置比Spring中的配置更加简洁。在维护代码方面,更改或更新的地方更少了。但是,与Spring不同,我们不能以编程方式定义消费者,而无需使用注释。
  AkkaStream
  下一个客户端是带有Alpakka连接器〔urlhttps:doc。akka。iodocsakkacurrentstreamindex。html〕的AkkaStreams〔url〕库。
  此设置提供了一种使用来自Kafka的消息的反应方式。它在底层使用了AkkaActors框架。
  在这里,我们将Kafka消费者作为事件源的实例。在提供的数据类型、提供的元数据和分区信息以及处理偏移提交的方式方面有所不同。
  让我们从Consumer。plainSource。ConsumerRecord它在单个线程中为整个主题发出消息,保留给定分区的消息消费顺序。根据Kafka消费者配置,流可以自动提交已处理的记录。
  Consumer。plainSource(consumerSettings,Subscriptions。topics(topicName))。map(consumerRecord{processinglogiccomesherereturnconsumerRecord;})。runWith(Sink。ignore(),materializer)。toCompletableFuture()。handle(AppSupport。doneHandler())。join();
  我们也可以选择手动提交消息。如果是这样,我们需要使用提供消费者记录和有关当前偏移量信息的可提交源之一。在处理完一条消息后,我们可以利用额外的数据来调用一个Committer实例来进行手动提交。
  Consumer。committableSource(consumerSettings,Subscriptions。topics(topicName))。map(committableMessage{processinglogiccomesherereturncommittableMessage;})。mapAsync(maxParallelism,msgCompletableFuture。completedFuture(msg。committableOffset()))。runWith(Committer。sink(CommitterSettings。create(committerSettings)),materializer)。toCompletableFuture()。handle(AppSupport。doneHandler())。join();
  关于并行处理事件,该库也提供了出色的工具。最简单的解决方案是使用普通分区源,它发出记录源以及主题分区信息。
  当我们使用来自子源的消息时,该操作在每个分区的单独线程上运行。但是,我们可以使用分区信息以自定义方式分配线程分配(我们需要使用flatMapMerge和groupBy运算符)。
  Consumer。plainPartitionedSource(consumerSettings,Subscriptions。topics(topicName))。mapAsync(maxPartitions,pair{SourceConsumerRecordString,String,NotUsedsourcepair。second();returnsource。map(record{processinglogiccomesherereturnrecord;})。runWith(Sink。ignore(),materializer);})。runWith(Sink。ignore(),materializer)。toCompletableFuture()。handle(AppSupport。doneHandler())。join();
  并行使用数据时最重要的是结果的顺序。我们有两个选择。
  第一个是使用mapAsync运算符。它是使用参数中指定大小的线程池。该阶段确保下游发出消息的顺序,但不保证处理顺序。另一方面假设发出消息的顺序对我们来说并不重要。在这种情况下,我们可以使用mapAsyncUnordered操作符它会在处理完成后向下游传递消息,而不管接收顺序如何。
  批处理也可用。我们可以通过使用类似groupedor的批处理操作符batch来实现它。在这种情况下,我们需要使用一个CommittableOffsetBatch实例并使用批处理中最后处理的消息的偏移量对其进行更新。然后,我们需要在流程的下一步中调用commit。
  AkkaStreams对Kafka的支持令人惊叹。它将消息作为数据流来消费,这是最适合Kafka消费者的方式。
  由于消息源的粒度,我们可以轻松地为我们的案例选择最合适的一个。通过利用Streams的强大API,我们可以非常快速地获得批处理或背压等功能。
  使用AkkaStreams时对我来说最大的缺点是操作符的丰富性。您可能需要一些时间来熟悉它。但是,当您查看连接器源代码时,您会发现许多如何将Streams与Kafka一起使用的示例。Vertx
  介绍的最后一种实现消费来自Kafka的消息的方法是使用Vert。x工具包。
  该方法类似于AkkaStreams的方法它适用于Verticle,一种轻量级Actor的形式。verticles使用事件总线在彼此之间传递消息。
  它们可以在事件循环和工作线程上运行。核心库提供基本功能(如在AkkaStreams中),我们需要使用外部组件来连接Kafka,即vertxkafkaclient。
  虽然一般假设与AkkaStreams中的假设非常相似,但使用代码看起来不同。
  Vert。x应用程序使用事件循环和工作线程。
  前者将事件传递到目标顶点,并且可以运行快速、非阻塞的代码。后者的目的是完成繁重的工作,例如IO或昂贵的计算。
  因此,我们应该考虑使用工作线程来消费Kafka消息,这样循环不会被阻塞,应用程序运行顺畅。
  示例代码包含作为工作人员运行的Kafkaverticles。
  对,那么我们该如何创建Kafka消息的消费者呢?Vert。x客户端为此提供了一个类KafkaConsumer。它提供了几种工厂方法,用于根据提供的配置创建实例。
  有了消费者,我们需要在启动顶点之前订阅一些Kafka主题。我们可以从subscribe方法的几个变体中进行选择。调用其中之一使顶点能够从单个或多个主题中读取数据。下一步是注册处理函数,使用接收到的消息。所有这一切,我们都是通过在消费者身上使用流畅的API来完成的。
  这是为一个或多个主题创建普通消费者的方式,没有分区拆分到不同的线程。正如您在示例项目中看到的那样,我已经封装了verticle地逻辑并将其部署为workerverticle。使用此解决方案,所有消息都将由同一个工作线程使用。classKafkaVerticleextendsAbstractVerticle{initializationOverridepublicvoidstart(){KafkaConsumer。create(vertx,kafkaConfig)。subscribe(topic)。handler(recordprocessinglogiccomeshere)。endHandler(vlog。info(Endofdata。Topic:{},this。topic))。exceptionHandler(elog。error(SingleKafkaconsumererror,e));}}
  根据Kafka配置,消费者可能会自动提交偏移量。
  但是手动触发动作呢?Vert。x消费者提供了完成这项工作的提交方法。
  我们可以将它们称为单个消息或特定主题和分区的一组偏移量。
  在为给定主题的所有分区创建消费者时,我们需要手动设置Vertx。
  首先,我们需要知道我们想要处理哪些主题的多少个分区。
  我们可以使用KafkaAdminClient来描述我们感兴趣的话题。
  接下来,我们需要为每个主题分区对创建一个包含Kafka消费者的专用线程。
  在线程内部,我们将消费者分配给所需的主题分区数据并指定处理程序,就像在普通消费者线程中一样。
  根据Kafka的配置,消费者可能会自动提交offsets。
  但是手动触发动作呢?Vert。x消费者提供了做这个工作的提交方法。我们可以为单个消息或者为特定主题和分区的一堆偏移量调用它们。
  当涉及到为某一主题的所有分区创建消费者时。
  我们需要手动设置Vertx。
  首先,我们需要知道我们想处理哪些主题的多少个分区。我们可以调用KafkaAdminClient来描述我们感兴趣的主题。
  接下来,我们需要为每个主题分区对创建一个专用Vertx线程,包含Kafka消费者。在顶点内,我们将消费者分配给所需的主题分区数据,并像普通消费者顶点那样指定处理程序。createrequirednumberofverticesIntStream。range(0,numberOfPartitions)。forEach(partition{vertx。deployVerticle(()KafkaPartitionedVerticle。create(topic,partition,kafkaConfig),deploymentOptions,asynclog。info(PartitionedKafkaconsumerdeployed。DeploymentId:{},async。result()));});insideKafkaPartitionedVerticleclassKafkaPartitionedVerticleextendsAbstractVerticle{initializationOverridepublicvoidstart(){KafkaConsumer。create(vertx,kafkaConfig)。assign(newTopicPartition(topic,partition),AsyncResult::result)。handler(recordprocessinglogiccomeshere)。endHandler(vlog。info(Endofdata。Topic:{},partition:{},this。topic,this。partition))。exceptionHandler(elog。error(PartitionedKafkaconsumererror,e));}}
  正如我上面提到的,每个Kafka消费者都使用一个专门的处理器来处理收到的消息。根据我们的需要,我们可以一条一条地消费记录,也可以分批消费。在前一种情况下,我们使用handler方法定义一个函数,而对于后者,我们使用batchHandler方法。Kafka组件分别以KafkaConsumerRecord或KafkaConsumerRecords的形式提供记录。在这两种情况下,在引擎盖下,我们可以找到一个好的旧ConsumerRecord实例。
  总结
  哪一个更优越呢?我想说没有,除了一种情况。
  如果你有一个项目考虑直接使用kafkaclients库,我会建议你不要这样做。这个库是一种连接到Kafka的驱动。在项目中使用它,我们需要接受的是,在某种程度上,我们将重新发明已经在其他工具中实现的轮子。
  如果你的项目中的框架不限制你,我建议使用AkkaStreams。
  否则,寻找已经存在的集成。如果你的服务是在Spring框架内开发的,那么应用AkkaStreams是没有意义的。或者在Vert。x应用程序中使用Micronaut。
  如果有更好的方法,欢迎各位大佬指教。
  原文:https:www。jdon。com58627

iPhone开机键10大实用功能,不会用的手机都白买了果粉之家,专业苹果手机技术研究十年!您身边的苹果专家说起iPhone的锁屏键,想必大家都很熟悉,但要问起iPhone的电源键具体有哪些实用功能,可能很多小伙伴就不太清楚了……瑞士冷知识很多人出国旅行已经是三年前的事了。因为一场疫情,说走就走的旅行,变成了说没就没的航班,就连酒店都变成了隔离的代名词。网友Bellanalice说出了大多数人的心声:……俄罗斯的船,美国不得不坐极目新闻记者宋清影据美联社报道,当地时间3月14日,美国宇航局官员表示,本月内美国宇航员范德海(MarkVandeHei)将乘坐俄罗斯联盟号飞船从国际空间站返回地球,还将……海南接续海外抢单,向优等生看齐本身就是一种成功12月4日,一支由浙江省商务厅等省级部门相关负责人及企业代表组成的抢单团驱车前往机场,开启为期6天的欧洲行,拉开了浙江百团千企万人拓市场促招引行动的序幕,也引来了外界一阵的欢呼……庙会是怎么来的呢?要说到传统的民俗文化活动,逛庙会绝对是榜上有名。跟着爸爸妈妈来到庙会,年味值瞬间拉满。庙会是怎么来的呢?过去,为了求得祖先及神灵的保佑,先民们选择了在宫殿或房舍里通……赵丽颖被问儿子有多少抚养费?赵丽颖漏嘴的回答,暴露了高情商引读:赵丽颖被问:儿子有多少抚养费?赵丽颖漏嘴的回答,暴露了高情商其实很多人都比较喜欢赵丽颖,因为赵丽颖看出来真的是非常的小巧可爱,而且让人感觉非常的单纯。都知道赵丽颖的……每天学习一味中药天麻平肝息风药均入肝经,多为动物药及矿石类药物,具有平肝潜阳、息风止痉的功效。部分药以其质重、性寒、沉降之性,兼有镇惊安神、清肝明目、重镇降逆、凉血以及祛风通络等功效。第二节……春天,阔腿裤更时髦好看的打开方式和这几件春外套搭配要说近几年时尚圈最受宠的裤装种类,那一定是阔腿裤了,阔腿裤作为四季常青的款式,有着极好的遮肉显瘦效果。不过越是火热的单品越容易烂大街,阔腿裤亦是如此,今天就来为大家安利一些阔腿……心海导航如何才能减少亲子矛盾与冲突,建立良好的亲子关系呢?理解和尊重父母。古人云百善孝为先,孝顺父母是中华民族的传统美德。父母是给予我们生命并养育我们的人,他们为我们的成长耗费了许多心……美国品牌也不行!特斯拉想要突破140万,就不能在国内搞双重标特斯拉作为美国品牌,在消费者的支持下,2022年销量想要突破140万特斯拉作为电动汽车中的领军企业,虽然也受到了芯片紧缺的影响,但是依然在2021年交出来一份满意的答卷。……老牌厂商彻底爆发,骁龙8708GB运存,屏下摄像头手机不足2在功能机时代,最受欢迎的国产品牌是华为,中兴,酷派和联想,在当时这四个品牌也尊称被称为中华酷联。随着后来智能手机兴起,这四个品牌只有华为混得比较好,不过近年来华为的遭遇大家也都……皮肤科医生建议脸上有皱纹,常用2个方法,或许能减轻每个女性在年轻的时候都是貌美如花的,不仅肌肤细腻光滑,身材也是苗条有型,随着岁月的变迁,年少青春的美人,也逐渐变成了年暮的老人,终究还是敌不过岁月的蹉跎,说起抗衰老,女性最有话……
詹姆斯威少因交易翻脸?杜兰特狂追中国美女被拒,瓦妮莎减肥成功在交易截止期前,威少一度认为自己要走了,但是在交易截止期前,威少赛季第一次缺阵,这也被认为是交易开启的前兆。结果让人没有想到的是,湖人队总经理佩林卡认为如今湖人的现状是球……2021年打工不如创业,优布劳抢占精酿啤酒屋蓝海市场2020是不平凡的一年,新冠疫情席卷全国,很多行业被迫停业,资金无法正常回笼,造成经营压力。同时,失业大潮亦愈演愈烈,生存的现实问题摆在了很多人的眼前,中国精酿啤酒市场,作为后……竹笋哪里的(凉拌竹笋)埔田竹笋是广东省揭阳市揭东区特产,也是中国国家地理标志产品。据中国特产协会了解,这里所产竹笋品种独特,是稀有的食用笋品种,且具有高纤维、低蛋白、无脂肪,含多种氨基酸及维生素,味……什么洗头膏去屑效果好(去屑止痒最好的洗发水)按:头屑问题如何解决?据统计,有1。4亿中国消费者有顽固性头屑问题。2020年10月发布的《最新中国居民头皮健康状况调查报告》显示,我国超过83的消费者都有不同程度……天时地利人和成就2020市场唯一绿色供热合同债权ABS天风榜天时地利人和成就2020市场唯一绿色供热合同债权ABS天风榜样2020年,是天风成立的第20年。廿年来,我们栉风沐雨、凝聚共识、团结奋进,因笃信不惧而勇往直前,才有天风今……体积小,价格便宜,容量管够!入手移速512GB移动固态硬盘固态硬盘这东西,一旦开始用,真的就会上瘾的!所以在捣鼓完将笔记本电脑的2个硬盘位都换成固态硬盘后,我又陆陆续续将原本用的移动硬盘也都换成固态的了但好像还觉得不够过瘾,因为……月球离地球有多少公里(中国9人疑似外星人)月球,还存在着太多的秘密,在以前人类没有登上月球之时,嫦娥奔月这个古代神话故事,给我们的童年带来了很多的神话传说,1969年,人类第一次登上月球后,月球上的环境,让大家第一次了……一个鸡蛋含多少蛋白质(怎样判断蛋白质吃多了)有一句话叫做没有蛋白质就没有生命,很多小伙伴应该都听说过。足以可见蛋白质对于我们人体来说有多么重要。毕竟缺乏蛋白质,确实会造成人体很多亚健康甚至疾病发生,比如因为我家乡属……莱德克汉堡加盟费多少总部莱德克汉堡加盟费用【总部电话】行业优势突出,很多人就在此抓住莱德克汉堡这个被很多人重视的商机,最终成为别人一辈子奋斗的榜样。莱德克汉堡旗开得胜,已经成为行业的旗帜。不少人……多久换减震器(汽车减震器油多久更换一次)家用轿车减震器建议6年或10万公里更换。1、一般乘用车减震器建议5年8万公里更换,家用轿车一般属于轻度用车(使用不那么频繁驾驶操作比较规范爱惜)6年10万公里更换减震器也……新款迷你录音机仅售2500元专业音质真的值了就在前两天,知名录音机品牌ZOOM,发布了一款全新的迷你录音机F3FieldRecorder。正方体的机身设计,最宽只有7。73厘米,携带很方便。而且搭配了加固外壳,四根支架扣……冬奥金牌榜中国创造历史,美媒公布另类排名,中国队变成第11名冬奥金牌榜中国队创造历史!美媒公布另类排名,中国队变成第11名北京时间2月20日,冬奥会闭幕式上演,也让世界各国的选手和观众再次见识到了属于中国的温暖。东道主中国队以9金……
友情链接:快好找快生活快百科快传网中准网文好找聚热点快软网