image frame

云原生之于服务端开发

     每个服务端开发人员都应该了解云原生。云原生视角,是一个全栈的服务端视角—自下而上从硬件设备到应用架构。在云原生视角下回过头来看服务端开发的问题,有点降维打击的感觉。现在看服务端开发的问题,再复杂的问题,也只是局部的一个点,很小的问题。

像专业开发人员那样调试程序

进程间通信的5种方式

以下是类UNIX操作系统(如Linux)中常见的5种通讯机制。

进程间通信的5种方式

     管道(Pipes):管道是指连接两个或多个进程的输入和输出,常用于流式传输数据。例如,shell脚本通常使用管道运算符“|” 将命令链接在一起:

1
cat /var/log/syslog | grep 'error' | less

     消息队列(Message Queues):消息队列通过允许进程以消息的形式交换数据来提供异步通信。写入队列的消息按先进先出的顺序处理。

例如,服务器可能将作业分派到队列中,消费守护进程从中拉取并独立处理。

     信号(Signals):信号提供了一种通知系统,能够让进程立即收到重要事件,如被强制终止。例如,SIGKILL提供了一种可靠的方法来结束无响应的应用程序。

     信号量(Semaphores):信号量是是一种在多线程环境中使用的同步机制,旨在确保多个线程不会同时访问同一块共享内存区域或其他临界资源。

     共享内存(Shared Memory):共享内存是允许直接访问共享内存区域,以便多个进程可以高效地读取和修改数据,而无需复制。一个示例用例是处理大型图像帧的程序,其中多个进程可以同时访问和处理图像的不同部分。

     这些IPC机制有时被组合在一起以实现高效的进程通信。

HTTPS是如何工作的

     超文本传输协议安全(HTTPS)是超文本传输协议(HTTP)的扩展。

     HTTPS使用传输层安全协议(TLS)来传输加密数据。如果数据在网上被劫持,劫持者得到的只是二进制代码。那么数据是如何加密和解密的呢?

HTTPS是如何工作的

  • 步骤1 - 客户端(浏览器)和服务器建立TCP连接。

  • 步骤2 - 客户端向服务器发送“客户端hello”。该消息包含一组必要的加密算法(密码套件)以及它可以支持的最新TLS版本。服务器通过发送“服务器hello”来响应,以便浏览器知道它是否支持算法和TLS版本。服务器然后向客户端发送SSL证书。证书包含公钥、主机名、过期日期等。客户端验证证书。

  • 步骤3 - 在验证SSL证书后,客户端生成会话密钥并使用公钥对其进行加密。服务器接收加密的会话密钥并使用私钥进行解密。

  • 步骤4 - 现在客户端和服务器都持有相同的会话密钥(对称加密),加密数据通过安全的双向通道进行传输。

     为什么HTTPS在数据传输期间会切换到对称加密?主要有两个原因:

  • 1、安全:非对称加密只适用于单向。这意味着如果服务器尝试将加密数据发送回客户端,任何人都可以使用公钥解密数据。

  • 2、服务器资源:非对称加密增加了大量的数学开销。它不适合长会话中的数据传输。

Java 开发常见面试知识点梳理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
1、Java 部分

设计模式:
单例模式(懒汉式、饿汉式、双重锁)
工厂模式(简单工厂、工厂方法、抽象工厂)
代理模式(静态代理、动态代理)
策略模式(解耦算法与业务)
观察者模式(发布-订阅模式)
装饰者模式(功能扩展)

并发:
Java 线程基础(线程创建、状态、生命周期)
线程池(ThreadPoolExecutor 原理、线程池优化)
并发工具类(CountDownLatch、CyclicBarrier、Semaphore)
锁机制(synchronized、ReentrantLock、公平锁、读写锁)
CAS 与原子操作(Atomic 类的实现原理、ABA 问题)
volatile 与内存可见性(happens-before 原则)
AQS(AbstractQueuedSynchronizer)原理(锁的底层实现)
并发容器(ConcurrentHashMap 原理、CopyOnWriteArrayList)

