精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

OpenTelemetry 深度定制:跨服務追蹤的實戰技巧

開發 前端
ContextCustomizer? 接口沒有提供對應的擴展,但是 SpanProcessor 是提供了擴展接口的。原本是想盡量別維護自己的 javaagent,但也好在 OpenTelemetry 是提供的接口,所以也并不會去修改原本的代碼。

背景

圖片圖片

我們的需求是這樣的:

圖片圖片

假設現在有三個服務:ServiceA、ServiceB、ServiceC。

ServiceA 對外提供了一個 http 接口 request,在這個接口會調用 ServiceB 的 order 訂單接口創建訂單,同時 serviceB 調用 serviceC 的 pay 接口。

圖片圖片

整個調用關系如上圖所示。

默認情況下 span 中的 attribute 會記錄當前 span 的一些信息,比如:

圖片圖片

這些都是當前一些當前 span 內置的信息,比如當前 gRPC 接口的一些基本數據:服務名、ip、端口等信息。

但這里并沒有上游的一些信息,雖然我們可以通過 Jaeger 的樹狀圖得知上游是哪個應用調用過來的,但是一旦某個 span 下有多個子 span 的調用,就沒辦法很直觀知道這個子 span 的上游是由誰發起的調用。

比如如下這個鏈路:

圖片圖片

當一個調用鏈非常長,同時也非常復雜時,沒辦法第一時間知道某一個 span 的上游到底是誰發起的,需要手動一層層的去折疊,或者全靠眼睛去找。

預期效果

圖片圖片

為此我們希望的效果是可以通過給每一個子 span 中加入兩個 attribute,來標明它的父調用來源。

比如在 serviceB 中的所有 span 中都會加上兩個標簽:來源是 serviceA,同時是 serviceA 的 request 接口發起的請求。

而在 serviceC 中同樣可以知道來源是 serviceB 的 Order 接口發起的調用。

我啟動了三個 demo 應用,分別是 create1,create2,create3.

create1 中會提供一個 request 接口,在這里面調用 create2 的 create2 接口,create2 的接口里接著調用 create3 的 create3 接口。

create1:

@RequestMapping("/request")  
    public String request(@RequestParam String name) {  
       HelloRequest request = HelloRequest.newBuilder()  
             .setName(name)  
             .build();  
       log.info("request: {}", request);  
       String message = myServiceStub.create2(request).getMessage();  
       Executors.newFixedThreadPool(1).execute(() -> {  
          myServiceStub.create2(request).getMessage();  
       });       return message;  
    }

create2:

@Override  
public void create2(HelloRequest request, StreamObserver<HelloReply> responseObserver) {  
    HelloReply reply = HelloReply.newBuilder()  
            .setMessage("Create2 ==> " + request.getName())  
            .build();  
    log.info("Create2: {}", reply.getMessage());  
    myMethod(request.getName());  
    myServiceStub.create3(request);
    responseObserver.onNext(reply);  
    responseObserver.onCompleted();  
}

create3:

@Override  
public void create3(HelloRequest request, StreamObserver<HelloReply> responseObserver) {  
    HelloReply reply = HelloReply.newBuilder()  
            .setMessage("Create3 ==> " + request.getName())  
            .build();  
    log.info("Create3: {}", reply.getMessage());  
    myMethod(request.getName());  
    responseObserver.onNext(reply);  
    responseObserver.onCompleted();  
}
java -javaagent:opentelemetry-javaagent-2.4.0-SNAPSHOT.jar \
-Dotel.javaagent.extensinotallow=otel-extensions-custom-context-1.0-SNAPSHOT.jar \
-Dotel.traces.exporter=otlp \
-Dotel.logs.exporter=none \
-Dotel.service.name=create2 \
-Dotel.exporter.otlp.protocol=grpc \
-Dotel.propagators=tracecontext,baggage,demo \
-Dotel.exporter.otlp.endpoint=http://127.0.0.1:5317 \
      -jar target/demo-0.0.1-SNAPSHOT.jar --spring.application.name=create2 --server.port=9191 --grpc.server.port=9292 --grpc.client.myService.address=static://127.0.0.1:9393

只是每個應用都需要使用我這邊單獨打的 agent 包以及一個 extension(tel-extensions-custom-context-1.0-SNAPSHOT.jar) 才能生效。

最終的效果如下:

圖片圖片

Baggage

在講具體的實現之前需要先了解幾個 Trace 中的概念,在這里主要用到的是一個稱為 Baggage 的對象。

在之前的文章中其實提到過它的原理以及使用場景:從 Dapper 到 OpenTelemetry:分布式追蹤的演進之旅

圖片圖片

Baggage 的中文翻譯是:包裹??;簡單來說就是我們可以通過自定義 baggage 可以將我們想要的數據存放在其中,這樣再整個 Trace 的任意一個 Span 中都可以讀取到。

@RequestMapping("/request")  
public String request(@RequestParam String name) {  
 // 寫入
    Baggage.current().toBuilder().  
          put("request.name", name).build()  
          .storeInContext(Context.current()).makeCurrent();
}         

// 獲取
String value = Baggage.current().getEntryValue("request.name");  
log.info("request.name: {}", value);

理解了這個之后,我們要實現的將上游的信息傳遞到下游就可以通過這個組件實現了。

只需要在上游創建 span 時將它自身數據寫入到 Baggage 中,再到下游 span 取出來寫入到 attribute 中即可。

ContextCustomizer

這里的關鍵就是在哪里寫入這個 Baggage,因為對第三方組件的 Instrumentation 的實現都是在 opentelemetry-java-instrumentation項目中。

javaagent.jar 包也是通過該項目打包出來的。

所以在該項目的 io.opentelemetry.instrumentation.api.instrumenter.Instrumenter#doStart 這個函數中我們發現一段邏輯:

圖片圖片

這個函數是在創建一個 span 的時候調用的,通常這個創建函數是在這些第三方庫的攔截器中創建的。

圖片圖片

比如這是在 grpc 的攔截器中調用。

// context customizers run before span start, so that they can have access to the parent span  
// context, and so that their additions to the context will be visible to span processors  
for (ContextCustomizer<? super REQUEST> contextCustomizer : contextCustomizers) {  
  context = contextCustomizer.onStart(context, request, attributes);  
}

ContextCustomizer 是一個接口只提供了一個函數:

public interface ContextCustomizer<REQUEST> {  
  
  /** Allows to customize the operation {@link Context}. */  
  Context onStart(Context parentContext, REQUEST request, Attributes startAttributes);  
}
  • Context 是上下文信息,可以在自定義的 ContextCustomizer 繼續往上下文中追加信息。
  • REQUEST 是一個泛型:一般是當前第三方組件的請求信息:

比如是 HTTP 時,這個 request 就是 HTTP 的請求信息。

而如果是 gRPC ,則是 gRPC 的請求信息。

其他的請求類型同理。

  • startAttributes 則是預先寫入的一些屬性,比如在上圖中看到的一些 rpc.service/rpc.method等字段。
// context customizers run before span start, so that they can have access to the parent span  
// context, and so that their additions to the context will be visible to span processors

從這個接口的調用注釋可以看出:這個自定義的 context 會在 span 開始之前調用,所以在這里是可以訪問到當前創建的 span 的父 context,同時在這里的 context 中新增的數據可以在 SpanProcessor 訪問到。

SpanProcessor

而 SpanProcessor 又是一個非常的重要的組件,我們接著剛才的 contextCustomizer 處往后跟蹤代碼。

context = contextCustomizer.onStart(context, request, attributes);
 --->Span span = spanBuilder.setParent(context).startSpan();
   --->io.opentelemetry.sdk.trace.SdkSpanBuilder#startSpan
    --->io.opentelemetry.sdk.trace.SdkSpan#startSpan
     --->spanProcessor.onStart(parentContext, span);

可以看到 spanProcessor.onStart 這個函數會在 contextCustomizer 之后調用。

圖片圖片

/**  
 * SpanProcessor is the interface {@link SdkTracer} uses to allow synchronous hooks for when a  
 * {@code Span} is started or when a {@code Span} is ended.  
 */
 
//==========================================================

/**  
 * Called when a {@link io.opentelemetry.api.trace.Span} is started, if the {@link  
 * Span#isRecording()} returns true.  
 * * <p>This method is called synchronously on the execution thread, should not throw or block the  
 * execution thread. * * @param parentContext the parent {@code Context} of the span that just started.  
 * @param span the {@code Span} that just started.  
 */void onStart(Context parentContext, ReadWriteSpan span);

