大数跨境
0
0

阿里今年的薪资。。。

阿里今年的薪资。。。 macrozheng
2025-12-05
9
导读:阿里今年的薪资也在陆续开了,根据网上的爆料来看,今年后端薪资大概是。。。

Boot+Cloud项目学习:macrozheng.com

阿里今年的薪资也在陆续开了。根据网上的爆料来看,今年后端薪资大概是:白菜 26K小 SP 27~28K大 SP 29~30KSSP 是 31~32K。阿里集团是 16 薪,蚂蚁是 15 薪,菜鸟是 14 薪。某些部门会有 2k 房补,目前了解到的是淘天应该有。

现在还没大规模开,所以到时候实际开的有可能会和这个有一点小出入(个人预测白菜应该有 24k 和 25k 的)。

阿里的技术面试一般三轮或者两轮(极少四轮),技术面表现还不错的话就会约 HR 面。阿里的 HR 面懂得都懂,需要重视,不是到了 HR 面就比较稳了!

还有一点投递小技巧,阿里不同的部门一般是可以分开投递的。

阿里面试前几年大家感觉难度还比较大,这几年各种常见的八股都问烂的,认真准备一下整体上都不会有什么太大问题。

阿里的技术面一般是问实习、项目和常见的八股,一般一面更多的是问八股考察基础,到了后面会问更多实习和项目相关的问题。

那阿里的整体面试难度如何呢?给大家分享一篇阿里淘天的秋招面经,我精选了一二面中的一些比较典型的面试问题进行解答, 大家可以感受一下美团的面试难度如何。

概览

介绍自己的项目

作为求职者,我们可以从哪些方案去准备项目经历的回答:

  1. 梳理项目全貌
    • 一句话概括项目:用简洁的语言说清楚这个项目是做什么的(核心业务/目标)以及为什么要做(项目背景、要解决什么痛点)。
    • 核心功能与亮点:介绍项目的主要功能模块,特别是那些技术含量高或业务价值大的部分。
    • 技术架构与选型:能清晰地说明项目的整体技术架构(比如是微服务、单体?用了哪些中间件?),并解释为什么选择这些技术(技术选型的考量)。准备好可能被要求画简要架构图或解释关键模块设计。
  2. 明确你的角色与贡献
    • 你的角色:清楚说明你在项目中担任的角色(比如核心开发者、模块负责人、项目经理等)。
    • 具体职责:你具体负责了哪些模块或任务?
    • 关键贡献(重中之重!):用 STAR 法则 (Situation, Task, Action, Result) 来准备几个实际案例。重点突出你通过具体行动取得了可量化的成果或解决了关键问题,一定要具体场景,而非罗列技术。例如,“负责优化 XX 接口,通过 A、B、C 措施,将响应时间从 X 降低到 Y,提升了 Z% 的用户体验”。
  3. 准备解决问题的亮点案例
    • 挖掘挑战:回忆项目中遇到的最棘手的技术难题、性能瓶颈、或者复杂的业务逻辑实现。这个在面试中很可能会问到,例如面试官会问你:“面试中遇到了什么困难?如何解决的?”。
    • 展现思路:详细说明你是如何分析问题(用了什么工具?怎么定位的?)、思考解决方案(考虑了哪些方案?为什么选择最终方案?)、最终如何解决的,以及结果如何。
    • 提炼收获:从解决这个问题的过程中,你学到了什么?技术上有什么成长?或者对业务有了更深的理解?
  4. 深入理解关键技术:吃透你在这个项目中用到的技术(举个例子,你的项目经历使用了 Seata 来做分布式事务,那 Seata 相关的问题你要提前准备一下吧,比如说 Seata 支持哪些配置中心、Seata 的事务分组是怎么做的、Seata 支持哪些事务模式,怎么选择?)。

库存扣减这里为什么要用 Redis Lua 脚本?

在库存扣减这个典型的高并发场景下,我们使用 Redis Lua 脚本,主要是为了保证操作的原子性,从而从根本上避免超卖问题。