集合框架:
List(ArrayList、LinkedList 区别)
Set(HashSet、TreeSet、LinkedHashSet)
Map(HashMap、TreeMap、LinkedHashMap、ConcurrentHashMap)
Fail-fast 与 fail-safe(遍历过程中修改问题)
HashMap 的底层原理(链表转红黑树的条件)

JVM:
JVM 内存模型(堆、栈、方法区、程序计数器)
类加载机制(双亲委派模型、类加载器)
垃圾回收算法(标记-清除、标记-整理、复制算法)
垃圾回收器(Serial、Parallel、CMS、G1 原理)
JVM 性能调优(JVM 参数、内存分析工具、GC 日志分析)
类文件结构(字节码结构、方法区细节)


2、框架部分

Spring:
Spring IOC 容器(Bean 的生命周期、依赖注入)
AOP 原理(动态代理、CGLib 实现)
事务管理(声明式事务、事务传播机制)
Spring MVC(请求处理流程、DispatcherServlet、HandlerMapping)
Spring Boot(自动配置原理、嵌入式容器)
Spring Cloud(服务注册与发现、负载均衡、断路器)

MyBatis:
MyBatis 基础(SQL 映射、动态 SQL、缓存机制)
一级缓存、二级缓存的原理和区别
MyBatis 插件机制(拦截器实现、性能优化)
性能调优(懒加载、批量处理、SQL 优化)


3、缓存

Redis 的基本数据结构:
String、List、Set、Sorted Set、Hash、Bitmap、HyperLogLog、Geo

大Key 和 热Key:
概念,如何解决

大Key问题:
如何拆分大Key,避免阻塞 Redis 线程

热Key问题:
热点数据导致单节点压力过大,如何通过分片或缓存穿透防止单点瓶颈

持久化:
RDB(快照)机制(优点、缺点、触发条件)
AOF(Append Only File)机制(优点、缺点、重写策略)
混合持久化(RDB+AOF 的结合)

Redis 高可用:
主从复制(异步复制的原理)
哨兵模式(自动故障转移)
Redis Cluster(分片、槽位映射、Gossip 协议)
持久化与高可用的权衡


4、MySQL

事务相关:
ACID 原则(原子性、一致性、隔离性、持久性)
事务隔离级别(读未提交、读已提交、可重复读、串行化)
锁机制(共享锁、排他锁、行锁、表锁)
MVCC(多版本并发控制,InnoDB 如何实现可重复读)

死锁:
概念及其解决办法(死锁检测、回滚机制)

SQL 优化:
索引设计与优化(覆盖索引、最左前缀原则、索引下推)
慢查询分析(explain、索引扫描、全表扫描)
分库分表(垂直拆分、水平拆分、分片策略)
读写分离(主从复制、读从库、写主库)


5、消息队列

消息类型:
点对点(Queue):消息只能由一个消费者消费
发布-订阅(Topic):消息广播给多个订阅者
延时消息:如 RabbitMQ 的 TTL 队列或 Kafka 延时消息
事务消息:RocketMQ 事务消息,用于实现分布式事务

消息队列架构:
Broker、Producer、Consumer 模型(生产者、消费者、Broker 的架构)

消息确认机制:
消息成功消费的确认流程,避免消息丢失

负载均衡:
如何平衡消费者之间的消费压力

可靠投递:
消息持久化(消息落盘,防止 Broker 宕机导致消息丢失)
幂等性保障(如何避免重复消费的问题,如幂等消费逻辑)
消息投递重试机制(失败后重试策略,死信队列)

消息堆积:
消息积压问题:由于消费速度跟不上生产速度,消息在队列中堆积
如何应对:增加消费者并行消费能力、削峰填谷


6、分布式