從注釋中可以知道 SpanProcessor 是作為一個 span 的生命周期中的關鍵節點的 hook 函數。

在這些函數中我們可以自定義一些 span 的數據,比如在 onStart 還可以往 span 中寫入一些自定義的 attribute。

這也是我們這次會用到的一個接口,我們的方案是:

在 gRPC 構建 Instrument 時自定義一個 GrpcServerContextCustomizer ,在這個自定義的 ContextCustomizer 中寫入一個 Baggage。

然后在 io.opentelemetry.sdk.trace.SpanProcessor#onStart 接口中取出這個 Baggage 寫入到當前 span 的 attribute 中。

這樣我們就可以看到之前提到的那些數據上游信息了。

圖片圖片

為 gRPC 添加上下文

先來看看如何為 gRPC 添加 Baggage:

我們先自定義一個 GrpcServerContextCustomizer 實現類:

public class GrpcServerContextCustomizer implements ContextCustomizer<GrpcRequest> {  
  private final String currentServiceName;  
  
  private static final String PARENT_RPC_KEY = "parent_rpc";  
  private static final String CURRENT_RPC_KEY = "current_rpc";  
  
  private static final String CURRENT_HTTP_URL_PATH = "current_http_url_path";  
  
  public GrpcServerContextCustomizer(String serviceName) {  
    this.currentServiceName = serviceName;  
  }  
  @Override  
  public Context onStart(Context parentContext, GrpcRequest grpcRequest,  
      Attributes startAttributeds) {  
    BaggageBuilder builder = Baggage.fromContext(parentContext).toBuilder();  
  
    String currentRpc = Baggage.fromContext(parentContext).getEntryValue(CURRENT_RPC_KEY);  
    String fullMethodName = startAttributeds.get(AttributeKey.stringKey("rpc.method"));  
    String rpcService = startAttributeds.get(AttributeKey.stringKey("rpc.service"));  
    // call from grpc  
    String method = rpcService + ":" + fullMethodName;  
    String baggageInfo = getBaggageInfo(currentServiceName, method);  
  
    String httpUrlPath = Baggage.fromContext(parentContext).getEntryValue(CURRENT_HTTP_URL_PATH);  
    if (!StringUtils.isNullOrEmpty(httpUrlPath)) {  
      // call from http  
      // currentRpc = currentRpc;  currentRpc = create1|GET:/request      // clear current_http_url_path      builder.put(CURRENT_HTTP_URL_PATH, "");  
    }  
    Baggage baggage = builder  
        .put(PARENT_RPC_KEY, currentRpc)  
        .put(CURRENT_RPC_KEY, baggageInfo)  
        .build();  
    return parentContext.with(baggage);  
  
  }  
  private static String getBaggageInfo(String serviceName, String method) {  
    if (StringUtils.isNullOrEmpty(serviceName)) {  
      return "";  
    }    return serviceName + "|" + method;  
  }  
}

從這個代碼中可以看出,我們需要先從上下文中獲取 CURRENT_RPC_KEY ,從而得知當前的 span 是不是 root span。

所以我們其實是把當前的 span 信息作為一個 PARENT_RPC_KEY 寫入到 Baggage 中。

這樣在 SpanProcessor 中便可以直接取出 PARENT_RPC_KEY 作為上游的信息寫入 span 的 attribute 中。

@Override  
    public void onStart(Context parentContext, ReadWriteSpan span) {
        String parentRpc = Baggage.fromContext(parentContext).getEntryValue("parent_rpc");  
        if (!StringUtils.isNullOrEmpty(parentRpc)) {  
            String[] split = parentRpc.split("\\|");  
            span.setAttribute("parent_rpc", parentRpc);  
            span.setAttribute("parent_service_name", split[0]);  
            span.setAttribute("parent_service_method", split[1]); 
        }  
    }

需要注意的是,這里的 Baggage 需要使用 Baggage.fromContext(parentContext) 才能拿到剛才寫入 Baggage 信息。

之后我們找到構建 gRPCServerInstrumenterBuilder 的地方,寫入我們剛才自定義的 GrpcServerContextCustomizer 即可。

圖片圖片

.addContextCustomizer(new GrpcServerContextCustomizer(serviceName))

這里我們選擇寫入到是 serverInstrumenterBuilder 而不是clientInstrumenterBuilder,因為在服務端的入口就知道是從哪個接口進來的請求。