正常的库存扣减逻辑是 读库存->判断够不够->写回新库存。在高并发下,两个线程可能同时读到库存都够,结果一个库存卖了两次,就超卖了。Lua 脚本能把这三步,打包成一个命令在 Redis 服务端一次性执行完。因为 Redis 是单线程执行命令,所以在跑这个脚本的期间,不会有其他命令插进来,这就保证了原子性。

不过, Lua 脚本依然存在下面这些缺陷:

  • 如果 Lua 脚本运行时出错并中途结束,之后的操作不会进行,但是之前已经发生的写操作不会撤销,所以即使使用了 Lua 脚本,也不能实现类似数据库回滚的原子性。
  • Redis Cluster 下 Lua 脚本的原子操作无法保证,原因是无法保证所有的 key 都在同一个 hash slot(哈希槽) 上。

Redis 和 MySQL 一致性如何保证?

缓存和数据库一致性是个挺常见的技术挑战。引入缓存主要是为了提升性能、减轻数据库压力,但确实会带来数据不一致的风险。绝对的一致性往往意味着更高的系统复杂度和性能开销,所以实践中我们通常会根据业务场景选择合适的策略,在性能和一致性之间找到一个平衡点。

下面单独对 Cache Aside Pattern(旁路缓存模式) 来聊聊。这是非常常用的一种缓存读写策略,它的读写逻辑是这样的:

  • 读操作
    1. 先尝试从缓存读取数据。
    2. 如果缓存命中,直接返回数据。
    3. 如果缓存未命中,从数据库查询数据,将查到的数据放入缓存并返回数据。
  • 写操作
    1. 先更新数据库。
    2. 再直接删除缓存中对应的数据。

图解如下:

如果更新数据库成功,而删除缓存这一步失败的情况的话,简单说有两个解决方案:

  1. 缓存失效时间(TTL - Time To Live)变短(不推荐,治标不治本):我们让缓存数据的过期时间变短,这样的话缓存就会从数据库中加载数据。另外,这种解决办法对于先操作缓存后操作数据库的场景不适用。
  2. 增加缓存更新重试机制(常用):如果缓存服务当前不可用导致缓存删除失败的话,我们就隔一段时间进行重试,重试次数可以自己定。不过,这里更适合引入消息队列实现异步重试,将删除缓存重试的消息投递到消息队列,然后由专门的消费者来重试,直到成功。虽然说多引入了一个消息队列,但其整体带来的收益还是要更高一些。

Redis 如何找到慢查询命令?

Redis 提供了一个内置的慢查询日志 (Slow Log) 功能,专门用来记录执行时间超过指定阈值的命令。这对于排查性能瓶颈、找出导致 Redis 阻塞的“慢”操作非常有帮助,原理和 MySQL 的慢查询日志类似。

在 redis.conf 文件中,我们可以使用 slowlog-log-slower-than 参数设置耗时命令的阈值,并使用 slowlog-max-len 参数设置耗时命令的最大记录条数。

当 Redis 服务器检测到执行时间超过 slowlog-log-slower-than 阈值的命令时,就会将该命令记录在慢查询日志(slow log)中,这点和 MySQL 记录慢查询语句类似。当慢查询日志超过设定的最大记录条数之后,Redis 会把最早的执行命令依次舍弃。

⚠️ 注意:由于慢查询日志会占用一定内存空间,如果设置最大记录条数过大,可能会导致内存占用过高的问题。

slowlog-log-slower-than 和 slowlog-max-len 的默认配置如下(可以自行修改):

# The following time is expressed in microseconds, so 1000000 is equivalent
# to one second. Note that a negative number disables the slow log, while
# a value of zero forces the logging of every command.
slowlog-log-slower-than 10000

# There is no limit to this length. Just be aware that it will consume memory.
# You can reclaim memory used by the slow log with SLOWLOG RESET.
slowlog-max-len 128

除了修改配置文件之外,你也可以直接通过 CONFIG 命令直接设置:

# 命令执行耗时超过 10000 微妙(即10毫秒)就会被记录
CONFIG SET slowlog-log-slower-than 10000
# 只保留最近 128 条耗时命令
CONFIG SET slowlog-max-len 128

