P7P8架构师技能树
2024-07-09 14:53:01 2 举报
AI智能生成
P7+架构师技能树
作者其他创作
大纲/内容
服务以接口为粒度,对消费者屏蔽实现细节
支持多种注册中心,服务实例上下线实时感知
可配置多种路由规则,能实现灰度发布
随机
轮询
最少活跃调用数
一致性哈希
内置多种负载均衡策略
java SPI加强版
实现filter: SPI + MDC(基于ThreadLocal) -> 添加切面,可用于增加traceId
场景
dubbo SPI机制
高度可扩展
可视化运维与统计
可设置重试次数
Failover Cluster:失败重试
用于非幂等写
只调用一次,不重试,失败立即报错,快速返回
Failfast Cluster:快速失败
用于日志写入等操作
忽略调用异常,不报错
Failsafe Cluster:失败安全
对最终一致性要求较高的事务
失败后,开启定时任务,间隔一定时间无限重试
Failback Cluster:失败自动恢复
高实时性读操作,对资源消耗大
同时调用多个提供者
Forking Cluster:并行调用
用于通知提供者更新本地资源(缓存)
调用所有提供者,要求全部成功
Broadcast Cluster:广播调用
支持容错配置
服务缓存如何存储
功能与特点
消费方:代理类实现消费方定义的消费接口
提供者:向注册中心暴露服务地址
消费方和提供方用定义好的序列化和反序列化协议通信
消费方序列化后使用线程池处理调用
如何通信
底层通讯细节
与spring cloud的不同
dubbo
http
协议
gRPC
Spring Cloud
Thrift
RPC框架
AP模型
最大程度保证可用性,牺牲一致性
Eureka
CP模型
写入数据时,为保证一致性,需要同步半数以上节点才可响应客户端
重新选举时,为保证一致性,必须等到master选举成功后才可提供服务
单台服务器写入,会一定程度影响性能。
问题:牺牲一定的可用性
Zookeeper
Nacos
选型
功能:发布/订阅、负载均衡、命名服务、Master选举、分布式锁
更新操作全局有序(唯一时间戳zxid)
ZAB协议:master崩溃恢复时,会选举出拥有最大zxid的主机做为master,然后同步至半数以上follower后,进入广播模式正常工作(半数模式为了平衡强一致性和高可用性)
选举过程
Watcher机制-客户端可指定注册一个znode,当znode有变化,会向指定的客户端发送变更通知
基于Curator
怎样使用zookeeper做分布式锁
节点类型
zookeeper数据存储结构
zookeeper
Spring MVC
Spring Boot
工厂模式
Bean容器
Bean的生命周期
业务逻辑解耦
BeanDefinitionReader
通过反射实例化对象
BeanFactory
IOC Container
相关概念
IOC & DI
字节码增强
动态代理
Aspect
Joint point
Target
Weaving
概念
AOP
循环依赖
事件发布监听
问题
Spring Framework
令牌桶
预热功能底层怎么实现的
限流:滑动时间窗口算法怎么实现
Metrics功能集合是怎么实现的
Sentinel
Spring全家桶
Hibernate
MyBatis
ORM
SOA
基础框架
https://bk.tw.lvfukeji.com/wiki/RPC
对于java来讲,就是远程方法调用
定义
RPC
三次握手
四次挥手
Socket
基本操作单元
TCP
UDP
RESTful
HTTP
epoll多路复用
Netty
应用
网络
epoll在内核开辟专用空间
避免内核线程遍历N个socket连接(O(n))
事件驱动-网卡有数据到达,引发内核中断
epoll
NIO
BIO
IO模型
响应式
File -> Files Paths
文件操作
字节操作
字符操作
对象操作
网络操作
IO
内存型缓存
避免上下文切换与线程竞争
单工作线程模型(键值对指令读写)
IO线程多路并行(version 6 UP)
持久化
集群数据同步
异步删除(4.0以上的功能)
独立线程
epoll多路复用程序
消息放入socket队列
基于事件的回调机制
NIO多路复用
线程模型
数据量变多,哈希冲突变多,触发扩容rehash--使用2个hash表渐进式互拷方式
rehash过程
全局哈希表
不使用原生C char[],重建带字符串长度的结构体,查找速度从O(n)优化为O(1)
不会产生缓冲区溢出
空间预分配+根据剩余长度值域自动扩容+空间惰性回收,减少分配空间频繁变动的性能损耗
二进制安全
SDS简单状态字符
dict
上层实现为String
10000以内的数缓存,共享同一个对象
int
List、hash、sorted set三种数据类型的底层实现之一
ZipList压缩列表
多级索引跳转,加快定位和批量处理速度O(logn)-O(n)
sorted set排序功能实现方式
SkipList
Streams
radix tree
底层数据结构
原理
sds long
单值缓存、计数器、分布式ID(incr 数量)、setNx分布式锁
String
quicklist zipList
链表实现--队列、社交平台消息时间轴、海量数据有序写入和获取
List
dict、quickList
批量操作用户相关数据、购物车增删改查&数量统计
Hash
intSet dict
微信微博关注模型、多集合交并差集、抽奖应用-无序集合增删改
Set
skipList zipList dict
各分类排行榜
ZSet
基础数据类型
可用于推荐系统
布隆过滤器
位运算
bitmap
基数运算
hyperLogLog
地理坐标
GEO
用于消息队列
提供了以前没有的主从复制、发布订阅消息持久化
Streams【from 5.0】
高级数据类型
数据保存类型
RDB
AOF
刷盘机制
热点数据过期,大量请求增加数据库压力
增加热点数据缓存有效期,或设置永不过期
缓存击穿
恶意使用不存在的业务ID请求,穿透缓存的DB
缓存不存在的请求业务ID,防止穿透至数据库
布隆过滤器-能确定一定不存在的数据,过滤恶意请求
解决方案
缓存穿透
同一时间大量缓存过期,请求大量访问至数据库
分散缓存的过期时间
缓存雪崩
分布式锁:setNx分布式锁
String类型原子操作:incr incrby decr decrby incrbyfloat
redis事务:watch+redis transaction
并发问题
空间用完后,写操作报错,读操作正常
设置过期时间
过期时间配置
定时,定期,惰性
设置过期策略(4种?)
删除时机配置
8种淘汰策略
淘汰哪些
怎样避免
存储空间问题
一致性问题
常见问题
主从同步方式为异步方式
一定程度(主节点正常时)满足可用性(AP),满足最终一致性
特点
无法自动切换主从,主节点崩溃后需要人工介入
缺点
1主N从
1主N从+哨兵集群
高可用
部署,运维压力并不比Codis轻
资源浪费,从节点不提供服务,只做备份节点
在高可用的同时,并未真正提高并发量
可布署多个codis转发中间件实例
分片存储
所有key分为1024个槽位,用crc32算法 & 1024取模映射
槽位关系存储在zookeeper,redis扩缩容后,需要rehash & move keys,zookeeper可动态管理
自动调整每个redis对应的分片,达到流量均衡
自动均衡
拥有cluster方案没有的dashboard
原因key分散到不同的redis实例
不支持redis事务
不支持部分命令
原因:涉及到rehash和key迁移
增加了zookeeper集群管理成本
单个key不宜过大
时间节点原因:当时没有更好的集群方式,cluster刚上线,未形成最佳实践
多个代理节点:可以承载高并发
实时自动均衡:实现高可用
更实用的dashboard
选择原因
Codis
多主多从
完全去中心化
16384个槽位
槽位关系存储在redis节点中(自动写配置文件),不需要zookeeper
客户端连接redis集群时,会得到槽位信息
属于轻量化工具,运维负担轻
官方项目,持续维护
客户端访问槽位使用此算法,达到负载均衡
需要redis-trib手动调整槽位与节点对应关系
Cluster
集群
Redis
缓存
【不推荐】只有一台服务器存放队列消息,其他服务器只存放元数据,消费时需要从中心服务器同步消息数据
普通集群(非高可用)
【单纯追求稳定实用可采用】每个子节点各维护一个队列,队列中的数据互相同步保持一致,节点有同步成本,且会导致不一致问题
镜像集群(高可用)
RabbitMQ
多主多从集群(高可用)
RocketMQ
例:积分子系统与下单业务并非强关联,适合使用消息队列,降低系统耦合度
解耦
非必须即使完成的业务操作,适合异步操作,以降低响应时间,提升QPS
异步
适合使用消息队列,将消息缓冲至队列中。同时也能提高经济性
削峰
好处
相对慢,安全性最高
同步消息
快,可能会在发送环节丢消息
异步消息
单向发送
生产者发送消息的方式
推模式
拉模式
消费者消费消息的方式
基本模式
生产者使用队列选择器,同一ID发送至同一队列
消费者要使用顺序消费监听器参数(不能使用并发消费监听器)
顺序消息(局部有序)
广播消费
开源可改造
固定的延迟级别
sendDelayMessage()设置messageDelayLevel
延迟消息
只与发送端有关,批量发送
批量消息
tag过滤
SQL过滤(仅推模式)
过滤消息
使用本地事务检查机制,可实现下单后一定时间内缴费的业务模式
half消息:保证本地事务和发送消息的一致性
事务消息
消息样例
解决方式:集群
可用性降低
处理方式:生产方可靠发送:ack确认+重试+补偿
生产者发送消息到broker时,网络故障
消息持久化同步处理
broker接收消息后,未持久化时宕机
消费方可靠消费:ack确认同步删除消息
消费者拉取消息后,broker删除消息后,消费者未成功处理
消息丢失
broker返回的ack未及时送到,导致重发
消费者消费后返回的ack未及时送到,导致MQ重复投递消息
原因:根本原因是网络闪断不可达
重复消息一定存在,不可避免
必须要在数据库做唯一验证
强校验(如money相关)
可在redis中存储场景唯一标识
弱校验(如短信通知)
保证消费幂等性
处理方案
重复消息
无需保证全局顺序性
发送时使用匿名内部类的方法MessageQueueSelector.select()
生产者-》 broker,局部顺序性消息发送至同一队列
保证局部顺序性即可
顺序性如何保证
消费速度<生产速度
消费端代码错误
消费端性能过于低下
具体分析其严重程度
原因
检查消费方的消费速度,并修复
增加消费者数量
转发消息至容量更大的MQ集群,并增加消费者
处理方式
消息大量积压
个别消息处理不成功,导致整个事务部分成功部分失败
生产者发送hallf 消息,broker接收后持久化一条“待发送状态”记录,然后回复ack给生产端
生产端执行本地事务,结果发送给MQ
如果broker未收到本地事务执行结果消息,发消息回查本地事务
MQ根据结果决定发送或删除half消息
消费端执行操作,需注意执行的幂等性
重要业务采用事务消息
非重要业务可以记录日志
消息处理一致性问题
转存至死信队列
消息过期怎么办
broker只会投递相同topic 、tag标记的消息给消费者
消息过滤
系统复杂性提高,带来的问题
RocketMQ底层数据结构
https://github.com/apache/rocketmq/blob/master/docs/cn/features.md
RocketMQ的十二个特性
RocketMQ集群搭建、原理
怎样多线程消费
解决消费缓慢的问题
消息缓冲区满了怎么办
怎么实现一个延时队列
消息队列RocketMQ
原子性
一致性
隔离性
持久性
ACID原则
required
supports
mandatory
required_new
not_supported
never
nested
Spring事务传播机制
step1: 预提交,执行操作,并把结果返回事务协调者
step2: 事务管理器(协调者)根据step1的结果,决定提交事务或回滚事务
步骤
单应用跨库事务开源
分布式事务收费
Atomicos
上层实现
事务粒度过大,过多表被锁定,影响性能,不适合复杂业务
XA/JTA的实现
协调者与资源管理者如出现单点故障,会阻塞事务,需人工介入
【强一致性】2PC
在2PC基础上加入超时机制,资源管理者超时时会自动提交事务
其中一个资源管理者超时后自动提交,如果其他资源管理者回滚,就会出现不一致的情况
3PC
step1: 预留资源
step2: 确定资源(提交 or 回滚)
本质是2PC的一种
复杂项目应用场景中,性能高于2PC
会生成全局事务ID,用于记录当前事务链路
每个事务需要开发lock、cancel、confirm操作
锁粒度小,每个数据表的每个lock、cancel、confirm操作都是单独提交事务
实现最终一致性
记录事务日志
注意事务幂等性
使用注意事项
实现微服务事务
tcc-transaction
Bytetcc
阿里GTS商用
【柔性事务】TCC两阶段补偿
本地消息表
消息事务
最大努力通知
底层方案
业务0侵入
zk nacos redis eureka applo
需要配置命名服务
DB存储
架构
资源管理者(被调用的微服务,持有资源管理权)
RM
事务管理者(事务管理者--如果持有资源管理权,也同时是RM)
TM
角色
AT
SAGA
TCC
模式
seata
中间件/组件
分布式事务
脏读
不可重复读
幻读
并发事务产生的问题
更改数据时,加X锁
读未提交
改时加X锁,读时加s锁
【解决脏读】读已提交
【解决脏读、不可重复读】重复读取
读时加s锁,事务结束时才释放s锁
【解决所有】串行
数据库的事务隔离级别
多个线程可同时对相同数据加s锁,加s锁后的数据不可以再加x锁
所有线程(包括加s锁的线程)只能读,不能写
S锁(读锁,共享锁Share)
只有一个线程可对同一数据加x锁
持有x锁的线程可读可写,其他线程不可读不可写
x锁(写锁,排他锁exclusive)
innoDB内部锁机制
MySQL事务
事务
结构为类似于HashMap
不能缓存的:自定义函数、存储函数、用户变量、临时表
失效机制:表数据和结构变化
数据表更新频繁,导致缓存命中率低下时,打开缓存只会增加系统开销
可使用redis缓存,mysql缓存可减轻缓存击穿的影响
读多写少,可考虑开启缓存
如何衡量是否应打开缓存?
缓存是如何使用内存的?
如何控制缓存内存碎片化?
事务对查询缓存有何影响?
语法解析和预处理
优化器生成对应的查询计划
基于成本的查询优化器如何工作?
查询优化
通过调用handler API完成
执行查询引擎
返回结果给客户端,并缓存
查询过程
一些函数操作为产生困扰,与现实业务不一致,代码不易处理
为什么不建议字段使用NULL
只通过索引就可以查到需要的数据,不需要回表
索引覆盖
5.6以前:复合条件查询中第二条件需要上推到服务器层,然后逐条回表筛选; 5.6以后:搜索引擎层直接多条件筛选
索引下推
范围查询时,mysql提供一定的内存用于给查询顺序排序,用于符合物理内存中数据的顺序;查询优化器可以介入判断具体的SQL是否值得使用mrr
MRR - multi-range read
FIC - fast index creation
索引合并(5.0+)
特性
因与最左匹配不符合
like %a 或 like %a%
没加索引的字段会引发全表扫描,所有的字段直接全表匹配即可,如果部分字段还使用索引的话,反而增加操作复杂性,查询事务会更慢
违反最左匹配原则
组合索引,如果没使用最左侧的字段条件,不会使用索引
类型隐式转换,如varchar类型的条件没有单引号
条件中使用索引的字段加了运算或函数
数据量极少,如使用索引需要回表,全表扫描反而更快。
优化后没有必要使用索引
什么情况下设置了索引但无法使用?
加索引后比全表扫描性能提高不明显
字段区分性低
会引发索引的频繁更新,影响性能
更新很频繁的字段
不使用此字段作为查询条件,或不直接使用此字段作查询条件(加运算或函数)时,索引无意义
表容量偏小,全表扫描效率高
什么情况下不建议创建索引?
条件字段未加索引
索引值不唯一会全表扫描,导致锁表
其他导致全表扫描的操作都会锁表
更新操作
针对同一表,使用不同条件(无论是否有索引)并发删除,会导致锁表
删除操作
什么操作会导致表锁定
索引设计
从节点连接至主节点后,创建此线程,用于发送bin log给从节点
binary log dump thread
master
连接主节点,请求主库 bin log,接收发来的bin log更新,保存在本地的retry log
I/O thread
读取retry log,解析并执行,实现主从一致
SQL thread
slave
同步线程
问题:slave延迟
主库直接执行事务,不等待从库
【默认】异步模式(async mode)
主库commit事务后,等待至少一台从库retry log写入成功应答后,才返回客户同
半同步模式(semi-sync)【from 5.5】
增强半同步(after-snyc)【from 5.7】
严重影响主库性能
主库等待所有从库retry log写入成功后执行事务
全同步模式
同步模式
一主一从
提高读性能
一主多从
从节点做备份
多主一从【from 5.7】
互为对方的从库
双主复制
可分摊主库同步的压力,不会影响最终一致性
级联复制
主从模型
基于schema
5.6
同一个会话内多次操作不可并行
基于组提交的多线程方式
5.7
突破以上限制
8.0
并行复制模式
主从分离
数据库连接池
mycat
分库分表
redo
undo
日志
mysql
登录、鉴权、session管理,session共享
子主题
自身调优
jvm调优
tomcat
统一入口
服务路由
作用:特定微服务子节点存储特定的本地缓存
hash(业务ID)
定向流量分发
负载均衡
水平扩展流量分发
安全屏蔽
软防火墙
功能
F5
LVS
Nginx
流量网关
zuul
适应用IO密集型
异步响应式非阻塞
Spring Cloud Gateway
业务网关
多层网关
网关层
链路监测(全链路监控)
CDN
DNS
DFS分布式文件系统
对象存储
知识点:交换机、路由器、骨干网、城域网、IDC等概念
阿里云
基础设施
怎样查看metaspace
jps -l
jinfo -flag
jstat -class 进程ID 间隔时间 次数
jstat -gc 9999 100 5 GC情况
jmap -Heap 3333 堆各区域使用情况
jmap -histo 3333 | more 查看内存中java对象情况
jmap -dump
jhat -port <port> <file> 启动http服务分析dump文件
eclipse MAT dump分析工具
jstack pid 线程信息,可发现死锁线程
visualVM
tomcat加JMX配置,可使用visualVM远程功能
命令与工具
方法深度调用(调用方法层次过多,如深度递归,或递归缺少边界条件)
栈空间不足
java.lang.StackOverflowError
new 对象过多过大,或堆空间设置过小
堆空间不足
java.lang.OutOfMemeryError:Java heap space
回收时间过长(98%时间回收不到2%内存)
无法有效回收
java.lang.OutOfMemeryError: GC overhead limit exceeded
堆内存充足,不会启动GC(如nio直接内存缓冲区耗光)
堆外直接内存(一般是物理内存1/4)耗光
java.lang.OutOfMemeryError: Direct buffer memory
常见于高并发场景,超1024线程(linux默认)
不能创建本地线程
java.lang.OutOfMemeryError: unable to create new native thread
元空间(方法区、metaspace)加载了过多内容-源于失控的类加载、动态代理类加载等
元空间耗光
java.lang.OutOfMemeryError: Metaspace
OOM问题解析
JVM
对当前类的Class对象加锁
修饰静态类方法
对当前实例对象this加锁
修饰实例类方法
指定一个加锁的对象,给对象加锁
代码块
synchronized
经典同步器
Compare and swap
操作用户空间,不需要操作系统调度, JVM自身解决问题
使用stamped、markable
ABA问题
CAS
运用templete method
AQS
完全公平算法
CFS
JUC类原理:AQS+CAS+volatile
AtomicReference
AtomicStampedReference
AtomicMarkableReference
AtomicFieldUpdator
Atomic原子更新操作类
部分场合用来替代Sync
配合Condition队列使用
ReentantLock重入锁
LockSupport
ReadWriteLock
Lock集合
Latch门闩
Semaphore信号量
CyclicBarrier栅栏
Phaser阶段同步器
同步交换器
Exchanger
复制一份给写操作线程
写时加锁,读时不加锁,在保证线程安全的前提下,实现了最高读取性能
实现了最终一致性
CopyOnWriteArrayList(ArraySet)机制
继承自ReentrantLock ---> AQS(CLH队列) + CAS
1.7 (数组+链表)+ Segment分段锁机制
1.8 (数组+链表+红黑树)取消分段锁,直接使用优化后的sync(带锁升级机制)
ConcurrentHashMap
JUC--新的同步器
AQS底层原理分析
多线程同步
Disruptor
案例
缓存行对齐
JMM
JVM内部实现,法力无边,不继承自ClassLoader
加载jre/lib核心包,例如rt.jar
根加载器
BootstrapClassLoader
加载jre/lib/ext
扩展类加载器
ExtClassLoader
加载自己开发的或第三方Class、jar
系统类加载器
AppClassLoader
ClassLoader
目的
怎样打破双亲委派
双亲委派
类的加载
HashMap链表进化为红黑树为什么选择阈值为8
普通引用
强引用
堆空间不足时,有新对象进入,软引用的对象空间会被释放
适合当缓存
SoftReference的成员变量
软引用
只要有GC就回收
可解决内存泄漏问题
WeakReference的成员变量
弱引用
初始化一个虚引用对象时,需要在参数里同时指定一个Queue
当虚引用的对象被回收时,会向Queue发一个消息
用于监控堆外内存的对象是否被回收,如果被回收就清理一下
PhantomReference的成员变量
虚引用
强、软、弱、虚引用
google guava
类库
java基础
排序算法
分治法
贪心算法
动态规划
源随机函数->0,1随机函数->拼接2进制数->丢弃目标函数返回值范围外的值
随机数转换
位运算相关题目应用
限流
双端队列
扩展
滑动窗口算法
滑动时间窗口算法
雪花算法
布谷鸟算法
布隆过滤器算法
KNN算法
推荐算法
算法
文件操作、第三方调用
非关链事务落库异步
异步化--消息队列
超过3个表禁止join
唯一索引能避免脏数据,且能明显提高查找速度,对insert的速度损耗可忽略
需要join的字段要保持类型一致,并且要有索引
varchar字段索引一定要指定索引长度
不可以使用左端模糊查询
控制结果集的大小
索引B+tree结构和原理,与B树的区别
数据库查询优化
并发--web应用架构本身就是并发执行的,内部可以根据实际情况启动线程池
压测并发现关键性能瓶颈
过滤不合法请求
JVM优化
线程安全问题
日活、pv uv
超卖问题
三高、多线程
可用性
分区容错性
CAP理论
基本可用
软状态
最终一致性
BASE理论
SOA与微服务
分布式限流
nginx ip hash
aliyun 植入cookis
粘性session
tomcat本身的集群广播方式
粘性session + redis备份共享
redis共享
session持久化至数据库
SpringSession + Zookeeper发布订阅
session复制
分布式session
round robbin
weighted round robbin
least connections
weighted least connections
random
ip hash
策略
四层网络层
不支持uri
基于硬件
七层应用层
支持uri
基于软件
NGINX
方案
一致性哈希的原理
X轴:水平复制(负载均衡)+ Y轴:微服务拆分(按业务功能拆分) + Z轴:数据分区
AKF拆分原则
业务解耦,独立性
团队管理层面
效率层面,并行+快速迭代
出于产品设计考量、工程管理考量,技术非主要因素
前后端分离
业务数据缓存、session不应存在于本地server,应转移至分布式中间件中
服务无状态
传输数据格式可读性强,https安全性强
RESTful风格服务
微服务四大设计原则
未来一段时间产品将会达到的并发量、同时在线人数、日活数
未来数据量
大规模系统容量评估
容灾
热部署
信息安全三要素CIA
架构设计的现实因素
组件的定义
组件的核心功能
组件的底层核心技术:包含网络通信方式、底层算法、数据类型、存储结构、线程模型等
组件的性能特点:存储量、时间复杂度、并发量
横向对比的优势
引入此技术为了解决什么问题
此技术是如何解决系统难题的
除了解决系统问题之外,此技术还有什么经典应和场景
引入组件会带来的问题、风险、成本
如何解决这些问题
技术选型的考虑因素
多租户
数据隔离
安全
可配置
可扩展
热布署
SAAS设计
分布式、微服务理论 & 架构设计理论
需求分析
技术方案研讨评审
技术框架搭建
任务拆分
细分工期评估
工期评估
人员分配
可读性
复用性
健壮性
学习的过程,发现代码的问题的同时,也学习代码的亮点
review本身也能促使工程师能更认真地对待每一行代码
code review
每日进度回顾
是否阻塞:原因、是否需要介入
进度控制
单元测试怎么解决外部依赖的问题
研发自测
git+maven+jenkins
项目持续集成
测试环境测试+性能测试
beta测试+日志+流量重放,模拟线上真实用户行为测试
生产环境监控与事故定位
线上业务高峰期值班制度制订
事故复盘
管理
你是怎样带领团队高效工作的
重构后的代码怎样安全上线
我们常用的框架中,分别用了什么设计模式
设计模式
秒杀系统设计
怎样设计一个秒杀系统
微服务演化架构图
GPT
热点
Go
Java
Python
后端体系
前端体系
语言层面
设计原则
分布式架构设计
云架构设计
微服务架构设计
大数据架构设计
安全架构设计
性能优化
架构设计
系统架构设计
数据模型设计
接口设计
数据库设计
系统设计
P7P8java架构师技能树
0 条评论
回复 删除
下一页