為 spring boot 的 http 接口添加上下文

如果只存在 gRPC 調用時只添加 gRPC 的上下文也夠用了,但是我們也不排除由外部接口是通過 HTTP 訪問進來的,然后再調用內部的 gRPC 接口;這也是非常常見的架構模式。

所以我們還需要在 HTTP 中增加 ContextCustomizer 將自身的數據寫入到 Baggage 中。

好在 HttpServerRouteBuilder 自身是實現了 ContextCustomizer 接口的,我們只需要往里面寫入 Baggage 數據即可。

public ContextCustomizer<REQUEST> build() {  
  Set<String> knownMethods = new HashSet<>(this.knownMethods);  
  return (context, request, startAttributes) -> {  
    if (HttpRouteState.fromContextOrNull(context) != null) {  
      return context;  
    }    String method = getter.getHttpRequestMethod(request);  
    if (method == null || !knownMethods.contains(method)) {  
      method = "HTTP";  
    }    String urlPath = getter.getUrlPath(request);  
    String methodPath = method + ":" + urlPath;  
  
    String currentRpc = Baggage.fromContext(context).getEntryValue(CURRENT_RPC_KEY);  
    String baggageInfo = getBaggageInfo(serviceName, methodPath);  
    Baggage baggage = Baggage.fromContext(context).toBuilder()  
        .put(PARENT_RPC_KEY, currentRpc)  
        .put(CURRENT_RPC_KEY, baggageInfo)  
        .put(CURRENT_HTTP_URL_PATH, methodPath)  
        .build();   
    return context.with(HttpRouteState.create(method, null, 0))  
        .with(baggage);  
  };}

這里新增了 CURRENT_HTTP_URL_PATH 用于標記當前的請求來源是 HTTP,在 grpc 的 ContextCustomizer 解析時會判斷這個值是否為空。

String httpUrlPath = Baggage.fromContext(parentContext).getEntryValue(CURRENT_HTTP_URL_PATH);  
if (!StringUtils.isNullOrEmpty(httpUrlPath)) {  
  // call from http  
  // currentRpc = currentRpc;  currentRpc = create1|GET:/request  // clear current_http_url_path  builder.put(CURRENT_HTTP_URL_PATH, "");  
}

圖片圖片

這樣就可以在 grpc 的下游接口拿到入口的 HTTP 接口數據了。

當然也有可能是在 grpc 接口中調用 HTTP 的接口的場景,只是我們的業務中沒有這種情況,所以就沒有適配這類的場景。

總結

ContextCustomizer 接口沒有提供對應的擴展,但是 SpanProcessor 是提供了擴展接口的。

原本是想盡量別維護自己的 javaagent,但也好在 OpenTelemetry 是提供的接口,所以也并不會去修改原本的代碼。

所以我們還是需要創建一個 extensions 的項目在實現 SpanProcessor,這個在之前的 《實戰:如何編寫一個 OpenTelemetry Extensions》有詳細講到。

所以最后的應用啟動方式如下:

java -javaagent:opentelemetry-javaagent-2.4.0-SNAPSHOT.jar \
-Dotel.javaagent.extensinotallow=otel-extensions-custom-context-1.0-SNAPSHOT.jar \

需要使用我們手動打包的 javaagent 以及一個自定義擴展包。

打包方式:

./gradlew assemble

opentelemetry-java-instrumentation 項目比較大,所以打包過程可能比較久。

因為這其實是一些定制需求,所以就沒提交到上游,感興趣的可以自行合并代碼測試。

最后可以這個分支中查看到修改的部分:https://github.com/crossoverJie/opentelemetry-java-instrumentation/compare/main...add-grpc-context

責任編輯:武曉燕 來源: crossoverJie
相關推薦

2009-12-24 16:15:17

2025-06-11 09:28:22

2010-08-13 14:44:26

思科路由器IOS軟件

2024-08-21 08:09:17

2022-05-10 09:33:50

Pandas技巧代碼

2025-05-14 08:20:00

Linux權限管理sudo

2018-10-30 12:15:26

CDN網絡技巧

2009-08-26 08:42:09

思科認證考試資料CCNA實戰技巧

2021-08-17 11:20:25

Vue前端技巧

2024-12-03 11:29:31

Javathis變量

2024-05-17 08:38:22