获取慢查询日志的内容很简单,直接使用 SLOWLOG GET 命令即可。

127.0.0.1:6379> SLOWLOG GET #慢日志查询
 1) 1) (integer) 5
   2) (integer) 1684326682
   3) (integer) 12000
   4) 1) "KEYS"
      2) "*"
   5) "172.17.0.1:61152"
   6) ""
  // ...

慢查询日志中的每个条目都由以下六个值组成:

  1. 唯一 ID: 日志条目的唯一标识符。
  2. 时间戳 (Timestamp): 命令执行完成时的 Unix 时间戳。
  3. 耗时 (Duration): 命令执行所花费的时间,单位是微秒
  4. 命令及参数 (Command): 执行的具体命令及其参数数组。
  5. 客户端信息 (Client IP:Port): 执行命令的客户端地址和端口。
  6. 客户端名称 (Client Name): 如果客户端设置了名称 (CLIENT SETNAME)。

SLOWLOG GET 命令默认返回最近 10 条的的慢查询命令,你也自己可以指定返回的慢查询命令的数量 SLOWLOG GET N

下面是其他比较常用的慢查询相关的命令:

# 返回慢查询命令的数量
127.0.0.1:6379> SLOWLOG LEN
(integer) 128
# 清空慢查询命令
127.0.0.1:6379> SLOWLOG RESET
OK

列举一些 Redis 中 O(n) 的命令

Redis 中的大部分命令都是 O(1)时间复杂度,但也有少部分 O(n) 时间复杂度的命令,例如:

  • KEYS *:会返回所有符合规则的 key。
  • HGETALL:会返回一个 Hash 中所有的键值对。
  • LRANGE:会返回 List 中指定范围内的元素。
  • SMEMBERS:返回 Set 中的所有元素。
  • SINTER/SUNION/SDIFF:计算多个 Set 的交集/并集/差集。
  • ……

由于这些命令时间复杂度是 O(n),有时候也会全表扫描,随着 n 的增大,执行耗时也会越长,从而导致客户端阻塞。不过, 这些命令并不是一定不能使用,但是需要明确 N 的值。另外,有遍历的需求可以使用 HSCANSSCANZSCAN 代替。

缓存穿透和缓存击穿有什么区别?如何解决?

缓存穿透中,请求的 key 既不存在于缓存中,也不存在于数据库中。

缓存穿透
缓存穿透

缓存击穿中,请求的 key 对应的是 热点数据 ,该数据 存在于数据库中,但不存在于缓存中(通常是因为缓存中的那份数据已经过期) 。

缓存击穿
缓存击穿

缓存穿透的常见解决方法

  1. 缓存无效 key :如果缓存和数据库都查不到某个 key 的数据,就写一个到 Redis 中去并设置过期时间。
  2. 布隆过滤器 :在缓存层之前加一层布隆过滤器,把所有真实存在的 key(例如所有商品 id、用户 id 等)预热进去。
  3. 接口限流 + 黑名单 :对单个 IP、UID、设备指纹等维度做限流(如 1 秒最多 100 次),触发限流阈值后加入临时/永久黑名单,直接 403。限流的具体方案可以参考这篇文章:服务限流详解[1]。

缓存击穿的常见解决方法

  1. 永不过期(不推荐):设置热点数据永不过期或者过期时间比较长。
  2. 提前预热(推荐):针对热点数据提前预热,将其存入缓存中并设置合理的过期时间比如秒杀场景下的数据在秒杀结束之前不过期。
  3. 加锁(看情况):在缓存失效后,通过设置互斥锁确保只有一个请求去查询数据库并更新缓存。

遇到过 MySQL 慢查询问题吗?怎么解决的?

为了优化慢 SQL ,我们首先要找到哪些 SQL 语句执行速度比较慢。

MySQL 慢查询日志是用来记录 MySQL 在执行命令中,响应时间超过预设阈值的 SQL 语句。因此,通过分析慢查询日志我们就可以找出执行速度比较慢的 SQL 语句。

