找回密码
 注册
关于网站域名变更的通知
查看: 430|回复: 1
打印 上一主题 下一主题

这是一个诡异的时间问题追查

[复制链接]
  • TA的每日心情

    2019-11-20 15:22
  • 签到天数: 2 天

    [LV.1]初来乍到

    跳转到指定楼层
    1#
    发表于 2020-3-9 10:17 | 只看该作者 回帖奖励 |正序浏览 |阅读模式

    EDA365欢迎您登录!

    您需要 登录 才可以下载或查看,没有帐号?注册

    x
    ! p1 r3 k' e7 x4 I
    问题引入:7 t  l) X$ U5 x0 I
    问题是我们重装了一台电脑之后,发现apache
    + |+ ?$ M# v$ H; `2 i  N的日志里突然增加了很多服务时间超长的请求,如下面两条:
    8 U4 |1 i  \$ w  g** - - 4913229 11227 [29/Mar/2012:09:59:58 +0800] "GET*****
    8 v. v: ]! }: |* C# W- v** - - 4793564 9846 [29/Mar/2012:09:59:58 +0800] "GET ****** _- c" ]2 u2 F5 \6 b% U
    请求服务时间都在4s以上!这绝对无法忍受啊!% c% G' D: N5 \

    4 h1 a, M1 k# v0 Y7 }6 P2 h' ^分析过程:) a- V7 E8 n# }  y/ R2 U

    6 `4 G# p0 j: z) V! \但是,当我们:
    6 ^( M( [7 H6 f* v& P" s$ L4 r4 V * 手动访问这台服务器之后,发现基本上请求都是正常响应的;
    $ `8 ~& N: j; V6 j! n * 从前端反向代理的日志来看,服务时间也是正常的;3 u0 K+ U0 k) W
    那这样推断,真相只有一个,那就是apache的日志时间记录有问题!6 A/ t& @+ g2 f3 S5 B
    ) W6 V* b: U& j- C$ Y/ b! E
    什么问题呢?不清楚,但是apache
    ( v. _1 H; Z6 T4 _+ Y' E6 d# h的时间记录不外乎是在收到请求时记个时间,请求处理完成之后再记一个时间,既然是时?
    5 b, m2 p" y7 h4 o$ i6 t  x1 Y0 W涞奈侍猓敲淳涂纯聪低呈奔浒桑幼罴虻サ?date 开始,多执行几次:
    : s7 d2 U7 e* n# | apache2 # date
    , R' g) G7 K. [2 E$ \Wed Mar 28 17:25:08 CST 2012
      b( E) ^6 |+ A; _0 A5 oapache2 # date
    7 A; K1 D6 \) R" V& j  q$ O4 NWed Mar 28 17:25:04 CST 2012  时间减少了?- Y6 Z6 C5 `2 k8 G: Z5 V$ a  U
    apache2 # date
    1 ^- S* l5 U9 \3 L2 {9 `Wed Mar 28 17:25:06 CST 2012. `: m3 T; s+ ?( E( y
    apache2 # date$ G3 A9 `: k0 V  \$ R2 E5 M
    Wed Mar 28 17:25:12 CST 20125 d! {/ g: a+ Q% l+ k: }- o0 X" d
    apache2 # date/ O% S9 x* R$ r  C/ L: Z3 a
    Wed Mar 28 17:25:13 CST 2012
    % a8 L+ O6 a# A. n4 Q" ^/ v4 {apache2 # date8 y; b; K3 I/ |5 k3 ^
    Wed Mar 28 17:25:09 CST 2012 时间减少了?
    * k4 D! C& b' u% papache2 # date
    7 z$ L" F* f' @9 y( }( lWed Mar 28 17:25:09 CST 20125 @3 F; K# V' e, a
    apache2 # date
    7 @( n1 x, L7 f" c& ]6 P, QWed Mar 28 17:25:15 CST 2012
    $ w. w- L9 g6 A0 L那么第一个怀疑就是系统里有进程在自己不断的调时间,比如ntpdate, ntpd' m9 \9 V/ h7 I3 d
    ,那么我们首先把 ntpd给停掉;然后系统也没有任何地方会调用ntpdate;
    8 n6 L) `: c+ |- O3 N; h继续观察,发现停掉ntpd后,现象依旧!
    / B' y$ @# o& j0 L还有什么可能呢? date% C, O5 X" f2 q. P4 s
    程序是从内核里面读取时间还是说需要读取硬件时间?到底是怎么计算的呢?
    # Q8 A* j  Q; I请教下同事们,据说 sys_time 是读的kernel里的时间,而 sys_gettimeofday
    9 G6 u' ]. O. ?  l5 P' l2 X是需要读硬件时钟的。
    9 L6 g  J) t, s" ^' V) R) Z# F那么就测试一把吧:' M3 f/ R- r% v( w* Z
    先写个程序调用 time(), 然后打印结果,结果是这样的:
    % N8 Q- [7 B; v! N$ A0 V) e. _8 E13329866909 c+ x3 U2 w# n8 ~8 K. E; W
    1332986692
    3 t1 F; O7 h7 i% U1 E: R+ Z' s1332986693+ _  f6 ~9 ?6 n3 C' ?
    1332986693/ B5 p: E: ?: z3 F8 h: j
    1332986694
    ) t% `0 n8 o! T$ S1332986694
    ; Z% c* m: U6 B+ S3 S: t; ]1332986695
    ; t; H. P& u8 c  x% Z* m1332986695
    - f# q6 B. v' U; {1332986696* b- E+ t/ y; ]
    1332986696& O' F% `4 C! I( n# }
    1332986697
    6 e& c8 a8 {( \6 r1 ^8 z13329866976 _* B' y5 A1 T6 \  W8 R. @
    1332986698
    ; P3 \+ c1 ~2 Z3 c6 A4 y1332986698  D5 x/ z; P# }2 [9 q! |& g7 Y
    1332986699
    % ^! A3 B- @4 K: x- i- ^# P. y  s1 Y确实没有问题了!看来有可能是硬件问题了,再看看clock_gettime 的调用:
    ) W. F  g2 j1 D5 i: T{6 a8 D3 c' i! e" i5 h1 x& [- e* |
            struct timespec ts;                              
    4 g/ Y3 t; W8 j/ @; u        int ret = 0;                                      ! d. I* k& X4 D- ~
            ret = clock_gettime(CLOCK_REALTIME, ts);         
    5 o3 i' ]- M0 p" P. `        printf("ret: %d, time: %d %d", ts.tv_sec, ts.tv_ns
    , R2 ~/ W* D2 x}                                                         
    $ ~6 c0 z% j4 ?% Z0 g编译:        gcc -g -o clock_gettime getdate.c -lrt            
    . {* ?" y- e: y* }                                                          5 g# c( i' S) O4 j7 _9 Q3 u
    ~ # ./clock_gettime                                    
    1 ?: \7 g: P: J+ ]% `5 n& Dret: 1332991087, time: 594076000 -1
    : G& l9 ~. c% y- ^, Tret: 1332991088, time: 379009000 -1* _* v3 P5 w( W7 _  z9 O* Z
    ret: 1332991089, time: 68561000 -1: c" s) {8 b+ a+ z
    ret: 1332991089, time: 714013000 -11 n) y: |) l1 Y
    ret: 1332991086, time: 511250000 -1 时间在跳2 v3 I: X- T! k; w5 {' F
    ret: 1332991091, time: 945626000 -1
    + @4 R8 M8 w8 hret: 1332991092, time: 650479000 -1
    # K( z( o4 B9 V) w0 ?4 {0 oret: 1332991088, time: 734780000 -10 s% J; w+ W% o" m
    ret: 1332991094, time: 506114000 -1时间在跳                    ( I" A5 |6 ~2 m; H  f
    看来果然有可能是硬件问题!# U2 b: K6 ~* @. y0 e- }5 a- |
    那么,检查一下,直接调用一下 hwclock --show ,看看是不是可以验证这个问题:
    / K9 N" z( F: N; B. V1 e% d4 @+ y ~ # hwclock --show                               + I' ~! p* d) |
    Thu 29 Mar 2012 10:22:21 AM CST  -0.948923 seconds  - Q- l4 T/ d: ?  N' z& g
    ~ # hwclock --show                               ; H9 ^" h3 Q1 p( r
    Thu 29 Mar 2012 10:22:22 AM CST  -0.188950 seconds  
    + ?. F: s) H/ s) _# R. R1 b ~ # hwclock --show                              
    ' A/ h; ^0 d: g" X* kThu 29 Mar 2012 10:22:23 AM CST  -0.244766 seconds  , S+ H. P! ~! C7 I* J
    ~ # hwclock --show                              
      F; D! r8 M, m0 l% bThu 29 Mar 2012 10:22:24 AM CST  -0.336868 seconds  
    + G1 v4 K* y9 \ ~ # hwclock --show                               ( g4 h  a* h. K; s+ s0 C4 k
    Thu 29 Mar 2012 10:22:25 AM CST  4.237159 seconds   
    4 h# D7 k2 {& R# }# i ~ # hwclock --show                               + a8 M& S  [$ r: M
    Thu 29 Mar 2012 10:22:26 AM CST  4.238672 seconds   4 S% G1 Y5 X0 f8 D7 z' m
    ~ # hwclock --show                              
    9 f9 S9 R( L  r. z% IThu 29 Mar 2012 10:22:27 AM CST  -0.379418 seconds  - m, d/ k0 L5 R* Y% ^* L
    时间居然都是正确的!显然问题没有那么简单。。。那到底是怎么回事??还是从date  M1 C* M3 V- I% U, C$ J
    开始查起吧:' |; b: L( H0 {8 Q: |. n
    date是一个glibc里面的程序,那它的时间源是从哪里来的?查看一下glibc6 m4 j7 h! ^& \; c) j+ R; f) A' K
    的源码,它的时间从这里来:
    / o! B" o+ K3 k) `0 C5 R// glibc coreutils gettime.c
    - N4 J$ G- ?0 e6 z7 G$ W/* Get the system time into *TS.  */
    0 \$ y, o  F+ j4 _void# Y* Z( I, l7 {) Y1 `/ q& k6 T
    gettime (struct timespec *ts)
    0 a/ }: H6 n$ V1 s' p/ p- F{
    2 U4 f- Q8 e6 [- L/ i& w#if HAVE_NANOTIME
    # P8 M5 q8 q( X/ P2 d& B) Z  nanotime (ts);
    ) ]' X) T( J1 Q#else
    . q+ V) ]! D- r/ @! O
    $ e! O6 A0 X3 d1 |8 L: h- u/ ~& `: ~# if defined CLOCK_REALTIME && HAVE_CLOCK_GETTIME' ~6 ]1 L% @+ _
      if (clock_gettime (CLOCK_REALTIME, ts) == 0)) ~' s7 j1 V4 ?. z0 t5 U6 D. _) k. K+ o
        return;
    # k5 @2 D2 m0 F: }5 n# endif/ L; f3 @& [, j
    / E( ]$ V5 r. X1 f7 j7 H
    # if HAVE_GETTIMEOFDAY$ p$ L% }( h/ z  W' h5 H/ [
      {8 d; C1 @8 }* |- d
        struct timeval tv;: x1 J9 L  E( L) S; o8 N* V% k
        gettimeofday (&tv, NULL);' U3 @- T% _, d1 B
        ts->tv_sec = tv.tv_sec;
    ! I1 b8 {1 j) h* G' G1 f. L    ts->tv_nsec = tv.tv_usec * 1000;
    9 f7 z7 i/ J$ {" x7 b- U# i  }0 ^4 M  R' h5 H6 O" ]. W
    # else: d: k7 c9 _6 ?8 [3 O
      ts->tv_sec = time (NULL);# [. s3 E4 o) G/ Y; g3 s) G" u
      ts->tv_nsec = 0;
    / n9 T. w# h/ F- ~% _; |# endif# o5 |. y! p% {' y
    5 |/ g9 k5 |) I
    #endif6 e( t" A$ b6 \$ W4 `  n% W
    }
    1 J1 K* h1 G4 U5 N: c按照 nanotime, clock_gettime, gettimeofday的顺序去读取,我们这个系统中就是
    1 L5 z" }2 g- Q& a( a' [/ Eclock_gettime,从上面的小程序中也可以看到clock_gettime的时间是有问题的,那么1 C+ R$ f; x. z4 x# y' A
    clock_gettime的时间源是怎么来的呢?$ I% i+ Z# |" g: _0 `& \& I) C
    // linux kernel 2.6.18 arch/x86_64/kernel/time.c
    $ `, z% t! X# k7 m% Xvoid do_gettimeofday(struct timeval *tv), L# q6 r' k  r8 O+ k' r
    {: `1 ~* E: v+ d7 w2 I7 T( W
    unsigned long seq, t;
    & w+ N$ ^+ n2 _8 a1 J8 y$ p4 \ unsigned int sec, usec;
    , A# O' C& E$ k1 X& _ # B$ ?$ l- k* h& g9 P8 }6 \! N8 j
    do {$ H  ?1 D8 _) a/ e
    seq = read_seqbegin(&xtime_lock);
    8 y& K- Q0 a7 J2 Q , f. I. I3 A/ J  e
    sec = xtime.tv_sec;
    9 v9 {$ o1 u; k, `* M; b! qusec = xtime.tv_nsec / NSEC_PER_USEC;
    ) x" G& Y% B8 X/ r* A* xt = (jiffies - wall_jiffies) * USEC_PER_TICK +
    6 ~' L  C2 {$ `/ odo_gettimeoffset();
    6 k5 K0 o( s( S4 |  Y; j' ?usec += t;$ Q9 l2 _  x' h+ a4 d# f3 X: _
    / z  K# l% E6 j# S7 w
    } while (read_seqretry(&xtime_lock, seq));, ~9 B5 \* }4 p) r
    3 g- f* \4 U! |! S% w5 ^1 F- P
    tv->tv_sec = sec + usec / USEC_PER_SEC;
    - X3 {+ X, q0 h4 C! c& `tv->tv_usec = usec % USEC_PER_SEC;5 C" @% }, \" ?. ]! ]2 n
    }
    : y& c  b* W$ Q$ c4 B9 _; k# M反正就是一通计算,其中比较重要的是 do_gettimeoffset( o" ^0 p# {/ I! o
    ,这个函数的目的是计算上一次更新 xtime
    ) s4 j) m# p+ v到当前执行这一段时间的偏移量,然后用这个偏移量去加到 xtime
    % U4 ~, G4 |5 d上去,就是当前的时间(因为xtime的精度不够,clock_gettime
    9 R6 G/ N9 Y! W$ X/ g的精度要求更高,所以必须计算一个偏移量)。
    4 c+ E8 F5 f) h" S* k/ J那么,这个 do_gettimeoffset又是从哪来的?同样的文件里面有:( Y0 C1 u( _0 m) {4 i
    static inline unsigned int do_gettimeoffset_tsc(void)* i: J+ d" z( g$ D9 w8 M8 Q
    {/ w) U( A- o; z8 Y
    unsigned long t;
    * P8 R8 [( b. sunsigned long x;# C! A0 g; B7 d! I4 a& G4 I
    t = get_cycles_sync();
    ! \5 [* a% Q( jif (t < vxtime.last_tsc)
    4 y' [7 }1 w* C+ X* U5 V" mt = vxtime.last_tsc; /* hack */" L6 \4 u- M. N! B2 ~+ A' e
    x = ((t - vxtime.last_tsc) * vxtime.tsc_quot) >> US_SCALE;6 `6 W; V! F' q# Z3 \  r
    return x;6 ]; ^9 H$ \9 r: P
    }
    4 ~0 k% U, n1 [/ P- T
    * g! z) c* D" R( Zstatic inline unsigned int do_gettimeoffset_hpet(void)
    9 d8 L& @$ u: y5 F, p{5 p% t3 S  B( `6 P* w( ]' q
    /* cap counter read to one tick to avoid inconsistencies */
    " C: ^/ d; l, K  junsigned long counter = hpet_readl(HPET_COUNTER) - vxtime.last;
    9 x4 y) @4 M( E0 `5 y9 zreturn (min(counter,hpet_tick) * vxtime.quot) >> US_SCALE;
    3 }+ h# r* ]) p}
    , ]+ \. d+ }" V1 v4 |6 I0 O 1 O' |1 L: o9 }
    unsigned int (*do_gettimeoffset)(void) = do_gettimeoffset_tsc;
    0 h& A& Q) A* i7 r7 o) o6 ~也就是说,go_gettimeoffset 是从 tsc寄存器从拿到的,这又是神马玩意呢? 4 g( O6 U2 [+ j3 A7 V
    参考一下下面的几篇文章【1】【2】【3】,基本就明白了:2 `' v, h, h8 u
    tsc是一个cpu内的寄存器,用来累加从系统启动到目前,所有的时钟周期数,全称是 " V& I/ g, \# R! |& P5 M
    Timestamp Counter;
      O6 C) `$ `7 n5 u% D. b而且,最重要的是我们发现了一个重要的线索,那就是:' X" M+ S! o1 P0 k7 z7 b
    在多核cpu的架构中,tsc寄存器是很有可能不一致的,特别是在intel的比较老的多核CPU
    & f3 ?' V7 x0 s! x% u1 @中!坑爹....
    + n# z0 I; `" G* t' n  a很多文章提到过这个问题,比如【1】【2】【4】,显然如果不同cpu  L% N2 V, _1 ^# v9 Y
    读到的值不同的话,多次执行,显然时间是不一致的。4 W3 `, E1 m: n+ z$ c
    看起来就是这个问题了,那么就来验证一把:. `; Q: O" x; M8 |- ^2 W
    #include<stdlib.h>
    , Y* a$ w- b! k" F, N3 z#include<stdio.h>) c' x3 h: n! s: w
    #include<sys/types.h>/ o2 u: v+ W. K: Q8 b
    #include<sys/sysinfo.h>
    ' @, h7 g9 d6 P) L8 Y#include<unistd.h>
    ( V! |/ t5 Q/ T/ Z. Q$ ]: g#include<time.h>
    ) U- z, a+ |9 @* ?$ m( V
    ! a% E4 G2 v0 {; c* A#define __USE_GNU
    + @; E: S( |) K/ T' n5 ]$ d9 N# H! a#include<sched.h>1 r+ a  @0 I- t9 y! a5 O
    #include<ctype.h>1 L2 R, T' T  }( A1 v
    #include<string.h>
    6 X8 k* ^" C+ b/ T" j
    5 o) E5 c" _, M2 k" ]) L( }) V. _' D . P% v5 }2 J( }4 n2 l# B/ N
      Z9 H8 h9 n2 T/ M+ Y# J+ Y
    int main(int argc, char **argv){
    , ]4 Z) p+ E5 Q# o4 J ( E6 V+ v# z! B/ \4 p6 Y( H
            cpu_set_t cs;& m6 G# ]5 A, O) w% D; S1 u
            CPU_ZERO(&cs);  l7 B- m! U" [' [5 N
            CPU_SET(0, &cs);
    0 o& N- ?: X" b # v3 K* i% a7 v0 ~8 h# p3 {
            sched_setaffinity(0, sizeof(cpu_set_t), &cs);
    ! n; U3 k8 P- U* @
    / G% X- y, F9 E        struct timespec ts;9 n3 F, ^6 e& S# m1 {+ k) ~
            int ret = 0;
    3 |' {. y* ]* r  B$ }* ^        ret = clock_gettime(CLOCK_REALTIME, &ts);
    4 H  _# l- {& C$ e        printf("ret: %d, time: %lld %lld", ret,  ts.tv_sec, ts.tv_nsec);
    * c: M# X1 g2 z5 k0 m
    5 S8 Q3 e4 ?. v# c/ w: ]+ @+ Z}6 p; L" x( A& g, g" x

    5 j  k; G' c1 ?# Egcc -g -o cpu0_clock_gettime cpu_getdate.c -lrt
    , r7 o' v1 ]/ C; _$ |8 c# C ( Z2 E# I7 v$ o- m( c4 ?0 H  X
    ret: 0, time: 1332992815 537481000
    # }, O  `, X& O! i* C& k. Fret: 0, time: 1332992816 506704000* C. _' k% E& _% R+ h0 z7 G
    ret: 0, time: 1332992817 9910000
    0 V, ~& S9 a6 t+ Y% n' c$ Oret: 0, time: 1332992817 4804310002 r1 ~, R3 F3 Q# q% Y8 Z: X, H
    ret: 0, time: 1332992817 936965000, Z8 z3 o% V" _+ P  D* {4 d
    ret: 0, time: 1332992818 416634000- b* ?4 Y$ n/ ]# b
    ret: 0, time: 1332992818 8503190001 ^$ v/ w/ a" ^2 \9 D
    ret: 0, time: 1332992819 305075000
    7 Y/ e5 ?' J; f. Uret: 0, time: 1332992819 7291080002 `3 a. g3 o- Q8 e" j9 ?, z, T
    ret: 0, time: 1332992820 164726000
    / w( [% K9 Y- ?0 \8 |/ S7 zret: 0, time: 1332992820 577573000
    - E+ z0 ]6 _" M. Bret: 0, time: 1332992820 9850250001 z+ p8 u* d+ X0 @1 T& G
    ret: 0, time: 1332992821 394070000% ~* u1 T$ V2 M: q2 d0 s
    ret: 0, time: 1332992821 816708000
    & U$ l% h& U" @: k. Nret: 0, time: 1332992822 216811000) f0 g8 c/ J& p9 T* K" ?
    ret: 0, time: 1332992822 616901000
    9 H6 k. O# u7 ?1 L3 T, pret: 0, time: 1332992823 18564000w5 X, a$ p: }7 H0 i4 K
    ret: 0, time: 1332992823 727585000
    " k0 H) R9 i/ U% k) N. {% v通过把程序的调度固定在某一个具体的cpu中,那么clock_gettime的结果也是正确的!7 W, L0 M4 z$ W+ F, ~$ w
    经过几次测试,很容易找到两个cpu时间不一致的情况,具体这个例子来说就是 cpu0和
    ) e$ }2 Y% P8 T# O! \. L6 ecpu5,把上面的程序修改一下,可以看到结果基本上每次都会跳一把。
    4 R* }2 o# _8 o& C; g$ `0 _7 \3 @问题解决:
    2 W* C! V, B/ P6 \% O) e. i那么,tsc在多核cpu中的值不同,应该怎么解决呢? 如 【4】所示,在高版本的linux
    : }2 M* o, j* n* L内核中,有人提交了补丁,可以在内核启动时检查并且同步一把,那么升级一下内核到 2
    6 d1 s( y: M. b- ~7 ?9 j.6.38。
    0 E6 M2 \- ?  f1 J) C( o6 T5 L8 f重新启动到新内核之后,问题解决!. ?! J) `3 Q8 }+ C8 ?. v
    总结一下:
    ) k+ E  p' ]& w* @0 Z: D0 {% E: n1. apache的时间统计方式,没具体看实现,但是显然前后的两个时间可能是在不同的cpu, r' s% D7 ^, z* L1 E. d9 w) r
    核上计算出来的。
    1 s2 a  b8 w6 A% f- H1 B2. tsc的值,并不能保证是同步的,特别是在某些Intel cpu
    . g% ?. y+ E) w* e3 Q的情况下;但是新的内核会做一些检查和resync的工作;9 S! s/ E6 @# f$ k
    3. time()调用直接读取内核的xtime值,不会触及硬件;但是 gettimeofday(), ( Z  q; x; u! q3 N8 r  }
    clock_gettime() 在 x86_64下都会读取tsc值;
    ; m4 G  Q0 E: J+ ~4. hwclock读的硬件时钟显然不是 tsc,应该是实时时钟RTC;
    ( {( j1 h/ S8 _! b【1】 http://en.wikipedia.org/wiki/Time_Stamp_Counter2 j) U# T# D1 h% c
    【2】 http://juliusdavies.ca/posix_clocks/clock_realtime_linux_faq.html7 @9 O1 d2 R# c& P' o. p
    【3】http://www.linuxforum.net/forum/gshowflat.php?Cat=&Board=driver&Number=
    & g  e( D6 g, S. I8 }8 h385219&page=0&view=collapsed&sb=5&o=all&fpart , linux时钟中断机制,Copyright
    & H- C: Z, D( L  ~2003 by 詹荣开9 x, Y1 C& ]$ ^& G7 Q
    【4】http://lwn.net/Articles/211051/ x86: unify/rewrite SMP TSC sync code  

    该用户从未签到

    2#
    发表于 2020-3-9 17:20 | 只看该作者
    时间问题追查,牛逼了
    您需要登录后才可以回帖 登录 | 注册

    本版积分规则

    关闭

    推荐内容上一条 /1 下一条

    EDA365公众号

    关于我们|手机版|EDA365电子论坛网 ( 粤ICP备18020198号-1 )

    GMT+8, 2025-11-25 22:21 , Processed in 0.171875 second(s), 24 queries , Gzip On.

    深圳市墨知创新科技有限公司

    地址:深圳市南山区科技生态园2栋A座805 电话:19926409050

    快速回复 返回顶部 返回列表