CAP 理论:
Consistency:一致性
Availability:可用性
Partition Tolerance:分区容错性
CAP 不可能三角:只能同时满足两者,典型场景举例

微服务架构:
服务拆分与通信(REST、RPC、gRPC)
服务发现(Zookeeper、Eureka、Consul)
负载均衡(Ribbon、Nginx、Spring Cloud LoadBalancer)
服务容错(Hystrix、Sentinel 实现熔断降级)

服务治理:
配置管理(Spring Cloud Config、Nacos)
服务监控(Prometheus、Grafana、Sleuth)
链路追踪(Zipkin、Jaeger,分布式追踪系统)

7、项目准备

日志框架简史

浅述Java对象的内存布局

     Java的实例对象、数组对象在内存中的组成包括如下三部分:对象头Hearder、实例数据、内存填充。示意图如下所示:

对象头结构

  • 对象头:其主要包括两部分数据:Mark Word、Class对象指针。特别地对于数组对象而言,其还包括了数组长度数据。在64位的HotSpot虚拟机下,Mark Word占8个字节,其记录了Hash Code、GC信息、锁信息等相关信息;而Class对象指针则指向该实例的Class对象,在开启指针压缩的情况下占用4个字节,否则占8个字节;如果其是一个数组对象,则还需要4个字节用于记录数组长度信息。这里列出64位HotSpot虚拟机Mark Word的具体含义,以供参考。需要注意的是在下图的Mark Word中,左侧为高字节,右侧为低字节。

对象头细节

  • 实例数据:用于存放该对象的实例数据。

  • 内存填充:64位的HotSpot要求Java对象地址按8字节对齐,即每个对象所占内存的字节数必须是8字节的整数倍。因此Java对象需要通过内存填充来满足对齐要求。

三高:高可用、高性能、高扩展

     我们经常被要求设计高可用性、高可扩展性和高性能。上图包含了针对“三高”的常见解决方案。

git 分支模型

高可用性

     这意味着我们需要确保系统高水平的正常运行时间。我们经常将设计目标描述为“3个9”或“4个9”。“4个9”,即99.99%的正常运行时间,意味着服务每天只能停机8.64秒。 为了实现高可用性,我们需要在系统中增加冗余节点。 有以下几种方法可以做到这一点:

  • hot-hot结构:两个实例接收相同的输入并将输出发送到下游服务。如果其中一个实例停机,另一个实例可以立即接管。由于双方都向下游发送输出,下游系统需要进行重复数据删除。

  • hot-warm结构:两个实例接收相同的输入,只有hot实例将输出发送到下游服务。如果hot实例发生故障,warm实例将接管并开始向下游服务发送输出。

  • single-leader Cluster:一个leader实例从上游系统接收数据并复制到其他副本。

  • Leaderless cluster:在这种类型的集群中没有领导者。任何写入操作都会被复制到其他实例。只要写入实例的数量加上读取实例的数量大于实例的总数,我们就会得到有效数据。

高性能

     这意味着服务需要在一段时间内处理大量请求。常用的指标是QPS(每秒查询数)或TPS(每秒事务数)。为了实现高性能,我们经常在架构中添加缓存,这样请求就可以在不命中数据库或磁盘等较慢的I/O设备的情况下返回。我们还可以增加计算密集型任务的线程数量。然而,添加太多线程可能会降低性能。最后,我们需要识别系统中的瓶颈并提高其性能。使用异步处理通常可以有效地隔离繁重的组件。

高可扩展性

     这意味着系统可以快速轻松地扩展以容纳更多容量(横向可扩展性)或更多功能(纵向可扩展性)。通常,我们会观察响应时间以决定是否需要扩展系统。为了实现高可扩展性,重要的是将服务的职责分离。为此,微服务被广泛采用。我们还利用服务注册表和负载均衡器将请求路由到适当的实例。

  • Copyrights © 2017 - 2025 杨海波
  • 访问人数: | 浏览次数:

请我喝杯咖啡吧~

支付宝
微信