出于性能层面的考虑,慢查询日志功能默认是关闭的,你可以通过以下命令开启:

# 开启慢查询日志功能
SET GLOBAL slow_query_log = 'ON';
# 慢查询日志存放位置
SET GLOBAL slow_query_log_file = '/var/lib/mysql/ranking-list-slow.log';
# 无论是否超时,未被索引的记录也会记录下来。
SET GLOBAL log_queries_not_using_indexes = 'ON';
# 慢查询阈值(秒),SQL 执行超过这个阈值将被记录在日志中。
SET SESSION long_query_time = 1;
# 慢查询仅记录扫描行数大于此参数的 SQL
SET SESSION min_examined_row_limit = 100;

设置成功之后,使用 show variables like 'slow%'; 命令进行查看。

| Variable_name       | Value                                |
+---------------------+--------------------------------------+
| slow_launch_time    | 2                                    |
| slow_query_log      | ON                                   |
| slow_query_log_file | /var/lib/mysql/ranking-list-slow.log |
+---------------------+--------------------------------------+
3 rows in set (0.01 sec)

我们故意在百万数据量的表(未使用索引)中执行一条排序的语句:

SELECT `score`,`name` FROM `cus_order` ORDER BY `score` DESC;

确保自己有对应目录的访问权限:

chmod 755 /var/lib/mysql/

查看对应的慢查询日志:

 cat /var/lib/mysql/ranking-list-slow.log

我们刚刚故意执行的 SQL 语句已经被慢查询日志记录了下来:

# Time: 2022-10-09T08:55:37.486797Z
# User@Host: root[root] @  [172.17.0.1]  Id:    14
# Query_time: 0.978054  Lock_time: 0.000164 Rows_sent: 999999  Rows_examined: 1999998
SET timestamp=1665305736;
SELECT `score`,`name` FROM `cus_order` ORDER BY `score` DESC;

这里对日志中的一些信息进行说明:

  • Time :被日志记录的代码在服务器上的运行时间。
  • User@Host:谁执行的这段代码。
  • Query_time:这段代码运行时长。
  • Lock_time:执行这段代码时,锁定了多久。
  • Rows_sent:慢查询返回的记录。
  • Rows_examined:慢查询扫描过的行数。

实际项目中,慢查询日志通常会比较复杂,我们需要借助一些工具对其进行分析。像 MySQL 内置的 mysqldumpslow 工具就可以把相同的 SQL 归为一类,并统计出归类项的执行次数和每次执行的耗时等一系列对应的情况。

找到了慢 SQL 之后,我们可以通过 EXPLAIN 命令分析对应的 SELECT 语句:

mysql> EXPLAIN SELECT`score`,`name`FROM`cus_order`ORDERBY`score`DESC;
+----+-------------+-----------+------------+------+---------------+------+---------+------+--------+----------+----------------+
| id | select_type | table     | partitions | type | possible_keys | key  | key_len | ref  | rows   | filtered | Extra          |
+----+-------------+-----------+------------+------+---------------+------+---------+------+--------+----------+----------------+
|  1 | SIMPLE      | cus_order | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 997572 |   100.00 | Using filesort |
+----+-------------+-----------+------------+------+---------------+------+---------+------+--------+----------+----------------+
1 row in set1warning (0.00 sec)

比较重要的字段说明:

  • select_type :查询的类型,常用的取值有 SIMPLE(普通查询,即没有联合查询、子查询)、PRIMARY(主查询)、UNION(UNION 中后面的查询)、SUBQUERY(子查询)等。
  • table :表示查询涉及的表或衍生表。
  • type :执行方式,判断查询是否高效的重要参考指标,结果值从差到好依次是:ALL < index < range ~ index_merge < ref < eq_ref < const < system。
  • rows : SQL 要查找到结果集需要扫描读取的数据行数,原则上 rows 越少越好。
  • ......

什么是反射?应用场景是?

简单来说,Java 反射 (Reflection) 是一种在程序运行时,动态地获取类的信息并操作类或对象(方法、属性)的能力

