日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

微服务秒杀项目整合网关+feign+redis分离热点商品分别下单示例

發布時間:2024/9/30 编程问答 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 微服务秒杀项目整合网关+feign+redis分离热点商品分别下单示例 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • 配置文件和通用文件
    • 通用結果類型:
    • 返回碼:
    • 統一異常處理:
    • 網關
    • feign服務
  • redission配置
  • controller
  • service:熱點商品和普通商品分開下單
  • 消息隊列監聽訂單


思路:對于普通商品進行正常下單(直接減去數據庫中的庫存然后生成訂單,對于熱點數據加一層redis緩存層,商品放在redis中,用分布式鎖加鎖,然后可以放入消息隊列中排隊下單,下單時先檢查Redis中庫存量是否足夠,成功了才減去數據庫庫存)
在這里還使用了feign用來遠程調用服務和網關攔截請求。

下面是代碼:/

配置文件和通用文件

@Configuration public class RedisConfig {/**** 模板操作對象序列化設置* @param redissonConnectionFactory* @return*/@Bean("redisTemplate")public RedisTemplate getRedisTemplate(RedisConnectionFactory redissonConnectionFactory) {RedisTemplate<Object, Object> redisTemplate = new RedisTemplate();redisTemplate.setConnectionFactory(redissonConnectionFactory);redisTemplate.setValueSerializer(valueSerializer());redisTemplate.setKeySerializer(keySerializer());redisTemplate.setHashKeySerializer(keySerializer());redisTemplate.setHashValueSerializer(valueSerializer());return redisTemplate;}/***** 序列化設置* @return*/@Beanpublic StringRedisSerializer keySerializer() {return new StringRedisSerializer();}/***** 序列化設置* @return*/@Beanpublic RedisSerializer valueSerializer() {Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);ObjectMapper objectMapper = new ObjectMapper();objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);jackson2JsonRedisSerializer.setObjectMapper(objectMapper);return jackson2JsonRedisSerializer;} }

通用結果類型:

@ApiModel(description = "Result",value = "Result") public class Result<T> {@ApiModelProperty(value="執行是否成功,true:成功,false:失敗",required = true)private boolean flag;//是否成功@ApiModelProperty(value="返回狀態碼,20000:成功,20001:失敗,20002:用戶名或密碼錯誤,20003:權限不足,20004:遠程調用失敗,20005:重復操作,20006:沒有對應的數據",required = true)private Integer code;//返回碼@ApiModelProperty(value="提示信息",required = true)private String message;//返回消息@ApiModelProperty(value="邏輯數據",required = true)private T data;//返回數據public Result(boolean flag, Integer code, String message, Object data) {this.flag = flag;this.code = code;this.message = message;this.data = (T) data;}public Result(boolean flag, Integer code, String message) {this.flag = flag;this.code = code;this.message = message;}public Result() {this.flag = true;this.code = StatusCode.OK;this.message = "操作成功!";}

返回碼:

/*** 返回碼*/ public class StatusCode {public static final int OK = 20000;//成功public static final int ERROR = 20001;//失敗public static final int LOGINERROR = 20002;//用戶名或密碼錯誤public static final int ACCESSERROR = 20003;//權限不足public static final int REMOTEERROR = 20004;//遠程調用失敗public static final int REPERROR = 20005;//重復操作public static final int NOTFOUNDERROR = 20006;//沒有對應的搶購數據//庫存遞減狀態碼public static final int DECOUNT_1=1; //遞減成功public static final int DECOUNT_NUM=405;//庫存不足public static final int DECOUNT_HOT=205;//商品是熱賣商品public static final int DECOUNT_OK=200;//庫存遞減成功public static final int ORDER_QUEUE=202;//搶購商品正在排隊public static final int ORDER_OK=200;//搶單成功//令牌無效public static final int TOKEN_ERROR=401; }

統一異常處理:

@ControllerAdvice //所有請求路徑,都將被該類處理->過濾器/(攔截器) public class BaseExceptionHandler {private static Logger logger = LoggerFactory.getLogger(BaseExceptionHandler.class);/**** 異常處理* 當前請求發生了指定異常,則執行該方法處理異常*/@ExceptionHandler(Exception.class)@ResponseBodypublic Result error(Exception ex){StringWriter stringWriter = new StringWriter();PrintWriter writer = new PrintWriter(stringWriter);ex.printStackTrace(writer);ex.printStackTrace();logger.error(stringWriter.toString());return new Result(false, StatusCode.ERROR,ex.getMessage(),stringWriter.toString());} }

網關

server:port: 8001 spring:application:name: gateway-webcloud:nacos:config:file-extension: yamlserver-addr: nacos-server:8848discovery:#Nacos的注冊地址server-addr: nacos-server:8848gateway:routes:#商品- id: goods_routeuri: lb://seckill-goodspredicates:- Path=/api/skuAct/**,/api/activity/**,/api/brand/**,/api/category/**,/api/seckillTime/**,/api/sku/**filters:- StripPrefix=1#訂單- id: order_routeuri: lb://seckill-orderpredicates:- Path=/api/order/**filters:- StripPrefix=1#搜索- id: search_routeuri: lb://seckill-searchpredicates:- Path=/api/search/**filters:- StripPrefix=1#用戶- id: user_routeuri: lb://seckill-userpredicates:- Path=/api/user/**filters:- StripPrefix=1#管理員- id: manager_routeuri: lb://seckill-managerpredicates:- Path=/api/admin/**filters:- StripPrefix=1#靜態頁- id: page_routeuri: lb://seckill-pagepredicates:- Path=/api/page/**filters:- StripPrefix=1

網關攔截設置:

@Component public class AuthorizeFilter implements GlobalFilter,Ordered {//令牌頭名字private static final String AUTHORIZE_TOKEN = "Authorization";private static final String ADMINAUTHORIZE_TOKEN = "Admin-Token-Itheima";/**** 過濾攔截* @param exchange* @param chain* @return*/@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {//獲取request和responseServerHttpRequest request = exchange.getRequest();ServerHttpResponse response = exchange.getResponse();//獲取用戶請求的地址String path = request.getURI().getPath();// /api/user/login放行///api/order/add 測試放行if(path.equals("/api/user/login") || path.equals("/api/admin/login") || path.equals("/api/search") || path.equals("/api/activity/times")){//放行return chain.filter(exchange);}HttpMethod method = request.getMethod();System.out.println(method.name());// /sku/xxx GET方式允許通過if(path.startsWith("/api/sku/") && request.getMethod().name().equalsIgnoreCase("GET")){//放行return chain.filter(exchange);}//獲取用戶請求頭中的令牌String token = request.getHeaders().getFirst(AUTHORIZE_TOKEN); //獲取請求頭中第1個Authorization參數//如果請求頭中沒有令牌,則有可能用的是參數傳入的if(StringUtils.isEmpty(token)){token = request.getQueryParams().getFirst(AUTHORIZE_TOKEN);//獲取請求參數中第1個Authorization}//如果請求頭和參數中都沒有令牌,則直接拒絕用戶訪問各大微服務if(StringUtils.isEmpty(token)){//從Cookie中獲取令牌數據HttpCookie cookie = request.getCookies().getFirst(AUTHORIZE_TOKEN);HttpCookie adminCookie = request.getCookies().getFirst(ADMINAUTHORIZE_TOKEN);if(cookie==null && adminCookie==null){//狀態嗎 401response.setStatusCode(HttpStatus.UNAUTHORIZED);//結束當前請求return response.setComplete();}//獲取令牌if(cookie!=null){token = cookie.getValue();}else{token = adminCookie.getValue();}//將令牌封裝到請求頭中request.mutate().header(AUTHORIZE_TOKEN,"bearer "+token);}return chain.filter(exchange);}/**** 排序* @return*/@Overridepublic int getOrder() {return 0;}@Beanpublic CorsWebFilter corsFilter() {CorsConfiguration config = new CorsConfiguration();// cookie跨域config.setAllowCredentials(Boolean.TRUE); //允許Cookie跨域config.addAllowedMethod("*"); //所有提交方法都允許跨域config.addAllowedOrigin("*"); //所有的域名都允許跨域config.addAllowedHeader("*");//跨域解析器UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(new PathPatternParser());source.registerCorsConfiguration("/**", config); //所有請求路徑都支持跨域return new CorsWebFilter(source);} }

feign服務

下面是庫存的接口:

@FeignClient(value = "seckill-goods") public interface SkuFeign {/***** 庫存遞減*/@PutMapping(value = "/sku/dcount/{id}/{count}")Result<Sku> dcount(@PathVariable(value = "id")String id,@PathVariable(value = "count")Integer count);/**** 熱點商品隔離*/@PostMapping(value = "/sku/hot/isolation")Result hotIsolation(@RequestParam List<String> ids);/***** 分頁查詢-查詢總數量*/@GetMapping(value = "/sku/count")Integer count();/***** 分頁查詢集合列表*/@GetMapping(value = "/sku/list/{page}/{size}")List<Sku> list(@PathVariable(value = "page")Integer page,@PathVariable(value = "size")Integer size);/**** 根據ID查詢Sku數據* @param id* @return*/@GetMapping("/sku/{id}")Result<Sku> findById(@PathVariable String id);/**** 商品數據歸0*/@GetMapping(value = "/sku/zero/{id}")Result zero(@PathVariable(value = "id") String id); }

消息通知的接口:

@FeignClient(value = "seckill-message") public interface MessageFeign {/***** 發送消息*/@GetMapping(value = "/message/{userid}")String send(@PathVariable(value = "userid")String userid,@RequestParam(value = "msg") String msg) throws IOException; }

redission配置

多個用戶實現加鎖操作,只允許有一個用戶可以獲取到對應鎖

@Component public class RedissonDistributedLocker implements DistributedLocker {@Autowiredprivate RedissonClient redissonClient;/**** 加鎖,會一直循環加鎖,直到拿到鎖* @param lockkey* @return*/@Overridepublic RLock lock(String lockkey) {RLock lock = redissonClient.getLock(lockkey);lock.lock();return lock;}/**** 加鎖,在指定時間內拿不到鎖就會放棄* @param lockkey* @return*/@Overridepublic RLock lock(String lockkey, long timeout) {RLock lock = redissonClient.getLock(lockkey);lock.lock(timeout,TimeUnit.SECONDS);return lock;}/**** 加鎖,在指定時間內拿不到鎖就會放棄* @param lockkey* @return*/@Overridepublic RLock lock(String lockkey, long timeout, TimeUnit unit) {return null;}/**** 加鎖,在指定時間內拿不到鎖就會放棄,如果拿到鎖,鎖最終有效時間為leasetime* @param lockkey* @return*/@Overridepublic boolean tryLock(String lockkey, long timeout, long leasetime, TimeUnit unit) {return false;}/***** 解鎖* @param lockkey*/@Overridepublic void unLock(String lockkey) {RLock lock = redissonClient.getLock(lockkey);lock.unlock();}/**** 解鎖* @param lock*/@Overridepublic void unLocke(RLock lock) {lock.unlock();} }

controller

商品SkuController

@RestController @RequestMapping("/sku")public class SkuController {@Autowiredprivate SkuService skuService; /***** 庫存遞減*/@PutMapping(value = "/dcount/{id}/{count}")public Result<Sku> dcount(@PathVariable(value = "id")String id,@PathVariable(value = "count")Integer count){//1.調用業務層實現遞減int code = skuService.dcount(id, count);String message="";Sku sku = null;switch (code){case StatusCode.DECOUNT_OK:sku = skuService.findById(id);message="庫存遞減成功!";break;case StatusCode.DECOUNT_NUM:message="庫存不足!";break;case StatusCode.DECOUNT_HOT:message="商品是熱點商品!";break;default:}//3.根據狀態碼,響應不同的提示信息return new Result<Sku>(true,code,message,sku);}/**** 熱點商品隔離*/@PostMapping(value = "/hot/isolation")public Result hotIsolation(@RequestParam List<String> ids){for (String id : ids) {skuService.hotIsolation(id);}return new Result(true,StatusCode.OK,"熱點數據隔離成功!");}

訂單OrderController:

@RestController @RequestMapping("/order") //@CrossOrigin public class OrderController {@Autowiredprivate OrderService orderService;@Autowiredprivate IdWorker idWorker;/***** 添加訂單*/@PostMapping(value = "/add/{id}")public Result add(@PathVariable(value = "id") String id, @RequestHeader(value = "Authorization") String authorization) {String username = null;try {//解析令牌Map<String, Object> tokenMap = JwtTokenUtil.parseToken(authorization);username =tokenMap.get("username").toString();} catch (Exception e) {return new Result(false, StatusCode.TOKEN_ERROR, "令牌無效!");}//封裝OrderOrder order = new Order();order.setId("No"+idWorker.nextId());order.setSkuId(id);order.setCreateTime(new Date());order.setUpdateTime(order.getCreateTime());order.setUsername(username);order.setTotalNum(1);//添加訂單int code = orderService.add(order);switch (code) {case StatusCode.ORDER_OK:return new Result(true, StatusCode.ORDER_OK, order.getId());case StatusCode.DECOUNT_NUM:return new Result(false, StatusCode.DECOUNT_NUM, "庫存不足!");case StatusCode.ORDER_QUEUE:return new Result(true, StatusCode.ORDER_QUEUE, "排隊搶購中!");default:return new Result(false, StatusCode.ERROR, "搶單發生異常!");}}/**** Order分頁條件搜索實現* @param page* @param size* @return*/@PostMapping(value = "/search/{page}/{size}")public Result<PageInfo> findPage(@RequestBody(required = false) OrderVo orderVo, @PathVariable int page, @PathVariable int size) {//調用OrderService實現分頁條件查詢OrderOrder order = new Order();BeanUtils.copyProperties(orderVo,order);PageInfo<Order> pageInfo = orderService.findPage(order, page, size);return new Result(true, StatusCode.OK, "查詢成功", pageInfo);}/**** 用戶訂單* @param page* @param size* @return*/@GetMapping(value = "/user/{page}/{size}")public Result<PageInfo> userOrders(@PathVariable int page,@PathVariable int size,@RequestParam(value = "type",defaultValue = "0")Integer type,@RequestHeader("Authorization")String authorization) {Map<String, Object> userMap = JwtTokenUtil.parseToken(authorization);//調用OrderService實現分頁條件查詢OrderOrder order = new Order();order.setUsername(userMap.get("username").toString());switch (type){case 1:order.setPayStatus("0");break;case 3:order.setPayStatus("1");break;}PageInfo<Order> pageInfo = orderService.findPage(order, page, size);return new Result(true, StatusCode.OK, "查詢成功", pageInfo);}}

service:熱點商品和普通商品分開下單

這里用了druid工具進行熱點數據監控:

@Component public class MonitorItemsAccess {@Value("${druidurl}")private String druidurl;@Autowiredprivate RedisTemplate redisTemplate;@Autowiredprivate DruidDataSource dataSource;/******* 定義熱點數據標準:* 1.某一件商品訪問量>N* 2.最近N小時*/public List<String> loadData() throws Exception{//獲取連接對象//Connection connection = (AvaticaConnection) DriverManager.getConnection(druidurl);Connection connection =dataSource.getConnection();//StatementStatement statement = connection.createStatement();//執行查詢ResultSet resultSet = statement.executeQuery(druidSQL());//解析結果集List<String> ids = new ArrayList<String>();while (resultSet.next()){String uri = resultSet.getString("uri");uri=uri.replace("/web/items/","").replace(".html","");ids.add(uri);}//關閉資源resultSet.close();statement.close();connection.close();return ids;}/**** SQL組裝* @return*/public String druidSQL(){//SQL語句String prefix="SELECT COUNT(*) AS \"viewCount\",uri FROM logsitems WHERE __time>=CURRENT_TIMESTAMP - INTERVAL '1' HOUR";//后部分String suffix=" GROUP BY uri HAVING viewCount>2";//SQL中間部分 AND uri NOT IN ('/web/items/S1235433012716498944.html')//SKU_S1235433012716498944String sql = "";//基于Redis中存的熱點商品的key來過濾排除要查詢的數據Set<String> keys = redisTemplate.keys("SKU_*");//所有以SKU_開始的key全部查詢出來if(keys!=null && keys.size()>0){sql=" AND uri NOT IN (";for (String key : keys) {sql+="'/web/items/"+key.substring(4)+".html',";}sql=sql.substring(0,sql.length()-1);sql+=")";}return prefix+sql+suffix;} }

然后用定時任務組件來執行上面的監控方法,設置每隔多久執行一次,這里用的是elasticjob第三方工具,實際當中可以用其他的定時任務框架

import com.dangdang.ddframe.job.api.ShardingContext; import com.dangdang.ddframe.job.api.simple.SimpleJob; import com.dangdang.elasticjob.lite.annotation.ElasticSimpleJob; import com.seckill.goods.feign.SkuFeign; import lombok.SneakyThrows; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component;import java.util.List; @Component @ElasticSimpleJob(//這是elasticjob工具的定時任務注解cron = "1/5 * * * * ?",jobName = "monitortask",shardingTotalCount = 1 ) public class MonitorTask implements SimpleJob{@Autowiredprivate MonitorItemsAccess monitorItemsAccess;@Autowiredprivate SkuFeign skuFeign;/**** 執行業務邏輯* @param shardingContext*/@SneakyThrows@Overridepublic void execute(ShardingContext shardingContext) {List<String> ids = monitorItemsAccess.loadData();for (String id : ids) {System.out.println("熱點商品ID:"+id);}//熱點數據隔離skuFeign.hotIsolation(ids);} }

訂單Service

@Service public class OrderServiceImpl implements OrderService {@Autowiredprivate OrderMapper orderMapper;@Autowiredprivate SkuFeign skuFeign;@Autowiredprivate IdWorker idWorker;@Autowiredprivate RedisTemplate redisTemplate;@Autowiredprivate KafkaTemplate kafkaTemplate;@Autowiredprivate RedissonDistributedLocker redissonDistributedLocker;@Autowiredprivate MessageFeign messageFeign;/***** 熱點商品下單* @param orderMap* @return*/@Overridepublic void hotAdd(Map<String, String> orderMap) throws IOException {//消息封裝對象Map<String,Object> messageMap = new HashMap<String,Object>();String username = orderMap.get("username");String id = orderMap.get("id");//Redis中對應的keyString key="SKU_"+id;String lockkey="LOCKSKU_"+id;String userKey="USER"+username+"ID"+id;//如果key在redis緩存,則表示商品信息在Redis中進行操作boolean bo =true;// redissonDistributedLocker.tryLock(lockkey, 10, 10, TimeUnit.MINUTES);if(bo){if(redisTemplate.hasKey(key)){//獲取商品數量Integer num = Integer.parseInt(redisTemplate.boundHashOps(key).get("num").toString());if(num<=0){//商品售罄通知messageMap.put("code",20001);messageMap.put("message","商品已售罄");messageFeign.send(username,JSON.toJSONString(messageMap));return;}Result<Sku> skuResult =skuFeign.findById(id);Sku sku = skuResult.getData();//1.創建OrderOrder order = new Order();order.setTotalNum(1);order.setCreateTime(new Date());order.setUpdateTime(order.getCreateTime());order.setId("No"+idWorker.nextId());order.setOrderStatus("0");order.setPayStatus("0");order.setConsignStatus("0");order.setSkuId(id);order.setName(sku.getName());order.setPrice(sku.getSeckillPrice()*order.getTotalNum());orderMapper.insertSelective(order);//2.Redis中對應的num遞減num--;if(num==0){skuFeign.zero(id);}//2.清理用戶排隊信息Map<String,Object> allMap = new HashMap<String,Object>();allMap.put(userKey,0);allMap.put("num",num);redisTemplate.boundHashOps(key).putAll(allMap);//3.記錄用戶購買過該商品,24小時后過期redisTemplate.boundValueOps(userKey).set("");redisTemplate.expire(userKey,1,TimeUnit.MINUTES);//搶單成功通知messageMap.put("code",200);messageMap.put("message","搶單成功!");messageFeign.send(username,JSON.toJSONString(messageMap));}//釋放鎖//redissonDistributedLocker.unLock(lockkey);return;}//搶單失敗通知messageMap.put("code",20001);messageMap.put("message","搶單失敗!");messageFeign.send(username,JSON.toJSONString(messageMap));}/**** 添加訂單* @param order* @return*/@GlobalTransactional@Overridepublic int add(Order order) {String userKey="USER"+order.getUsername()+"ID"+order.getSkuId();//1.遞減庫存Result<Sku> dcount = skuFeign.dcount(order.getSkuId(), order.getTotalNum());//2.遞減成功->下單->記錄當前用戶搶單的時間點,24小時內不能搶購該商品if(dcount.getCode()== StatusCode.DECOUNT_OK){//int q=10/0;Sku sku = dcount.getData();//下單//order.setId("No"+idWorker.nextId());order.setOrderStatus("0");order.setPayStatus("0");order.setConsignStatus("0");order.setSkuId(sku.getId());order.setName(sku.getName());order.setPrice(sku.getSeckillPrice()*order.getTotalNum());orderMapper.insertSelective(order);//記錄當前用戶搶單的時間點,24小時內不能搶購該商品redisTemplate.boundValueOps(userKey).set("");redisTemplate.boundValueOps(userKey).expire(1, TimeUnit.MINUTES);return StatusCode.ORDER_OK;}else{//3.遞減失敗//405庫存不足if(dcount.getCode()==StatusCode.DECOUNT_NUM){return StatusCode.DECOUNT_NUM;}else if(dcount.getCode()==StatusCode.DECOUNT_HOT){//205商品熱點String key = "SKU_"+order.getSkuId();Long increment = redisTemplate.boundHashOps(key).increment(userKey, 1);if(increment==1){//執行排隊Map<String,String> queueMap = new HashMap<String,String>();queueMap.put("username",order.getUsername());queueMap.put("id",order.getSkuId());kafkaTemplate.send("neworder", JSON.toJSONString(queueMap));}return StatusCode.ORDER_QUEUE;}//0return dcount.getCode();} }

消息隊列監聽訂單

@Component public class RabbitOrderListener {@Autowiredprivate OrderService orderService;/**** 訂單消費* @param message*/@RabbitListener(queues = PayOrderMchNotifyMQ.MQ_NAME)public void getMessage(String message) throws IOException {//下單信息Map<String,String> orderMap = JSON.parseObject(message,Map.class);//熱點商品下單orderService.hotAdd(orderMap);} }

總結

以上是生活随笔為你收集整理的微服务秒杀项目整合网关+feign+redis分离热点商品分别下单示例的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 日韩国产亚洲欧美 | 欧美午夜精品久久久 | 亚洲免费黄色 | 国产偷人 | 亚洲经典一区 | 色哟哟在线播放 | 九九久久99 | 无码精品人妻一区二区 | 国产一级片毛片 | 色吊丝av中文字幕 | 伊人伊人鲁 | 欧美高清精品一区二区 | xx色综合| 成人久久久久久久 | 久久伊人中文字幕 | 国产伦精品一区二区三区高清版 | 久久一区视频 | 午夜小视频网站 | 日韩一级二级三级 | 伊人久久精品视频 | 色综合一区二区三区 | 奇米影视大全 | 欧美午夜理伦三级在线观看 | 制服丝袜先锋影音 | 91丨九色丨丰满人妖 | 日韩午夜网站 | 亚洲老女人视频 | 99久久婷婷国产综合精品电影 | 中文毛片无遮挡高潮免费 | 66亚洲一卡2卡新区成片发布 | 女同性做爰全过程 | 91亚洲国产成人精品一区 | 亚洲自拍小视频 | 中文人妻熟妇乱又伦精品 | 国产成人精品a视频一区 | 精品女同一区 | 香蕉视频在线观看视频 | 超碰人人人人人 | 久久精品欧美日韩精品 | 免费成人电影在线观看 | 欧美日韩国产免费一区二区三区 | 美女100%露胸无遮挡 | 国产一区二区三区视频网站 | 日本学生初尝黑人巨免费视频 | 国内视频自拍 | 亚洲精品一卡 | 亚洲怡春院 | 一级久久久久久久 | 亚洲久视频 | 伊人精品综合 | 国产113页 | 91福利在线观看视频 | 熟女肥臀白浆大屁股一区二区 | av无码久久久久久不卡网站 | 91成人网页 | 日本午夜一区 | 久草免费资源站 | www.youjizz国产 | 日韩中文第一页 | 欧美日韩高清不卡 | 夜夜躁狠狠躁日日躁 | 一级黄色片大全 | 亚洲一区二区日韩欧美 | 丁香婷婷社区 | 伊人影院99| 天天爽天天操 | 艹少妇视频 | 91视频官网| 天堂av2021| 永久免费视频网站直接看 | 国产成人久久精品 | 在线视频免费观看 | caobi视频| 色欲AV无码精品一区二区久久 | 三级网站在线免费观看 | 国产精品91在线观看 | 在线免费观看日韩视频 | 亚洲自偷自偷偷色无码中文 | 青青草成人免费在线视频 | 成人av中文字幕 | 成人首页 | 欧美日本在线看 | 91av精品 | 黄色日b片 | 黄色网络在线观看 | 激情五月激情综合网 | 四虎永久免费地址 | 日本草草影院 | 黑森林av凹凸导航 | 粗喘呻吟撞击猛烈疯狂 | 亚洲久久天堂 | 伊人网在线 | 扒下小娇妻的内裤打屁股 | 色香蕉视频 | 金瓶风月在线 | 成人免费毛片免费 | 免费无码又爽又黄又刺激网站 | 国产视频a | 最新视频在线观看 |