精品欧美一区二区三区在线观看 _久久久久国色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技術棧公眾號

国产一区二区三区四区老人| 黄色软件在线| 欧美a级片网站| 精品福利一二区| 成年人午夜免费视频| 免费在线稳定资源站| 免费国产亚洲视频| 久久这里只有精品99| 日本免费福利视频| 成人污污视频| 色综合色狠狠天天综合色| 一区二区三区四区五区精品 | 国产精品偷伦一区二区| 全网免费在线播放视频入口 | 日韩h在线观看| 欧美午夜aaaaaa免费视频| 欧美人体视频xxxxx| 久久精品日韩一区二区三区| 97视频资源在线观看| 男人天堂视频网| 国产精品啊v在线| 色偷偷av亚洲男人的天堂| 91精品啪在线观看国产| 日韩免费在线电影| 一本色道久久综合亚洲aⅴ蜜桃| 中文字幕色呦呦| 国产高清视频免费最新在线| 国产91在线|亚洲| 国产噜噜噜噜噜久久久久久久久| 日本熟妇一区二区| 99久久婷婷| 国产亚洲精品激情久久| 亚洲精品在线视频免费观看| 日韩中文字幕一区二区高清99| 欧美性大战久久久久久久蜜臀 | 欧美aa在线观看| 亚洲另类春色国产| 亚洲人成77777| 国产中文字幕在线观看| 99久久亚洲一区二区三区青草| 国产日韩在线看片| 久草热在线观看| 久久综合影视| 97国产suv精品一区二区62| 欧美成欧美va| 亚洲人metart人体| 久久色精品视频| 久久久免费看片| 精品美女久久久| 亚洲欧美日韩国产中文专区| 国产日韩视频一区| 国产精品xxx在线观看| 欧美日韩高清一区二区三区| av污在线观看| 欧美爱爱视频| 欧美精品电影在线播放| 一区二区xxx| 在线视频成人| 日韩一区二区三区电影| 国产精品91av| 日韩欧美美女在线观看| 亚洲欧美日韩国产中文| 五月天精品在线| 欧美日韩第一| 日韩性生活视频| 美女视频久久久| 一区二区蜜桃| 久久人人97超碰精品888| 国产做受高潮漫动| 久久久久久久波多野高潮日日| 日本精品性网站在线观看| 波多野结衣黄色网址| 美女一区二区三区在线观看| 国产成人在线视频| 中文字幕 自拍偷拍| 精品一区二区三区影院在线午夜| 92看片淫黄大片看国产片| 成人av无码一区二区三区| 成人美女视频在线观看18| 鲁丝一区鲁丝二区鲁丝三区| 一广人看www在线观看免费视频| 中文字幕一区二区三区精华液| 欧美日韩午夜爽爽| 欧美13videosex性极品| 欧美中文字幕一区| 日本r级电影在线观看| 精品深夜福利视频| 中文字幕av一区中文字幕天堂| 成人在线观看小视频| 亚洲黄色成人| 国产精品日韩欧美| 欧美熟妇乱码在线一区| 久久久久成人黄色影片| 男女h黄动漫啪啪无遮挡软件| 91豆花视频在线播放| 欧美综合天天夜夜久久| 在线观看欧美一区二区| 久草成人在线| 久久69精品久久久久久久电影好| 日韩成人av毛片| 美女精品自拍一二三四| 国产精品果冻传媒潘| 天天爱天天干天天操| 中文字幕va一区二区三区| 日韩小视频网站| 免费成人高清在线视频| 精品国产91洋老外米糕| 一本在线免费视频| 亚洲深夜影院| 91精品国产91久久久久青草| 高清av电影在线观看| 图片区小说区区亚洲影院| 日本在线播放一区二区| 欧美极品中文字幕| 久久久免费av| 99精品视频在线播放免费| 国产欧美一区二区精品性色超碰 | 欧美电影免费观看完整版| 中文字幕免费高清| 91久久黄色| 91传媒在线免费观看| 日本韩国在线视频爽| 色综合天天综合网天天狠天天| gogo亚洲国模私拍人体| 91欧美大片| 国产精品视频xxxx| 国产资源在线看| 欧美午夜无遮挡| 俄罗斯黄色录像| 亚洲精品网址| 国产综合色香蕉精品| 国产高清免费在线播放| 一本久久综合亚洲鲁鲁五月天| 黄色在线免费播放| 好吊视频一区二区三区四区| 亚洲xxxxx| xvideos国产在线视频| 欧美人xxxx| 国产人与禽zoz0性伦| 日韩av不卡在线观看| 欧美久久久久久久| 欧美日韩大片| 亚洲欧美在线磁力| 久久久久在线视频| 国产人妖乱国产精品人妖| 成人免费无码av| 国产在线观看91一区二区三区| 26uuu亚洲伊人春色| 天天操天天干天天干| 婷婷中文字幕综合| 国产性生活毛片| 亚洲综合二区| 欧美日韩精品综合| 欧美舌奴丨vk视频| 在线不卡国产精品| 中文人妻熟女乱又乱精品| 欧美国产一区在线| 久久久久久久久久一区二区| 外国成人免费视频| 成人18视频| 久草免费在线视频| 一区二区三区无码高清视频| 伊人久久成人网| 亚洲欧美另类久久久精品2019| 伊人免费视频二| 伊人影院久久| 日韩精品国内| 在线视频成人| 97国产精品视频人人做人人爱| 日韩精品视频在线观看一区二区三区| 欧美日韩一区二区在线播放| 毛茸茸多毛bbb毛多视频| 日韩国产高清在线| 干日本少妇视频| 久久动漫网址| 国产美女精品免费电影| 超碰免费在线播放| 日韩av网站在线| 中文天堂在线资源| 亚洲香肠在线观看| 精品欧美一区二区久久久| 久久爱另类一区二区小说| 喜爱夜蒲2在线| 久久99蜜桃| 91色琪琪电影亚洲精品久久| 成人bbav| 久久国产一区二区三区| 欧美性猛交 xxxx| 色av一区二区| 欧美精品乱码视频一二专区| 久久久99精品免费观看不卡| 99精品视频国产| 久久综合图片| 国产 欧美 日韩 一区| 精品国产一区二区三区| 成人欧美一区二区三区视频xxx | 日本韩国欧美三级| 久久久久久久久毛片| 久久色在线观看| 日本xxxx免费| 久久国产精品99久久久久久老狼 | 日韩精品一区二区三区swag| 国产免费www| 亚洲一区二区四区蜜桃| 国产伦理片在线观看| 成人小视频免费观看| 色乱码一区二区三区在线| 狠狠爱www人成狠狠爱综合网| 水蜜桃亚洲一二三四在线| 风间由美性色一区二区三区四区| 国产剧情日韩欧美| 欧美电影免费观看| 91国产中文字幕| 伊人影院在线视频| 日韩亚洲一区二区| 国产香蕉在线| 日韩电影中文字幕在线| www.黄色av| 欧美另类高清zo欧美| 无码人妻一区二区三区线| 亚洲午夜激情av| 免费看一级大片| 中文字幕一区在线观看视频| 一本加勒比北条麻妃| av男人天堂一区| 亚洲成人福利视频| 国产精品亚洲第一| 中文字幕人妻熟女人妻a片| 麻豆极品一区二区三区| 免费观看成人在线视频| 免费在线欧美黄色| 99热自拍偷拍| 国产日韩欧美| 成人毛片视频网站| 国产色综合网| 熟女少妇在线视频播放| 亚洲免费大片| 精品国产一区三区| 国产精品亚洲欧美| 欧美极品欧美精品欧美图片| 国产亚洲网站| 免费在线激情视频| 久久一区中文字幕| 热久久精品国产| 日韩精品欧美精品| 天天爱天天操天天干| 日本伊人精品一区二区三区观看方式| 可以在线看的黄色网址| 每日更新成人在线视频| 欧美日韩在线成人| 日韩av一级片| www.99r| 国产一区二区不卡| 香蕉视频在线观看黄| 成人黄色大片在线观看| 我和岳m愉情xxxⅹ视频| 国产性做久久久久久| 日本午夜精品视频| 亚洲美女屁股眼交| 四虎永久在线精品| 91久久久免费一区二区| 亚洲天堂狠狠干| 日韩一区二区三区在线视频| 性一交一乱一精一晶| 精品国免费一区二区三区| 熟妇高潮一区二区三区| 亚洲欧美综合图区| 免费黄色在线网站| 久久久久亚洲精品成人网小说| 川上优av中文字幕一区二区| 国产成人精品一区二区在线 | 欧美三片在线视频观看 | 成人片免费看| 国产精品久久久久久久久久久久久 | 亚洲视频资源在线| 豆国产97在线 | 亚洲| 黑人精品xxx一区| 一道本在线视频| 精品国产人成亚洲区| 毛片网站在线观看| 欧美成人精品h版在线观看| 色戒汤唯在线观看| 国产日韩欧美自拍| 台湾佬综合网| 一区不卡字幕| 亚洲精品色图| 91 在线视频观看| 99re热视频精品| 黄色录像免费观看| 欧美日韩免费在线| 国产伦精品一区二区三区四区| 亚洲аv电影天堂网| 成人在线观看免费| 欧美交受高潮1| 外国成人毛片| 久久久亚洲综合网站| 午夜精品毛片| 欧美两根一起进3p做受视频| 国产乱人伦偷精品视频不卡| 日韩av一二区| 亚洲午夜免费视频| 91在线观看喷潮| 日韩精品亚洲元码| 日韩少妇视频| 成人乱色短篇合集| 久久av网址| 国产在线精品91| 国产高清不卡一区| 国产不卡在线观看视频| 欧美日韩激情小视频| 精品国产av一区二区三区| 在线日韩中文字幕| 成人美女大片| 精品一区二区三区免费毛片| 国产精品99久久精品| 黄色一级大片在线观看| 成人av网站在线观看免费| 波多野结衣亚洲一区二区| 欧美在线|欧美| 精品视频三区| 欧美最猛性xxxx| 国产精品白浆| 蜜臀av色欲a片无码精品一区| 国产综合久久久久影院| 丁香激情五月少妇| 欧美性猛交xxxxx免费看| 欧美一区二区三区成人片在线| 久久视频在线直播| 粉嫩一区二区三区在线观看| 亚洲欧洲三级| 蜜臀久久久久久久| 亚洲不卡的av| 欧洲视频一区二区| 蝌蚪视频在线播放| 日韩av电影手机在线| 亚洲精品进入| 国产一区亚洲二区三区| 久久色.com| 免费观看日批视频| 国产午夜精品视频| 经典三级一区二区| 少妇免费毛片久久久久久久久 | 欧美性猛交xxxx乱大交91| 国产精品盗摄一区二区三区| 中文人妻熟女乱又乱精品| 中文字幕视频在线免费欧美日韩综合在线看 | 777奇米四色成人影色区| 毛片在线看网站| 亚洲影院高清在线| 国精品一区二区| 欧美大喷水吹潮合集在线观看| 午夜视黄欧洲亚洲| 色猫av在线| 国产精品香蕉av| 亚洲精品极品少妇16p| 国产精品嫩草69影院| 亚洲成人7777| 欧美成人免费| 国产精品视频不卡| 91精品一区国产高清在线gif| 91av免费观看| 污片在线观看一区二区| 国产三级电影在线| 亚洲www在线| 99国产精品| 极品蜜桃臀肥臀-x88av| 欧美日本免费一区二区三区| 2021国产在线| 九色综合婷婷综合| 奇米色777欧美一区二区| 欧美一区免费观看| 亚洲国产另类 国产精品国产免费| 高清毛片在线观看| 亚洲人久久久| 成人一区在线看| 久久久精品视频网站| 色婷婷综合久久久久| 成人av动漫| 中文字幕第21页| 一区二区三区免费| 国产一区二区三区福利| 成人精品视频99在线观看免费| 精久久久久久| 欧美a级片免费看| 精品国产髙清在线看国产毛片| 一区二区三区四区日本视频| 伊人精品久久久久7777| 99精品视频在线播放观看| 在线观看毛片视频| 久久免费福利视频| 久久综合88| 日韩av一二区| 日韩欧美亚洲国产另类| 欧美xxxx做受欧美护士| 少妇一晚三次一区二区三区| 久久久亚洲高清| 亚洲第一视频在线播放| 国产男人精品视频| 一本久久综合| 波多野结衣亚洲色图|