通常情况下,我们写的代码在编译时类型就已经确定了,要调用哪个方法、访问哪个字段都是明确的。但反射允许我们在运行时才去探知一个类有哪些方法、哪些属性、它的构造函数是怎样的,甚至可以动态地创建对象、调用方法或修改属性,哪怕这些方法或属性是私有的。

正是这种在运行时“反观自身”并进行操作的能力,使得反射成为许多通用框架和库的基石。它让代码更加灵活,能够处理在编译时未知的类型。

我们平时写业务代码可能很少直接跟 Java 的反射(Reflection)打交道。但你可能没意识到,你天天都在享受反射带来的便利!很多流行的框架,比如 Spring/Spring Boot、MyBatis 等,底层都大量运用了反射机制,这才让它们能够那么灵活和强大。

下面简单列举几个最场景的场景帮助大家理解。

1.依赖注入与控制反转(IoC)

以 Spring/Spring Boot 为代表的 IoC 框架,会在启动时扫描带有特定注解(如 @Component@Service@Repository@Controller)的类,利用反射实例化对象(Bean),并通过反射注入依赖(如 @Autowired、构造器注入等)。

2.注解处理

注解本身只是个“标记”,得有人去读这个标记才知道要做什么。反射就是那个“读取器”。框架通过反射检查类、方法、字段上有没有特定的注解,然后根据注解信息执行相应的逻辑。比如,看到 @Value,就用反射读取注解内容,去配置文件找对应的值,再用反射把值设置给字段。

3.动态代理与 AOP

想在调用某个方法前后自动加点料(比如打日志、开事务、做权限检查)?AOP(面向切面编程)就是干这个的,而动态代理是实现 AOP 的常用手段。JDK 自带的动态代理(Proxy 和 InvocationHandler)就离不开反射。代理对象在内部调用真实对象的方法时,就是通过反射的 Method.invoke 来完成的。

public class DebugInvocationHandler implements InvocationHandler {
    privatefinal Object target; // 真实对象

    public DebugInvocationHandler(Object target) this.target = target; }

    // proxy: 代理对象, method: 被调用的方法, args: 方法参数
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("切面逻辑:调用方法 " + method.getName() + " 之前");
        // 通过反射调用真实对象的同名方法
        Object result = method.invoke(target, args);
        System.out.println("切面逻辑:调用方法 " + method.getName() + " 之后");
        return result;
    }
}

4.对象关系映射(ORM)

像 MyBatis、Hibernate 这种框架,能帮你把数据库查出来的一行行数据,自动变成一个个 Java 对象。它是怎么知道数据库字段对应哪个 Java 属性的?还是靠反射。它通过反射获取 Java 类的属性列表,然后把查询结果按名字或配置对应起来,再用反射调用 setter 或直接修改字段值。反过来,保存对象到数据库时,也是用反射读取属性值来拼 SQL。

WebSocket 与短轮询、长轮询的区别

这三种方式,都是为了解决“客户端如何及时获取服务器最新数据,实现实时更新”的问题。它们的实现方式和效率、实时性差异较大。

1.短轮询(Short Polling)

  • 原理:客户端每隔固定时间(如 5 秒)发起一次 HTTP 请求,询问服务器是否有新数据。服务器收到请求后立即响应。
  • 优点:实现简单,兼容性好,直接用常规 HTTP 请求即可。
  • 缺点
    • 实时性一般:消息可能在两次轮询间到达,用户需等到下次请求才知晓。
    • 资源浪费大:反复建立/关闭连接,且大多数请求收到的都是“无新消息”,极大增加服务器和网络压力。

2.长轮询(Long Polling)

  • 原理:客户端发起请求后,若服务器暂时无新数据,则会保持连接,直到有新数据或超时才响应。客户端收到响应后立即发起下一次请求,实现“伪实时”。
  • 优点
    • 实时性较好:一旦有新数据可立即推送,无需等待下次定时请求。
    • 空响应减少:减少了无效的空响应,提升了效率。
  • 缺点
    • 服务器资源占用高:需长时间维护大量连接,消耗服务器线程/连接数。
    • 资源浪费大:每次响应后仍需重新建立连接,且依然基于 HTTP 单向请求-响应机制。

