myjava
2021-08-17 15:42:31 0 举报
AI智能生成
java知识点脑图
作者其他创作
大纲/内容
设计模式(代码简单吗没必要,复杂可维护的话有优势)
接口和抽象类
1.接口抽象类是框架基础,框架包括方法框架和流程框架(一套稳定的流程);
2.面向接口和抽象类,只要接口和抽象类是稳定的,一般可以抛开具体实现来编程,框架比较稳定
柔性多态? dispatch(功能号)做功能分发?
2.面向接口和抽象类,只要接口和抽象类是稳定的,一般可以抛开具体实现来编程,框架比较稳定
柔性多态? dispatch(功能号)做功能分发?
反射
主要的类:Class、Field、Constructor、Method
反射与框架:反射提供编写稳定框架的能力, 新增功能时可能只需要增加对应的类class,而调用规则不变
工厂模式(用途:创建对象)(用过)
简单工厂: create一般是静态的,也称静态工厂,主要描述结果与条件的关系,同时无需继承某个父类
抽象工厂, 定义生产动作,具体不同的产品实现不同的生产动作,相比简单工厂优点在于:如果生产的动作比较复杂
* 新增产品时,不会对原有代码造成入侵,优于简单工厂
* 新增产品时,不会对原有代码造成入侵,优于简单工厂
一般而言产品都会实现同一个接口,能够画出功能层次图
生成器模式/建造者模式(用途:创建对象)
建造者模式, 就是创建的产品基本属于同一类,而且流程都基本相同,但是不同的产品每个流程内容不太相同的,
*而工厂模式,是创建的产品本身可能就完全不同,只是同一族而已,重要的是要能够抽象出产品及其创建流程;
如果只是单个产品的话,属性很多,使用构造方法不容易构造,可以链式调用,直接使用static builder.build()
*而工厂模式,是创建的产品本身可能就完全不同,只是同一族而已,重要的是要能够抽象出产品及其创建流程;
如果只是单个产品的话,属性很多,使用构造方法不容易构造,可以链式调用,直接使用static builder.build()
观察者模式(用途:数据生产者和消费者,各种阻塞队列)(用过)
包括主题层(数据产生层可以带上数据处理层),主题中一般包括register(Observer),unregister和notify方法,以及维护观察者的池子;Observer观察者层(数据消费层);将变化数据给到observer即推数据,将subject引用给到observer即拉数据,jdk中utill包下的Observable和Observer就是拉式观察者的顶级接口
本质上是一种事件驱动型的发布订阅模式
本质上是一种事件驱动型的发布订阅模式
桥接模式(用途:多个事物要实现多功能 nxm)
本质上是将原本在事物中要实现功能的接口变为了在抽象事物类(关键)中持有功能接口的引用,思想是引用代替继承,吧本来要继承重写的方式改变为持有引用的方式
代理模式(用途:在多个方法前或者后都要执行共同逻辑)(用过)
静态代理+动态代理
模板模式(用途:流程顺序相同,一般写在abstract类中)(用过)
行为流程顺序由父类定义,具体每个流程由子类实现,父类的定义流程顺序的方法应该final,禁止重写
原型模式(用途:创建构造器复杂的对象或者很多数据差不多相同的对象)(用过)
(1)其实就是对象的克隆,一个对象作为原型,实现Cloneable接口,重写clone方法,注意深克隆(调用clone方法和字节流方法)和浅克隆
(2)克隆不会再调用构造器,用于构造器逻辑比较复杂,或者比较耗性能的一些对象的拷贝
(2)克隆不会再调用构造器,用于构造器逻辑比较复杂,或者比较耗性能的一些对象的拷贝
中介者模式(用途:几个对象之间相互引用,且状态改变或者涉及到数据同步时需要相互通知的场景)
最大的优点是解耦,不使用该模式时,明显对象本身无法复用,因为耦合很严重
缺点是中介类会变得很复杂,不严格来说,只要解耦的模式都可看做中介者模式,如MVC或者线程池模型,将线程任务的生产与执行分离
缺点是中介类会变得很复杂,不严格来说,只要解耦的模式都可看做中介者模式,如MVC或者线程池模型,将线程任务的生产与执行分离
命令模式
调用者与命令的执行者解耦,调用者只调用命令,命令绑定具体的执行者
责任链模式(应用:请求者有一个,而处理者有多个,而且每个处理者有不同的处理范围(类比请假)可替换if else(范围条件的情况下),或者一个以上的对象处理某个请求时使用责任链)
抽象出Handler,然后每个Handler持有下一个处理的handler,同时,每个handler设置自己处理的范围,处理逻辑统一在抽象类中
策略模式(替换if else的场景)(用过)
if else大批量比较多,可考虑使用该模式,写个enum
适配器模式(用途:将两个没有关系的类联系起来,其中一个类不太方便实现另一个类的接口,并从一个类型数据返回另一个类型数据)
子类继承目标类并实现源数据类,包括类适配器,对象适配器(持有源应用),转换的目标是哪个就实现哪个接口
门面模式(用法:内部复杂对应多个子系统,但对外只提供一个接口)
接口隔离原则:两个有交互的系统,只暴露有限的必要的接口,用一个Facade来对外,其他的子系统只与门面关联,Socket其实就是一个⻔面模式,它把复杂的TCP/IP协议族隐藏在Socket接⼝后面
享元模式(用法:自己实现的缓存池模型/缓存模型都算)(用过)
享元模式就是池模型,内部维护有限的几个池元素,供外部调用,String Integer、线程池 连接池等都是享元模式,
* 如果享元模式中池子里对象都是唯一的,那么就是享元模式下用工厂模式实现的单例模式
* 如果享元模式中池子里对象都是唯一的,那么就是享元模式下用工厂模式实现的单例模式
mysql调优
架构
客户端(发/收数据)、服务端(权限校验、语法校验、优化、
统计分析、执行等)、存储引擎(磁盘存储数据)
统计分析、执行等)、存储引擎(磁盘存储数据)
常用监控命令
show profile(s)
分析每条sql执行的过程和耗时,官网:
https://dev.mysql.com/doc/refman/5.7/en/show-profile.html
set profiing =1;show profile;
https://dev.mysql.com/doc/refman/5.7/en/show-profile.html
set profiing =1;show profile;
Performance Schema
mysql性能监控的数据库,未来会替代show profile,该数据库需要root权限(一般dba看)
show full processlist
查询数据库的所有连接(线程),可以看到具体语句的正在执行的状态
explain、show warnings
展示sql执行的顺序和优化后的sql
schema和数据类型
数据类型优化
最小的数据类型通常最好
类型越简单越好,该什么类型就什么类型,该date不要string,能整型不要string
尽量不使用null
数据类型细节问题(char与varchar)
主键选择
代理主键(与业务无关,推荐)、自然主键(业务耦合)
字符集选择
关于utf8字符集的详解
存储引擎、适当拆分(分库分表,垂直水平)
执行计划
explain解释:https://blog.csdn.net/weixin_42410730/article/details/101864257
mysql索引
索引结构的选择,mysql两种索引结构:hash和B+tree
原理:https://editor.csdn.net/md/?articleId=101864257
原理:https://editor.csdn.net/md/?articleId=101864257
聚合索引 和非聚合索引,页合并,页分裂
技术名词
回表、索引下推、最左匹配(组合索引最终也是一颗B+树)、索引覆盖
索引优化
前缀索引、组合索引当最左索引不是等值查询时,剩下的索引列将无法被用上,大表之所以慢瓶颈在于带宽和磁盘IO
索引优化细节
join连接使用索引的原理
查询优化
myISAM对count有记录,记录了全表的总条数,而inndb得读所有索引;
很多情况下,子查询会被优化成关联查询,可以通过explain 和show warnings观察优化后的执行语句
很多情况下,子查询会被优化成关联查询,可以通过explain 和show warnings观察优化后的执行语句
排序算法中可能在内存也可能使用临时磁盘空间
表分区
innodb文件空间管理:tablespace(segment段(extent区(page)));
分表的两种策略;水平:同一张表,1-100一张表,100-200一张表,依次类推,应用在历史表等;垂直:不同表,将一部分一个机器,另一个部分一个机器
分表的两种策略;水平:同一张表,1-100一张表,100-200一张表,依次类推,应用在历史表等;垂直:不同表,将一部分一个机器,另一个部分一个机器
分区表的限制,range分区的官网使用案例
服务端相关
redo log 、undo log、binlog详解
最大连接设置多少合适?跟内存/系统响应时间/系统本身是否还有其他进程等,连接数比越大,负面影响越大
mysql锁机制、事务机制;共享 排他 间隔锁 自增锁、意向插入锁
、锁退化、乐观锁
、锁退化、乐观锁
mysql主从复制、mycat读写分离
redis
基本类型和操作和二进制安全:String(int string bitmap)全局计数使用、list(注意lpush和rpush的倒叙结构,lpush+lpop是栈结构)、hash(面向对象、详情页点赞 收藏等使用)、sortedset(去重 排序 做排行榜等,底层跳表)、set(去重、集合运算,srandmember)
架构上,epoll多路复用,单线程监听所有连接,但是数据处理并非单线程
事务 watch(保证原子性,不可回滚,cas锁保证key未被改变过)
布隆过滤器,解决缓存穿透
技术选型:redis只 保存热数据,因为内存有限,
数据淘汰机制:默认抛异常、allkeys-lru,allkeys-random,valitile-ttl,votatile-lru,volatile-random
数据淘汰机制:默认抛异常、allkeys-lru,allkeys-random,valitile-ttl,votatile-lru,volatile-random
持久化aof/rdb,rdb使用fork+copyonwrite实现,两种方式 bgsave/save;
aof:追加 三种:always/no/everysec default,缺点:恢复数据慢,占用空间大
aof:追加 三种:always/no/everysec default,缺点:恢复数据慢,占用空间大
集群的三种方式
主备故障转移(解决单机故障问题,备机一般最多只读,可以读写分离,几乎不用)
主从分片redis cluster 采用无中心模式(解决容量问题和IO压力,不同的key放不同节点,主从都接受client)、
一致性hash与hash槽的区别、数据倾斜,redis三种常见的分区实现方案、选举从机变主机
一致性hash与hash槽的区别、数据倾斜,redis三种常见的分区实现方案、选举从机变主机
哨兵模式(备机一般不对外提供服务)集群不能水平扩展,需要额外的sentinel服务,ratf算法选举新领头哨兵
分布式锁三种实现
redisson用的最多
DB主键,但是过期清除是个问题
zk的临时节点
zookeeper
分布式协调系统,leader保证写的原子性和顺序性,临时节点和持久节点,watch监听器一次性使用
分组管理,分布式锁,分布式配置
主从架构,leader集群搭建,所有操作统一经过leader进行以队列保证顺序性
网络协议
https
四次握手、证书、服务器私钥和公钥的作用、OS内置CA证书、java的https请求需提前加载根证书、对称和非对称、CA对公钥加密后的签名
Restful接口规范
表象层状态转移:客户端通过http协议对处于服务端的表象层(资源)进行状态转移(改变)
uri资源定位不应该包括动词,动作应该通过http协议的METHOD来表示
API接口
接口安全:xss攻击、https;接口幂等性;restful接口
java多线程并发
java实现原子性的两种方式:锁和CAS(lock也是cas实现)
synchronized
CAS
Lock
Atomic包
JUC同步工具
基于AQS
Lock
ReentrantLock 原理:AQS(volatile state+cas更新+SupportLock.park())
StampedLock
ReentrantReadWriteLock,原理:AQS中的state高16位维护读锁个数,第16位维护写锁个数
CountDownLatch 递减门闩,aqs中的state是计数器,await将当前队列加入等待队列,并调用park,
countdown方法中当state cas操作后为0,则调用unpark,控制线程执行顺序
countdown方法中当state cas操作后为0,则调用unpark,控制线程执行顺序
Condition,能够使的满足条件的线程等待await或者唤醒signalAll,多维护了ConditionObject中的双向等待链表,signalAll会将node(持有thread引用)从condition队列中移到aqs等待队列中,取争抢锁
CyclicBarrier线程栅栏:概念理解:栅栏:等待的人数够了,就发一次车,不够就一直等待
Semaphore信号量
acquire方法限流,Semaphore信号量原理:state是允许的个数
,每个线程来state通过cas减1操作,如果state减到小于0,则说明线程数大于锁数,应该入aqs等待队列,然后park
,每个线程来state通过cas减1操作,如果state减到小于0,则说明线程数大于锁数,应该入aqs等待队列,然后park
ThreadLocal线程本地变量,原理 Thread-->localMap--->ThreadLocal的内部类-->put时put到线程的localMap中
ForkJoinTask
LockSupport
unsafe中的方法,线程等待时不再像wait那样需要获得锁,放入os的等待队列,
不再进行调度,唤醒时可以准确指定某个线程(notify不行),unpark可以在park前调用,导致park失效,
Unsafe类提供了硬件级别的原子操作,cas都是使用的该类的方法,提供了一些绕开JVM的更底层功能,类似直接的c++操作,使用不安全,分配的内存gc不会管理,需要手动释放,官方不建议使用
不再进行调度,唤醒时可以准确指定某个线程(notify不行),unpark可以在park前调用,导致park失效,
Unsafe类提供了硬件级别的原子操作,cas都是使用的该类的方法,提供了一些绕开JVM的更底层功能,类似直接的c++操作,使用不安全,分配的内存gc不会管理,需要手动释放,官方不建议使用
基本概念
sleep,yield,join ,状态,状态转换,wait/notify 等待通知模型,notify不释放锁
synchronize实现
synchronized在jvm中没有具体的规定如何实现,hotspot实现:对象头里markword中锁标记,
锁升级,非临界区代码(方法)不会阻塞,异常会释放锁(代码会退出),重量级锁的原理,ObjectMonitor
锁升级,非临界区代码(方法)不会阻塞,异常会释放锁(代码会退出),重量级锁的原理,ObjectMonitor
线程停止, interrupt+throw e或者return,isInterrupted(不清除中断标志),interrupted(清除中断标志)
线程实现的三种方式:Thread 、Runnable和Callable异同点
同步容器
Collection
List
Set
HashSet
内部维护了一个HashMap,用于add的值就是map的key,map的value是个默认的Object
SortedSet
TreeSet
内部维护的是treeMap,红黑树实现,天然排序
Queue
BlockingQueue,使用的是Condition
DelayQueue
按时间调度线程,内部维护了一个priorityqueue按照延迟时间排序,然后take时取出具体的延迟时间,
调用condition.awaitNanos(time)当线程延迟对应的时间后执行,无界
调用condition.awaitNanos(time)当线程延迟对应的时间后执行,无界
priorityQueue
优先级的队列,元素必须实现comparable接口的compareTo方法,在put方法中对元素调用compareTo比较排序,
而与入队的时间顺序无关,无界(内部有扩容)
而与入队的时间顺序无关,无界(内部有扩容)
ArrayListBlockingQueue
使用ReentrantLock+2个Condition,take时调用 notEmpty.await();dequue时调用 notFull.signal();
put时相反,数组实现的有界队列
put时相反,数组实现的有界队列
Linkedlistblockingqueue
带头节点的链表+ReentrantLock+2个Condition实现,阻塞原理同arraylistblockingqueue,无界
SynchronousQueue
容量为零,用于两个线程交换数据,put一个后,如果没有take,那么生产方会一直等待,
CAS+LockSupport.park实现阻塞,其中数据是通过Node(next)进行维护
CAS+LockSupport.park实现阻塞,其中数据是通过Node(next)进行维护
ConcurrentLinkedQueue
CAS
Map
HashMap
看java基础中的源码解释,红黑树是一种黑色节点完美平衡的二叉查找树,插入需要按照二叉查找树插入+自旋
HashTable
get和put加锁synchronize
TreeMap
红黑树
ConcurrentMap
ConcurrentHashMap
1.通过10线程读取一千万数据,结果是chm的写与hashtable类似,
而读效率高了一个数量级,原因是写的时候要做各种判断如树的结构变动,
读的时候线程读不同的key数据互不影响,而hashtable会阻塞;
2.红黑树
而读效率高了一个数量级,原因是写的时候要做各种判断如树的结构变动,
读的时候线程读不同的key数据互不影响,而hashtable会阻塞;
2.红黑树
ConcurrentSkiplistMap
排序了的concurrenthashmap,
使用了跳表
使用了跳表
线程池
ThreadPoolExecutor
自定义线程池的7个参数:
总体的原理是通过创建的线程来执行提交的任务的run方法
ForkJoinPool
ExecutorService
定义了跟线程生命周期相关的方法,如shutdown.submit等
Excutors
只有一个exucute方法,子类实现用来真正执行线程,该接口将线程的定义和执行分开
常用线程池
SingleThreadExcutor顺序执行任务,FixeTreadExcutor,CachedThreadPool 生成的线程数不做限制,来一个new一个线程执行,ScheduledThreadPoolExecutor
ParallelStreamAPI
使用了forkjoinPool
Future
future中接收outcome,get阻塞是通过cas+SupportLock+volatile state做线程间通知,
异步执行,执行完后会存储结果
异步执行,执行完后会存储结果
FutureTask
即实现了future也实现了runnable
网络IO
BIO
accept和read操作都是阻塞,如果要改成多线程,那么主线程accept然后子线程read,会每个连接会创建一个线程,并发不高有单机10k问题(同步阻塞)
NIO
new IO accept和read不再阻塞,而是返回-1或者整数,缺点:需要死循环进行系统调用(accept和read)(系统调用次数增多),当连接越来越多,遍历所有的Client就是O(N)的时间复杂度;优点:有效节省线程,不像BIO,一个连接一个线程(同步非阻塞)
多路复用器
概念:一次系统调用将所有IO连接的状态都返回(重点;只能返回状态),而NIO一次系统调用只能知道一条连接的状态,优点:相比NIO省下了多次系统调用(同步非阻塞)
实现分类:
select和poll
epoll
与select和poll差别1:内核开辟空间,红黑树保存所有建立的连接,不用再每次都进行传入fds;
差别2:有数据来时,会随着网卡的中断,cpu会将准备好的有数据的fds单独拷贝到一个链表中,epoll调用时,直接返回该链表即可,不用再遍历所有的fds
差别2:有数据来时,会随着网卡的中断,cpu会将准备好的有数据的fds单独拷贝到一个链表中,epoll调用时,直接返回该链表即可,不用再遍历所有的fds
poll和epoll调用的内核过程:
https://blog.csdn.net/weixin_42410730/article/details/104500872
注意:无论NIO还是多路复用器,都是要遍历所有连接的状态的,区别在于NIO遍历所有连接,每个连接都要发系统调用,而多路复用则一次系统调用返回准备好的连接描述符,比NIO节省了系统调用的次数
同步异步阻塞非阻塞
linux目前没有内核级别的异步处理方案
Netty
ByteBuf
分为Unpool、Pool ,每种又细分Heap和direct
1; direct和heap区别:heap是在jvm堆上分配内存,从内核到堆上经过:内核-->本地内存-->jvm堆的拷贝;direct内存,在堆上生成一个对象,持有的引用是direct内存空间,少一次数据拷贝过程
2.unpool和pool区别:Unpool是每次通过底层new Byte[]数组实现(查看源码的)/或者unsafe申请direct空间;pool是每个线程绑定了一个Cache,所有的操作都在这个cache中,避免每次都申请空间,通过FastThreadLocal实现
3.ByteBuf.release(),用完之后要手动释放内存,内存回收并非实时的,连接数上来后可能会造成内存泄漏,netty异常,应由最后一次使用bytebuf的方法调用release(),参看官网说明:https://netty.io/wiki/reference-counted-objects.html,排查泄漏位置 得加参数-Dio.netty.leakDetectionLevel=advanced,最后一个handler可继承SimpleChannelInboundHandler,框架来release
1; direct和heap区别:heap是在jvm堆上分配内存,从内核到堆上经过:内核-->本地内存-->jvm堆的拷贝;direct内存,在堆上生成一个对象,持有的引用是direct内存空间,少一次数据拷贝过程
2.unpool和pool区别:Unpool是每次通过底层new Byte[]数组实现(查看源码的)/或者unsafe申请direct空间;pool是每个线程绑定了一个Cache,所有的操作都在这个cache中,避免每次都申请空间,通过FastThreadLocal实现
3.ByteBuf.release(),用完之后要手动释放内存,内存回收并非实时的,连接数上来后可能会造成内存泄漏,netty异常,应由最后一次使用bytebuf的方法调用release(),参看官网说明:https://netty.io/wiki/reference-counted-objects.html,排查泄漏位置 得加参数-Dio.netty.leakDetectionLevel=advanced,最后一个handler可继承SimpleChannelInboundHandler,框架来release
组件
pipeline
拦截链,入栈从头到尾调用handler,出栈从尾到头执行handler
HandlerContext
ChannelHandlerContext 的作用是将handler和pipeline进行关联,一个pipeline中持有一个ChannelHandlerContext 链表,有上一个和下一个context的指针引用,每次addlast(handler)就会创建一个context,然后一个context中又持有一个handler实现,也就是一个handler对应一个context,而 pipeline只有一个,pipeline通过有context链表与handler关联起来
Channel
一个channel就是一个Socket连接(四元组)
ChannelHandler
消息处理器,为了解耦,分成多个,netty开发主要就是开发处理器
EventLoop
黏包和拆包
原因:发送和读取是相互独立的过程,应用中write数据后,只是提交到send_buf中,而非write一次,tcp就发送一次,缓存一些后就开始发送具体每次发送多少数据,由tpc通过滑动窗口进行控制,或者tcp的MSS分段或则IP的MTU分段导致,这样channelRead数据到的数据本身不一定是一个个message,但是前后两个buf之间数据是连续的,需要手动进行拆分,注意拆包和黏包是针对某一个tcp连接而言的
粘包问题的解决策略
1.定长消息,不够补齐;2Header+BOdyssey header定长,并指明body的长度;3消息头和消息尾部特殊符号结尾
现有工具:
1.ByteToMessageDecoder 有累加器,将不完整的消息留存下一次读 ;
2.LineBasedFramDecoder 基于行的解码器,读取换行符\r或者\r\n,客户端应该使用 System.getProperty("line.separator")屏蔽差异;
4.DelimiterBasedFrameDecoder 分隔符编码器,单个分隔符时,取分隔符前面的内容,没有分隔符的内容不会读取而是会被缓存等待下次分隔符来,当内容大于最大buf长度时异常,多个分隔符时,以取到最短内容为准,而非取两者之间的内容
5.FixedLengthFrameDecoder 固定长度解码器(小于长度的消息将被抛弃)
2.LineBasedFramDecoder 基于行的解码器,读取换行符\r或者\r\n,客户端应该使用 System.getProperty("line.separator")屏蔽差异;
4.DelimiterBasedFrameDecoder 分隔符编码器,单个分隔符时,取分隔符前面的内容,没有分隔符的内容不会读取而是会被缓存等待下次分隔符来,当内容大于最大buf长度时异常,多个分隔符时,以取到最短内容为准,而非取两者之间的内容
5.FixedLengthFrameDecoder 固定长度解码器(小于长度的消息将被抛弃)
jvm调优
https://www.processon.com/mindmap/604980437d9c08214c65ce42
kafka
生产者
发送原理、常用配置、
消费者
消息队列和发布订阅的实现、常用配置、分区和consumer的组内对应、重平衡
位移offset提交、简介多线程处理消费逻辑
消息轮训poll拉取消息的原理
broker
集群搭建、高吞吐低延迟的原因(epoll、reactor模型,页缓存、sendfile、顺序访问)
replicas对分区的分配、broker端参数、ISR
日志存储
offset消息三层结构存储、页缓存sendfile等
位移水位线、存储offset索引和timestamp索引
spring
springcloud
基本使用
各大组件的基本原理和实现
springclou gateway
应用
1.分发服务,2.身份认证,鉴权,3.过滤请求黑名单
4.监控,5.限流(网关限流和每个服务的限流、常见限流算法实现)
6. 负载均衡 使用ribbon,7.替换请求路径(新老地址兼容) 8 全局异常统一处理方案(@ControllerAdvice的starter或者网关切面)
限流算法
固定时间窗口、滑动时间窗口、令牌桶限流,redis都可实现
项目
微服务项目: 中转场、 适配各种物联网协议,数据接入服务:modbus、自定义协议等
服务拆分原则:隔离系统的变化点,尽量减少服务之间的影响,水平扩展,高聚低耦拆分原则:以业务为主,不主动 不拒绝不负责,粒度自定义,可大可小,原则就是服务的部署和更新不影响其他模块使用 AKF拆分的模型:
springboot
启动过程、自动装配原理、自定义过日志打印的starter
rabbitmq
四种exchange、队列
与kafka对比:吞吐量,有序性(如何保证?)、时效性(kafka存在batch发送,poll internal等慢但可调),消息回溯、消息可靠性、
一次性语义,https://baijiahao.baidu.com/s?id=1678867036216216885&wfr=spider&for=pc
一次性语义,https://baijiahao.baidu.com/s?id=1678867036216216885&wfr=spider&for=pc
0 条评论
下一页
为你推荐
查看更多
抱歉,暂无相关内容