2023-10-16 23:43:52

云原生可觀測性

2025-04-23 08:35:00

2024-01-10 16:46:13

Kubernetes容器

2025-02-13 08:06:54

2010-04-15 16:03:19

Hyper-V災難恢復

2013-09-29 10:37:32

2009-12-29 16:37:35

Ubuntu 9.10

2024-08-30 14:21:04

2024-11-11 10:00:00

點贊
收藏

51CTO技術棧公眾號

裸体裸乳免费看| 欧美一二区视频| 91九色露脸| 好吊日在线视频| 色成人综合网| 国产亚洲欧美日韩俺去了| 日韩av免费网站| 最新中文字幕av| 综合另类专区| 国产亚洲欧美一级| 国产精品久久久久久久av电影 | 欧美性69xxxx肥| 久久久久高清| 成人黄色片在线观看| 欧美wwwww| 日韩三区在线观看| 久艹视频在线免费观看| 色呦呦免费观看| 视频一区在线播放| 日韩视频免费在线观看| 国产大学生av| 欧美xnxx| 午夜伦欧美伦电影理论片| 亚洲欧洲日本国产| 无码国精品一区二区免费蜜桃| 老汉av免费一区二区三区| 97精品国产91久久久久久| 成人性视频免费看| 欧美成人一区在线观看| 91精品福利在线一区二区三区 | 激情综合网址| 色偷偷噜噜噜亚洲男人| 亚洲男女在线观看| 国产精品1区| 在线观看一区日韩| 无码精品a∨在线观看中文| 3d玉蒲团在线观看| 国产精品免费aⅴ片在线观看| 久久精品日韩精品| 欧美熟妇交换久久久久久分类 | 91一区二区| 亚洲乱码国产乱码精品精| 超碰人人cao| 久久69成人| 色婷婷激情一区二区三区| 免费一级淫片aaa片毛片a级| 麻豆视频在线观看免费| 国产欧美日韩亚州综合 | 99久热这里只有精品视频免费观看| 色狠狠桃花综合| 精品人妻一区二区三区四区在线 | 久久这里有精品| 欧美aaa级片| 免费视频一区三区| 国产视频亚洲精品| 久久人人爽人人人人片| 国产精品自在线拍| 亚洲第一黄色网| 一级黄色片毛片| 成人午夜大片| 亚洲国产精品资源| 亚洲综合色噜噜狠狠| 成人精品久久一区二区三区| jizz国产在线| 日本成人中文字幕在线视频| 国产成人涩涩涩视频在线观看| 中文字幕免费观看| 日韩精品1区2区3区| 国产z一区二区三区| 久久久999久久久| 久久精品国产成人一区二区三区| 国产精品美女无圣光视频| 超碰在线观看91| 男人操女人的视频在线观看欧美 | 日本在线免费观看| 国产一区成人| 日本欧美中文字幕| 欧美在线视频精品| 国内久久精品视频| 高清视频一区二区三区| 天堂中文资源在线观看| 91看片淫黄大片一级在线观看| 欧美日韩在线一二三| 国产综合在线观看| 中文字幕一区二区三区精华液| 欧美在线观看黄| 超碰91在线观看| 色偷偷久久一区二区三区| 午夜免费福利视频在线观看| 日韩av综合| 日韩av在线导航| youjizz亚洲女人| 综合视频在线| 2019日本中文字幕| 中文字幕在线观看第二页| 国产麻豆欧美日韩一区| 韩国成人一区| www.成人.com| 一区二区三区 在线观看视频| 欧美,日韩,国产在线| 99精品国自产在线| 精品人在线二区三区| 91视频免费观看网站| 欧美电影免费观看高清| 欧美激情高清视频| 欧美特级黄色片| 国产精品一二三在| 欧美日韩在线高清| 超碰porn在线| 一本大道av一区二区在线播放| 天堂av8在线| 久久资源综合| 久久久999国产| 欧美一区二区三区四| 韩国午夜理伦三级不卡影院| 久久久久久久有限公司| www久久日com| 日本韩国欧美一区| 久久国产劲爆∧v内射| 欧美3p视频| 日本精品一区二区三区在线播放视频 | 成年人免费在线播放| 精品中文字幕一区二区三区| 亚洲日本成人女熟在线观看| 精品人妻在线播放| 激情图区综合网| 国产日韩精品综合网站| 中文字幕一区2区3区| 成人一级片在线观看| 一区二区三区的久久的视频| 婷婷电影在线观看| 日本精品视频一区二区| 99riav国产精品视频| 日韩手机在线| 久久精品91久久久久久再现| 无码人妻精品一区二| 91在线观看一区二区| 亚洲精品蜜桃久久久久久| 亚洲经典视频| 久久久国产一区二区三区| 波多野结衣激情视频| 久久综合网色—综合色88| 精品少妇在线视频| 日韩欧美久久| 欧美另类老女人| 国产精品热久久| 亚洲欧洲日本在线| xxx国产在线观看| 欧美日韩中文一区二区| 国产成人黄色av| 久久久pmvav| 色域天天综合网| 自拍偷拍视频亚洲| 日韩制服丝袜av| 日本中文不卡| 精品欧美一区二区三区在线观看 | 97视频在线观看网站| 色婷婷精品大视频在线蜜桃视频| 男人天堂av电影| 日日夜夜免费精品视频| 小说区图片区图片区另类灬| 蜜桃视频成人m3u8| 搡老女人一区二区三区视频tv| 国产精品露脸视频| 亚洲欧洲日本在线| 人妻 丝袜美腿 中文字幕| 韩日成人av| 久久免费99精品久久久久久| 成人免费看黄| 少妇高潮久久久久久潘金莲| 国产精品国产三级国产aⅴ| 亚洲欧洲综合另类在线| 女人扒开双腿让男人捅| 激情综合激情| 欧美一区观看| 日本亚洲欧洲无免费码在线| 欧美高清videos高潮hd| 天天色综合久久| 4438全国亚洲精品观看视频| 欧美精品亚洲一区二区在线播放| 成年人二级毛片| 成人午夜视频福利| 久久久久久久久久久久久国产精品 | 亚洲精选一区| 日韩高清专区| 久久精品九色| 91高清免费在线观看| 在线免费观看黄色av| 欧美一卡二卡在线观看| 永久免费看片在线播放| 久久久夜色精品亚洲| 在线观看国产中文字幕| 欧美午夜a级限制福利片| 蜜桃av噜噜一区二区三| 九九久久国产| 91精品国产自产91精品| 日本三级在线播放完整版| 欧美v国产在线一区二区三区| 黄色片中文字幕| 亚洲精品视频观看| 国产精品无码一区二区三区| 国产主播一区二区| 国产成人av影视| 国产中文一区| 亚洲国产精品一区在线观看不卡 | 欧美高清一区二区| 成人精品在线| 日韩免费观看网站| 国产盗摄在线视频网站| 日韩中文字幕免费视频| 天天摸天天碰天天爽天天弄| 亚洲一区二区高清| 东京热无码av男人的天堂| www.亚洲色图.com| 天天摸天天舔天天操| 蜜桃伊人久久| 日本中文字幕网址| 欧美日韩亚洲三区| 香蕉精品视频在线| 欧州一区二区| 欧美一级片免费观看| 精品嫩草影院| 亚洲综合中文字幕68页| 欧美视频免费看| 国产成人极品视频| 僵尸再翻生在线观看| 色综合五月天导航| 国产在线69| 精品国内自产拍在线观看| 97超碰人人在线| 亚洲天堂网站在线观看视频| 亚洲欧美日韩精品永久在线| 欧美mv日韩mv国产网站app| 国产理论片在线观看| 欧美性生活大片视频| 一级一片免费看| 福利一区福利二区微拍刺激| 黄色片视频网站| 亚洲3atv精品一区二区三区| 免费网站看av| 亚洲永久精品大片| 国产一区二区三区在线视频观看| 国产精品久久久久久亚洲伦| 日韩丰满少妇无码内射| 久久久午夜精品理论片中文字幕| av在线播放网址| heyzo一本久久综合| 岛国精品一区二区三区| 成人国产亚洲欧美成人综合网| 91精产国品一二三| 成人免费毛片片v| 乱码一区二区三区| 成人av影院在线| 欧美深性狂猛ⅹxxx深喉 | 免费看污片的网站| 欧美高清在线一区| 免费看一级黄色| 中文字幕一区二区三区在线不卡 | 五月天久久比比资源色| 国产 欧美 日韩 在线| 精品久久中文字幕久久av| 日本视频免费在线| 午夜视频在线免费观看| 亚洲激情视频在线播放| 四虎影视在线播放| 亚洲天堂男人天堂| 日本中文字幕伦在线观看| 日韩中文理论片| 黄色一级大片在线免费看产| 精品综合久久久久久97| 草草在线视频| 国产精品免费一区二区三区都可以| 精品久久在线| 成人黄色片视频网站| 日韩成人动漫在线观看| 日韩一区二区电影在线观看| 我不卡影院28| 岛国大片在线播放| 日韩制服丝袜先锋影音| 性生活在线视频| 91视频www| а天堂中文在线资源| 亚洲国产精品影院| 成人黄色免费网| 精品国产青草久久久久福利| 欧美日韩免费做爰大片| 久久精品视频99| 美女扒开腿免费视频| 亚洲日本中文| 98国产高清一区| 亚洲另类av| 最新视频 - x88av| 亚洲在线电影| 五月天国产视频| 国产亚洲一区二区在线观看| 国产稀缺精品盗摄盗拍| 欧美日韩国产限制| 国产精品国产三级国产普通话对白| 精品少妇一区二区三区免费观看| 欧美日本网站| 欧美高清电影在线看| 欧美黄色三级| 国产精品久久久久久久小唯西川| 欧美日韩黑人| 9久久9毛片又大又硬又粗| 久久99精品国产.久久久久久| 波多野结衣一二三区| 最新久久zyz资源站| www.com亚洲| 精品久久久久av影院| 麻豆传媒在线免费| 日本精品一区二区三区在线| 国产精品一区二区三区美女| 中文字幕一区二区三区在线乱码| 一区二区三区国产在线| 免费不卡av网站| 中文字幕电影一区| 久久亚洲精品国产| 亚洲精品在线三区| 成人无遮挡免费网站视频在线观看| 欧美孕妇与黑人孕交| 97久久亚洲| 亚洲自拍偷拍一区二区三区| 视频一区视频二区中文| 成人网站免费观看| 午夜私人影院久久久久| hs视频在线观看| 久久精品国产久精国产思思| 91福利精品在线观看| 玛丽玛丽电影原版免费观看1977 | 九九综合在线| 欧美视频在线免费播放| 成人午夜看片网址| 久久精品99国产精| 337p亚洲精品色噜噜| 午夜激情视频在线| 国产精品美女久久| 日韩在线观看| 亚洲综合色在线观看| 久久精品在线观看| 波多野结衣小视频| 国产一区二区三区三区在线观看 | 国产人成在线视频| 国产成人短视频| 精品国产不卡| 美女黄色片视频| 国产精品污网站| 亚洲一区精品在线观看| 色噜噜国产精品视频一区二区| 91超碰碰碰碰久久久久久综合| 日韩av电影免费播放| 日韩电影在线一区二区三区| 国产调教在线观看| 欧美高清视频www夜色资源网| 黄网页免费在线观看| 久久久不卡影院| 欧美深性狂猛ⅹxxx深喉| 亚洲成a人片在线观看中文| 天堂中文资源在线观看| 日本精品在线视频 | 亚洲人成人99网站| 国产另类xxxxhd高清| 亚洲日本无吗高清不卡| 国产在线视视频有精品| 青娱乐国产在线| 亚洲高清久久网| 成人自拍av| 国产系列第一页| 丁香婷婷深情五月亚洲| 99久热在线精品996热是什么| 日韩精品在线播放| 久久免费影院| 福利视频免费在线观看| 久久综合狠狠综合久久综合88 | 免费一级全黄少妇性色生活片| 精品久久久久久亚洲综合网| 美女高潮在线观看| 亚洲蜜桃av| 成人一区二区三区在线观看| 无码人妻丰满熟妇精品| 播播国产欧美激情| 欧美色图婷婷| 黄色永久免费网站| 亚洲国产你懂的| melody高清在线观看| 亚洲一区制服诱惑| 亚洲欧美日韩一区在线观看| 在线观看天堂av| 亚洲精品国产精品国产自| 日韩城人网站| 男人揉女人奶房视频60分 | 日本系列第一页| 中文字幕av一区| 加勒比久久高清| 奇米视频7777| 日韩欧美在线网址| 老司机福利在线视频| 欧美成人在线免费观看| 国产乱码精品一区二区三| 亚洲婷婷综合网|