3. WebSocket

  • 原理:客户端与服务器通过一次 HTTP Upgrade 握手后,建立一条持久的 TCP 连接。之后,双方可以随时、主动地发送数据,实现真正的全双工、低延迟通信。
  • 优点
    • 实时性强:数据可即时双向收发,延迟极低。
    • 资源效率高:连接持续,无需反复建立/关闭,减少资源消耗。
    • 功能强大:支持服务端主动推送消息、客户端主动发起通信。
  • 缺点
    • 使用限制:需要服务器和客户端都支持 WebSocket 协议。对连接管理有一定要求(如心跳保活、断线重连等)。
    • 实现麻烦:实现起来比短轮询和长轮询要更麻烦一些。
Websocket 示意图
Websocket 示意图

SSE 与 WebSocket 有什么区别?

SSE (Server-Sent Events) 和 WebSocket 都是用来实现服务器向浏览器实时推送消息的技术,让网页内容能自动更新,而不需要用户手动刷新。虽然目标相似,但它们在工作方式和适用场景上有几个关键区别:

  1. 通信方式:
    • SSE: 单向通信。只有服务器能向客户端(浏览器)发送数据。客户端不能通过同一个连接向服务器发送数据(需要发起新的 HTTP 请求)。
    • WebSocket: 双向通信 (全双工)。客户端和服务器可以随时互相发送消息,实现真正的实时交互。
  2. 底层协议:
    • SSE: 基于标准的 HTTP/HTTPS 协议。它本质上是一个“长连接”的 HTTP 请求,服务器保持连接打开并持续发送事件流。不需要特殊的服务器或协议支持,现有的 HTTP 基础设施就能用。
    • WebSocket: 使用独立的 ws:// 或 wss:// 协议。它需要通过一个特定的 HTTP "Upgrade" 请求来建立连接,并且服务器需要明确支持 WebSocket 协议来处理连接和消息帧。
  3. 实现复杂度和成本:
    • SSE:实现相对简单,主要在服务器端处理。浏览器端有标准的 EventSource API,使用方便。开发和维护成本较低。
    • WebSocket:稍微复杂一些。需要服务器端专门处理 WebSocket 连接和协议,客户端也需要使用 WebSocket API。如果需要考虑兼容性、心跳、重连等,开发成本会更高。
  4. 断线重连:
    • SSE:浏览器原生支持。EventSource API 提供了自动断线重连的机制。
    • WebSocket:需要手动实现。开发者需要自己编写逻辑来检测断线并进行重连尝试。
  5. 数据类型:
    • SSE:主要设计用来传输文本 (UTF-8 编码)。如果需要传输二进制数据,需要先进行 Base64 等编码转换成文本。
    • WebSocket:原生支持传输文本和二进制数据,无需额外编码。

为了提供更好的用户体验和利用其简单、高效、基于标准 HTTP 的特性,Server-Sent Events (SSE) 是目前大型语言模型 API(如 OpenAI、DeepSeek 等)实现流式响应的常用甚至可以说是标准的技木选择

这里以 DeepSeek 为例,我们发送一个请求并打开浏览器控制台验证一下:

可以看到,响应头应里包含了 text/event-stream,说明使用的确实是 SSE。并且,响应数据也确实是持续分块传输。

TCP/IP 四层模型

TCP/IP 四层模型 是目前被广泛采用的一种模型,我们可以将 TCP / IP 模型看作是 OSI 七层模型的精简版本,由以下 4 层组成:

  1. 应用层
  2. 传输层
  3. 网络层
  4. 网络接口层

需要注意的是,我们并不能将 TCP/IP 四层模型 和 OSI 七层模型完全精确地匹配起来,不过可以简单将两者对应起来,如下图所示:

TCP/IP 四层模型
TCP/IP 四层模型

关于每一层作用的详细介绍,请看 OSI 和 TCP/IP 网络分层模型详解(基础)[2] 这篇文章。

为什么网络要分层?

