日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術文章
文章詳情頁

使用spring boot 整合kafka,延遲啟動消費者

瀏覽:197日期:2023-02-18 15:50:56
spring boot 整合kafka,延遲啟動消費者

spring boot整合kafka的時候一般使用@KafkaListener來設置消費者,但是這種方式在spring啟動的時候就會立即開啟消費者。如果有需要根據配置信息延遲開啟指定的消費者就不能使用這種方式。

參考了類:KafkaListenerAnnotationBeanPostProcessor,我提取了一部分代碼。可以根據需要隨時動態的開啟消費者。還可以很方便的啟動多個消費者。

為了方便使用,我自定義了一個注解:

import org.springframework.kafka.annotation.TopicPartition; import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target; @Target({ ElementType.METHOD})@Retention(RetentionPolicy.RUNTIME)public @interface DelayKafkaConsumer { String id() default ''; String[] topics() default {}; String errorHandler() default ''; String groupId() default ''; TopicPartition[] topicPartitions() default {}; String beanRef() default '__listener';}配合注解使用的factory:

import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.aop.framework.Advised;import org.springframework.aop.support.AopUtils;import org.springframework.beans.BeansException;import org.springframework.beans.factory.BeanFactory;import org.springframework.beans.factory.BeanFactoryAware;import org.springframework.beans.factory.ListableBeanFactory;import org.springframework.beans.factory.ObjectFactory;import org.springframework.beans.factory.config.*;import org.springframework.context.expression.StandardBeanExpressionResolver;import org.springframework.core.MethodIntrospector;import org.springframework.core.annotation.AnnotationUtils;import org.springframework.core.convert.converter.Converter;import org.springframework.core.convert.converter.GenericConverter;import org.springframework.format.Formatter;import org.springframework.format.FormatterRegistry;import org.springframework.format.support.DefaultFormattingConversionService;import org.springframework.kafka.annotation.KafkaListenerConfigurer;import org.springframework.kafka.annotation.PartitionOffset;import org.springframework.kafka.annotation.TopicPartition;import org.springframework.kafka.config.KafkaListenerEndpoint;import org.springframework.kafka.config.KafkaListenerEndpointRegistrar;import org.springframework.kafka.config.MethodKafkaListenerEndpoint;import org.springframework.kafka.listener.KafkaListenerErrorHandler;import org.springframework.kafka.support.KafkaNull;import org.springframework.kafka.support.TopicPartitionInitialOffset;import org.springframework.messaging.converter.GenericMessageConverter;import org.springframework.messaging.handler.annotation.support.*;import org.springframework.messaging.handler.invocation.HandlerMethodArgumentResolver;import org.springframework.messaging.handler.invocation.InvocableHandlerMethod;import org.springframework.stereotype.Service;import org.springframework.util.Assert;import org.springframework.util.ReflectionUtils;import org.springframework.util.StringUtils; import java.lang.reflect.Method;import java.util.*;import java.util.concurrent.atomic.AtomicInteger; @Servicepublic class MyKafkaConsumerFactory implements KafkaListenerConfigurer,BeanFactoryAware { private static final Logger logger = LoggerFactory.getLogger(MyKafkaConsumerFactory.class); private KafkaListenerEndpointRegistrar kafkaListenerEndpointRegistrar; private final AtomicInteger counter = new AtomicInteger(); private BeanFactory beanFactory; private BeanExpressionResolver resolver = new StandardBeanExpressionResolver(); private BeanExpressionContext expressionContext; private final ListenerScope listenerScope = new ListenerScope(); private final KafkaHandlerMethodFactoryAdapter messageHandlerMethodFactory = new KafkaHandlerMethodFactoryAdapter(); @Override public void configureKafkaListeners(KafkaListenerEndpointRegistrar registrar) {this.kafkaListenerEndpointRegistrar = registrar;addFormatters(messageHandlerMethodFactory.defaultFormattingConversionService); } public void startConsumer(KafkaListenerEndpoint endpoint){kafkaListenerEndpointRegistrar.registerEndpoint(endpoint); } public void startConsumer(Object target){logger.info('start consumer {} ...',target.getClass());Class<?> targetClass = AopUtils.getTargetClass(target);Map<Method, Set<DelayKafkaConsumer>> annotatedMethods = MethodIntrospector.selectMethods(targetClass,new MethodIntrospector.MetadataLookup<Set<DelayKafkaConsumer>>() { @Override public Set<DelayKafkaConsumer> inspect(Method method) {Set<DelayKafkaConsumer> listenerMethods = findListenerAnnotations(method);return (!listenerMethods.isEmpty() ? listenerMethods : null); } });if (annotatedMethods.size()==0) throw new IllegalArgumentException(target.getClass()+' need have method with @DelayKafkaConsumer');for (Map.Entry<Method, Set<DelayKafkaConsumer>> entry : annotatedMethods.entrySet()) { Method method = entry.getKey(); logger.info('find message listen handler method : {} , object : {}',method.getName(),target.getClass()); for (DelayKafkaConsumer listener : entry.getValue()) {if(listener.topics().length==0) { logger.info('topics value is empty , will skip it , method : {} , target object : {}',method.getName(),target.getClass()); continue;}processKafkaListener(listener,method,target);logger.info('register method {} success , target object : {}',method.getName(),target.getClass()); }}logger.info('{} consumer start complete .',target.getClass()); } protected void processKafkaListener(DelayKafkaConsumer kafkaListener, Method method, Object bean) {Method methodToUse = checkProxy(method, bean);MethodKafkaListenerEndpoint endpoint = new MethodKafkaListenerEndpoint();endpoint.setMethod(methodToUse);endpoint.setBeanFactory(this.beanFactory);String errorHandlerBeanName = resolveExpressionAsString(kafkaListener.errorHandler(), 'errorHandler');if (StringUtils.hasText(errorHandlerBeanName)) { endpoint.setErrorHandler(this.beanFactory.getBean(errorHandlerBeanName, KafkaListenerErrorHandler.class));}processListener(endpoint, kafkaListener, bean, methodToUse); } protected void processListener(MethodKafkaListenerEndpoint<?, ?> endpoint, DelayKafkaConsumer kafkaListener, Object bean, Object adminTarget) {String beanRef = kafkaListener.beanRef();if (StringUtils.hasText(beanRef)) { this.listenerScope.addListener(beanRef, bean);}endpoint.setBean(bean);endpoint.setMessageHandlerMethodFactory(this.messageHandlerMethodFactory);endpoint.setId(getEndpointId(kafkaListener));endpoint.setGroupId(getEndpointGroupId(kafkaListener, endpoint.getId()));endpoint.setTopics(resolveTopics(kafkaListener));endpoint.setTopicPartitions(resolveTopicPartitions(kafkaListener));kafkaListenerEndpointRegistrar.registerEndpoint(endpoint);if (StringUtils.hasText(beanRef)) { this.listenerScope.removeListener(beanRef);} } private String getEndpointId(DelayKafkaConsumer kafkaListener) {if (StringUtils.hasText(kafkaListener.id())) { return resolve(kafkaListener.id());}else { return 'Custom-Consumer' + this.counter.getAndIncrement();} } private String getEndpointGroupId(DelayKafkaConsumer kafkaListener, String id) {String groupId = null;if (StringUtils.hasText(kafkaListener.groupId())) { groupId = resolveExpressionAsString(kafkaListener.groupId(), 'groupId');}if (groupId == null && StringUtils.hasText(kafkaListener.id())) { groupId = id;}return groupId; } private String[] resolveTopics(DelayKafkaConsumer kafkaListener) {String[] topics = kafkaListener.topics();List<String> result = new ArrayList<>();if (topics.length > 0) { for (int i = 0; i < topics.length; i++) {Object topic = resolveExpression(topics[i]);resolveAsString(topic, result); }}return result.toArray(new String[result.size()]); } private void resolveAsString(Object resolvedValue, List<String> result) {if (resolvedValue instanceof String[]) { for (Object object : (String[]) resolvedValue) {resolveAsString(object, result); }}else if (resolvedValue instanceof String) { result.add((String) resolvedValue);}else if (resolvedValue instanceof Iterable) { for (Object object : (Iterable<Object>) resolvedValue) {resolveAsString(object, result); }}else { throw new IllegalArgumentException(String.format( '@DelayKafkaConsumer can’t resolve ’%s’ as a String', resolvedValue));} } private TopicPartitionInitialOffset[] resolveTopicPartitions(DelayKafkaConsumer kafkaListener) {TopicPartition[] topicPartitions = kafkaListener.topicPartitions();List<TopicPartitionInitialOffset> result = new ArrayList<>();if (topicPartitions.length > 0) { for (TopicPartition topicPartition : topicPartitions) {result.addAll(resolveTopicPartitionsList(topicPartition)); }}return result.toArray(new TopicPartitionInitialOffset[result.size()]); } private List<TopicPartitionInitialOffset> resolveTopicPartitionsList(TopicPartition topicPartition) {Object topic = resolveExpression(topicPartition.topic());Assert.state(topic instanceof String,'topic in @TopicPartition must resolve to a String, not ' + topic.getClass());Assert.state(StringUtils.hasText((String) topic), 'topic in @TopicPartition must not be empty');String[] partitions = topicPartition.partitions();PartitionOffset[] partitionOffsets = topicPartition.partitionOffsets();Assert.state(partitions.length > 0 || partitionOffsets.length > 0,'At least one ’partition’ or ’partitionOffset’ required in @TopicPartition for topic ’' + topic + '’');List<TopicPartitionInitialOffset> result = new ArrayList<>();for (int i = 0; i < partitions.length; i++) { resolvePartitionAsInteger((String) topic, resolveExpression(partitions[i]), result);} for (PartitionOffset partitionOffset : partitionOffsets) { Object partitionValue = resolveExpression(partitionOffset.partition()); Integer partition; if (partitionValue instanceof String) {Assert.state(StringUtils.hasText((String) partitionValue),'partition in @PartitionOffset for topic ’' + topic + '’ cannot be empty');partition = Integer.valueOf((String) partitionValue); } else if (partitionValue instanceof Integer) {partition = (Integer) partitionValue; } else {throw new IllegalArgumentException(String.format('@PartitionOffset for topic ’%s’ can’t resolve ’%s’ as an Integer or String, resolved to ’%s’',topic, partitionOffset.partition(), partitionValue.getClass())); } Object initialOffsetValue = resolveExpression(partitionOffset.initialOffset()); Long initialOffset; if (initialOffsetValue instanceof String) {Assert.state(StringUtils.hasText((String) initialOffsetValue),'’initialOffset’ in @PartitionOffset for topic ’' + topic + '’ cannot be empty');initialOffset = Long.valueOf((String) initialOffsetValue); } else if (initialOffsetValue instanceof Long) {initialOffset = (Long) initialOffsetValue; } else {throw new IllegalArgumentException(String.format('@PartitionOffset for topic ’%s’ can’t resolve ’%s’ as a Long or String, resolved to ’%s’',topic, partitionOffset.initialOffset(), initialOffsetValue.getClass())); } Object relativeToCurrentValue = resolveExpression(partitionOffset.relativeToCurrent()); Boolean relativeToCurrent; if (relativeToCurrentValue instanceof String) {relativeToCurrent = Boolean.valueOf((String) relativeToCurrentValue); } else if (relativeToCurrentValue instanceof Boolean) {relativeToCurrent = (Boolean) relativeToCurrentValue; } else {throw new IllegalArgumentException(String.format('@PartitionOffset for topic ’%s’ can’t resolve ’%s’ as a Boolean or String, resolved to ’%s’',topic, partitionOffset.relativeToCurrent(), relativeToCurrentValue.getClass())); } TopicPartitionInitialOffset topicPartitionOffset = new TopicPartitionInitialOffset((String) topic, partition, initialOffset, relativeToCurrent); if (!result.contains(topicPartitionOffset)) {result.add(topicPartitionOffset); } else {throw new IllegalArgumentException(String.format('@TopicPartition can’t have the same partition configuration twice: [%s]',topicPartitionOffset)); }}return result; } private void resolvePartitionAsInteger(String topic, Object resolvedValue, List<TopicPartitionInitialOffset> result) {if (resolvedValue instanceof String[]) { for (Object object : (String[]) resolvedValue) {resolvePartitionAsInteger(topic, object, result); }}else if (resolvedValue instanceof String) { Assert.state(StringUtils.hasText((String) resolvedValue), 'partition in @TopicPartition for topic ’' + topic + '’ cannot be empty'); result.add(new TopicPartitionInitialOffset(topic, Integer.valueOf((String) resolvedValue)));}else if (resolvedValue instanceof Integer[]) { for (Integer partition : (Integer[]) resolvedValue) {result.add(new TopicPartitionInitialOffset(topic, partition)); }}else if (resolvedValue instanceof Integer) { result.add(new TopicPartitionInitialOffset(topic, (Integer) resolvedValue));}else if (resolvedValue instanceof Iterable) { for (Object object : (Iterable<Object>) resolvedValue) {resolvePartitionAsInteger(topic, object, result); }}else { throw new IllegalArgumentException(String.format( '@DelayKafkaConsumer for topic ’%s’ can’t resolve ’%s’ as an Integer or String', topic, resolvedValue));} } private Set<DelayKafkaConsumer> findListenerAnnotations(Method method) {Set<DelayKafkaConsumer> listeners = new HashSet<>();DelayKafkaConsumer ann = AnnotationUtils.findAnnotation(method, DelayKafkaConsumer.class);if (ann != null) { listeners.add(ann);}return listeners; } private Method checkProxy(Method methodArg, Object bean) {Method method = methodArg;if (AopUtils.isJdkDynamicProxy(bean)) { try {method = bean.getClass().getMethod(method.getName(), method.getParameterTypes());Class<?>[] proxiedInterfaces = ((Advised) bean).getProxiedInterfaces();for (Class<?> iface : proxiedInterfaces) { try {method = iface.getMethod(method.getName(), method.getParameterTypes());break; } catch (NoSuchMethodException noMethod) { }} } catch (SecurityException ex) {ReflectionUtils.handleReflectionException(ex); } catch (NoSuchMethodException ex) {throw new IllegalStateException(String.format('target method ’%s’ found on bean target class ’%s’, ' +'but not found in any interface(s) for bean JDK proxy. Either ' +'pull the method up to an interface or switch to subclass (CGLIB) ' +'proxies by setting proxy-target-class/proxyTargetClass ' +'attribute to ’true’', method.getName(), method.getDeclaringClass().getSimpleName()), ex); }}return method; } @Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException {this.beanFactory = beanFactory;if (beanFactory instanceof ConfigurableListableBeanFactory) { this.resolver = ((ConfigurableListableBeanFactory) beanFactory).getBeanExpressionResolver(); this.expressionContext = new BeanExpressionContext((ConfigurableListableBeanFactory) beanFactory, this.listenerScope);} } private String resolveExpressionAsString(String value, String attribute) {Object resolved = resolveExpression(value);if (resolved instanceof String) { return (String) resolved;}else { throw new IllegalStateException('The [' + attribute + '] must resolve to a String. ' + 'Resolved to [' + resolved.getClass() + '] for [' + value + ']');} } private Object resolveExpression(String value) {String resolvedValue = resolve(value);return this.resolver.evaluate(resolvedValue, this.expressionContext); } /** * Resolve the specified value if possible. * @param value the value to resolve * @return the resolved value * @see ConfigurableBeanFactory#resolveEmbeddedValue */ private String resolve(String value) {if (this.beanFactory instanceof ConfigurableBeanFactory) { return ((ConfigurableBeanFactory) this.beanFactory).resolveEmbeddedValue(value);}return value; } private void addFormatters(FormatterRegistry registry) {for (Converter<?, ?> converter : getBeansOfType(Converter.class)) { registry.addConverter(converter);}for (GenericConverter converter : getBeansOfType(GenericConverter.class)) { registry.addConverter(converter);}for (org.springframework.format.Formatter<?> formatter : getBeansOfType(Formatter.class)) { registry.addFormatter(formatter);} } private <T> Collection<T> getBeansOfType(Class<T> type) {if (this.beanFactory instanceof ListableBeanFactory) { return ((ListableBeanFactory) this.beanFactory).getBeansOfType(type).values();}else { return Collections.emptySet();} } private static class ListenerScope implements Scope { private final Map<String, Object> listeners = new HashMap<>(); ListenerScope() { super();} public void addListener(String key, Object bean) { this.listeners.put(key, bean);} public void removeListener(String key) { this.listeners.remove(key);} @Overridepublic Object get(String name, ObjectFactory<?> objectFactory) { return this.listeners.get(name);} @Overridepublic Object remove(String name) { return null;} @Overridepublic void registerDestructionCallback(String name, Runnable callback) {} @Overridepublic Object resolveContextualObject(String key) { return this.listeners.get(key);} @Overridepublic String getConversationId() { return null;} } private class KafkaHandlerMethodFactoryAdapter implements MessageHandlerMethodFactory { private final DefaultFormattingConversionService defaultFormattingConversionService = new DefaultFormattingConversionService(); private MessageHandlerMethodFactory messageHandlerMethodFactory; public void setMessageHandlerMethodFactory(MessageHandlerMethodFactory kafkaHandlerMethodFactory1) { this.messageHandlerMethodFactory = kafkaHandlerMethodFactory1;} @Overridepublic InvocableHandlerMethod createInvocableHandlerMethod(Object bean, Method method) { return getMessageHandlerMethodFactory().createInvocableHandlerMethod(bean, method);} private MessageHandlerMethodFactory getMessageHandlerMethodFactory() { if (this.messageHandlerMethodFactory == null) {this.messageHandlerMethodFactory = createDefaultMessageHandlerMethodFactory(); } return this.messageHandlerMethodFactory;} private MessageHandlerMethodFactory createDefaultMessageHandlerMethodFactory() { DefaultMessageHandlerMethodFactory defaultFactory = new DefaultMessageHandlerMethodFactory(); defaultFactory.setBeanFactory(MyKafkaConsumerFactory.this.beanFactory); ConfigurableBeanFactory cbf = (MyKafkaConsumerFactory.this.beanFactory instanceof ConfigurableBeanFactory ? (ConfigurableBeanFactory) MyKafkaConsumerFactory.this.beanFactory : null); defaultFactory.setConversionService(this.defaultFormattingConversionService); List<HandlerMethodArgumentResolver> argumentResolvers = new ArrayList<>(); // Annotation-based argument resolution argumentResolvers.add(new HeaderMethodArgumentResolver(this.defaultFormattingConversionService, cbf)); argumentResolvers.add(new HeadersMethodArgumentResolver()); // Type-based argument resolution final GenericMessageConverter messageConverter = new GenericMessageConverter(this.defaultFormattingConversionService); argumentResolvers.add(new MessageMethodArgumentResolver(messageConverter)); argumentResolvers.add(new PayloadArgumentResolver(messageConverter) { @Overrideprotected boolean isEmptyPayload(Object payload) { return payload == null || payload instanceof KafkaNull;} }); defaultFactory.setArgumentResolvers(argumentResolvers); defaultFactory.afterPropertiesSet(); return defaultFactory;} }}

通過startConsumer來啟動一個消費者(多次調用會啟動多個消費者)。target必須至少包含一個有@DelayKafkaConsumer注解的方法。這里類似@KafkaListener。我去掉了一部分功能,保留了比較常用的部分。

這里提供了一個通過注解的方式在spring boot項目中動態控制consumer的方法。還有其他的方法來達到這種效果,不過我覺得這種方法比較方便。

java項目集成springboot使用kafka消費者,啟動失敗報錯 Failed to construct kafka consumer

之前博客里面提到本公司為物聯網項目。項目中使用mqtt+kafka進行與設備端的通訊,之前的協議格式為json格式,現在改成字節數組byte[]格式進行通信。

集成springboot后,具體的demo網上很多,接下來有時間會出一份kafka的demo。

報錯信息如下:

Failed to start bean ’org.springframework.kafka.config.internalKafkaListenerEndpointRegistry’; nested exception is org.apache.kafka.common.KafkaException:Failed to construct kafka consumer

原因分析:

之前json格式通信時候,構建kafka消費工廠的時候,其中ConcurrentMessageListenerContainer的key為String類型,而value現在為byte[]類型,所以構建消費者工廠的時候需要指定正確的value類型。

代碼如下:

public KafkaListenerContainerFactory<ConcurrentMessageListenerContainer<String, byte[]>> kafkaListenerContainerByteFactory() { ConcurrentKafkaListenerContainerFactory<String, byte[]> factory = new ConcurrentKafkaListenerContainerFactory<String, byte[]>(); factory.setConsumerFactory(consumerByteFactory()); factory.setConcurrency(concurrency); factory.getContainerProperties().setPollTimeout(1500); return factory; }

整體kafka生產者+kafka消費者的demo會在接下來的博客中陸續整理。

以上為個人經驗,希望能給大家一個參考,也希望大家多多支持好吧啦網。

標簽: Spring
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
蜜桃一区二区三区在线| 亚洲啊v在线免费视频| 亚洲一区免费| 欧美.日韩.国产.一区.二区 | 九色精品91| 国产午夜精品一区在线观看| 麻豆久久久久久| 欧美综合社区国产| 水蜜桃久久夜色精品一区| 在线精品国产亚洲| 妖精视频成人观看www| 国产一区二区三区探花| 日本成人在线视频网站| 日韩国产在线观看一区| 欧美日韩精品免费观看视完整| 精品视频高潮| 7777精品| 米奇777超碰欧美日韩亚洲| 日本 国产 欧美色综合| 日本中文字幕视频一区| 国产夫妻在线| 国产日韩在线观看视频| 捆绑调教美女网站视频一区 | 福利在线一区| 亚洲大片在线| 欧美日韩国产一区二区三区不卡| 亚洲午夜黄色| 国产精品免费不| 久久国产生活片100| 麻豆一区二区三| 久久av中文| 欧美日韩国产欧| 捆绑调教日本一区二区三区| 日韩一区二区三区在线免费观看| 日本v片在线高清不卡在线观看| 亚洲v天堂v手机在线| 91亚洲国产成人久久精品| 捆绑调教美女网站视频一区| 国产精品xxx| 电影91久久久| 久久久人人人| 麻豆成人在线观看| 日本aⅴ亚洲精品中文乱码| 在线一区欧美| 国产在线成人| 快播电影网址老女人久久| 国产精品久久久久久av公交车| 天堂av在线一区| 中文字幕在线视频久| 亚洲精品影视| 亚洲深夜av| 欧美在线资源| 色综合www| 久久xxx视频| 亚洲一区二区三区免费在线观看| 欧美精品九九| 福利一区和二区| 欧美久久亚洲| 日韩一区二区三区精品视频第3页| 久久国产精品成人免费观看的软件| 久久亚洲精精品中文字幕| 日韩精品久久久久久| 日韩在线观看一区二区| 一区免费视频| 五月婷婷亚洲| 欧美成人日韩| 欧美成人精品| 欧美精品一二| 99国产成+人+综合+亚洲欧美| 欧美日韩视频网站| 国产精品高颜值在线观看| 精品国产精品久久一区免费式 | 在线中文字幕播放| 久久香蕉网站| 日本一区二区高清不卡| 久久精品欧洲| 国产成人1区| av在线最新| 韩国精品主播一区二区在线观看| 97精品视频在线看| 精品欧美一区二区三区在线观看| 日韩一区三区| 久久国产欧美| 中文日韩在线| 无码日韩精品一区二区免费| 日韩成人一级| 欧美一级一区| 欧美另类中文字幕| 欧美一区精品| 国产欧美另类| 久久亚洲国产精品尤物| 成人亚洲一区| 久久久精品网| 婷婷成人基地| 久久婷婷激情| 免费看欧美美女黄的网站| 亚洲精品黄色| 国产精品一区二区免费福利视频| 国产精品久久777777毛茸茸| 久久精品国产精品亚洲毛片| 日韩二区三区四区| 你懂的国产精品永久在线| 国产一区国产二区国产三区| 欧美不卡高清一区二区三区| 91精品观看| 日本一区中文字幕| 久久精品一本| 亚洲一级网站| 国产一区二区三区四区二区| 免费在线亚洲欧美| 亚洲一区二区毛片| 国产一区三区在线播放| 亚洲小说春色综合另类电影| 久久福利影视| 久久免费黄色| 99视频精品全部免费在线视频| 日韩欧美一区二区三区在线视频| 日韩中出av| 精品国产一区二区三区av片| 久久九九精品| 亚洲另类av| 国产不卡人人| 免费看的黄色欧美网站| 超碰在线99| 国产精品一区高清| 热久久久久久久| 99久久精品国产亚洲精品| 不卡中文字幕| 欧美在线观看天堂一区二区三区| 亚洲美女久久精品| 蜜臀av性久久久久蜜臀aⅴ流畅 | 久久亚洲精精品中文字幕| 麻豆国产精品777777在线| 国产精品magnet| 久久激情婷婷| 日韩三级精品| 久久免费黄色| 国产剧情一区二区在线观看| 久久久久网站| 日韩视频1区| 亚洲欧洲美洲av| 日韩中文字幕| 亚洲一级影院| 久久精品国内一区二区三区| 免费日韩av| 在线手机中文字幕| 日韩av网站在线免费观看| 久久高清免费| 久久精品国产网站| 日本一区二区三区视频在线看| 欧美精品资源| 国产精品一区高清| 日韩在线播放一区二区| 亚洲成av在线| 欧美aa在线视频| 亚洲综合婷婷| 亚洲免费高清| 午夜欧美精品| 欧美日韩精品免费观看视频完整| 四虎4545www国产精品| 精品国产三区在线| 国产极品久久久久久久久波多结野| 成人国产综合| 欧美一区自拍| 免费日本视频一区| 久久中文字幕av| 综合一区在线| av中文字幕在线观看第一页| 精品国产精品久久一区免费式 | 日韩中文字幕区一区有砖一区 | 美女精品视频在线| 国产探花一区| 国产精品99精品一区二区三区∴ | 久久激情综合网| 视频在线在亚洲| 91成人在线精品视频| 亚洲无线观看| 久久五月天小说| 国产suv精品一区二区四区视频 | 青草综合视频| 亚洲a级精品| 亚洲乱码久久| 7777精品| 美女精品久久| a天堂资源在线| 精品捆绑调教一区二区三区| 久久久国产精品一区二区中文| 久久久夜夜夜| 六月天综合网| 久久毛片亚洲| 日本亚洲欧洲无免费码在线| 亚洲综合不卡| 国产精品女主播一区二区三区| 国产在线成人| 欧美日韩免费观看一区=区三区| 欧美亚洲国产激情| 国产精品亚洲综合在线观看| 国产精品主播| 麻豆精品少妇| 久久精品国产网站|