说到分层,我们先从我们平时使用框架开发一个后台程序来说,我们往往会按照每一层做不同的事情的原则将系统分为三层(复杂的系统分层会更多):

  1. Repository(数据库操作)
  2. Service(业务操作)
  3. Controller(前后端数据交互)

复杂的系统需要分层,因为每一层都需要专注于一类事情。网络分层的原因也是一样,每一层只专注于做一类事情。

好了,再来说回:“为什么网络要分层?”。我觉得主要有 3 方面的原因:

  1. 各层之间相互独立:各层之间相互独立,各层之间不需要关心其他层是如何实现的,只需要知道自己如何调用下层提供好的功能就可以了(可以简单理解为接口调用)。这个和我们对开发时系统进行分层是一个道理。
  2. 提高了灵活性和可替换性:每一层都可以使用最适合的技术来实现,你只需要保证你提供的功能以及暴露的接口的规则没有改变就行了。并且,每一层都可以根据需要进行修改或替换,而不会影响到整个网络的结构。这个和我们平时开发系统的时候要求的高内聚、低耦合的原则也是可以对应上的。
  3. 大问题化小:分层可以将复杂的网络问题分解为许多比较小的、界线比较清晰简单的小问题来处理和解决。这样使得复杂的计算机网络系统变得易于设计,实现和标准化。 这个和我们平时开发的时候,一般会将系统功能分解,然后将复杂的问题分解为容易理解的更小的问题是相对应的,这些较小的问题具有更好的边界(目标和接口)定义。

我想到了计算机世界非常非常有名的一句话,这里分享一下:

计算机科学领域的任何问题都可以通过增加一个间接的中间层来解决,计算机整个体系从上到下都是按照严格的层次结构设计的。

TCP 和 UDP 区别

特性
TCP
UDP
连接性
面向连接
无连接
可靠性
可靠
不可靠 (尽力而为)
状态维护
有状态
无状态
传输效率
较低
较高
传输形式
面向字节流
面向数据报 (报文)
头部开销
20 - 60 字节
8 字节
通信模式
点对点 (单播)
单播、多播、广播
常见应用
HTTP/HTTPS, FTP, SMTP, SSH
DNS, DHCP, SNMP, TFTP, VoIP, 视频流

HTTP 和 HTTPS 有什么区别?(重要)

HTTP 和 HTTPS 对比
HTTP 和 HTTPS 对比
  • 端口号:HTTP 默认是 80,HTTPS 默认是 443。
  • URL 前缀:HTTP 的 URL 前缀是 http://,HTTPS 的 URL 前缀是 https://
  • 安全性和资源消耗:HTTP 协议运行在 TCP 之上,所有传输的内容都是明文,客户端和服务器端都无法验证对方的身份。HTTPS 是运行在 SSL/TLS 之上的 HTTP 协议,SSL/TLS 运行在 TCP 之上。所有传输的内容都经过加密,加密采用对称加密,但对称加密的密钥用服务器方的证书进行了非对称加密。所以说,HTTP 安全性没有 HTTPS 高,但是 HTTPS 比 HTTP 耗费更多服务器资源。
  • SEO(搜索引擎优化):搜索引擎通常会更青睐使用 HTTPS 协议的网站,因为 HTTPS 能够提供更高的安全性和用户隐私保护。使用 HTTPS 协议的网站在搜索结果中可能会被优先显示,从而对 SEO 产生影响。

Github上标星11K的微服务实战项目mall-swarm,全套 视频教程 来了!全套教程约26小时,共59期,如果你想学习目前最新的微服务技术栈,同时提高自己微服务项目的开发能力的话,不妨了解下,下面是项目的整体架构图,感兴趣的小伙伴可以点击链接 mall-swarm视频教程 加入学习。

整套 视频教程 的内容还是非常完善的,涵盖Spring Cloud核心组件、微服务项目实战、Kubernetes容器化部署等内容,你也可以点击链接 mall-swarm视频教程 了解更多内容。

【声明】内容源于网络
0
0
macrozheng
内容 1937
粉丝 0
macrozheng
总阅读105
粉丝0
内容1.9k