当前位置: 首页 > news >正文

深度思考rpc框架面经之五:rpc限流:rpc事务:tps测试

11 注册中心监控和rpc限流(用友云产品部二面)

11.1 你这个注册中心有实现相关的监控吗

11.1.1 如何实现注册中心有实现相关的监控

是的,我可以为你提供关于RPC注册中心及其监控的相关信息。RPC注册中心是用于管理微服务之间调用关系的中心化服务,它可以帮助微服务发现和调用其他服务。而监控是确保微服务健康、稳定运行的重要手段,可以实时检测和报警系统中的异常情况。

对于RPC注册中心的监控,通常包括以下几个方面:

  1. 服务健康检查:定期检查注册在注册中心的服务是否健康运行,如果服务出现故障,可以及时从注册中心摘除,防止其他服务调用失败。

  2. 服务调用统计:统计每个服务的调用次数、失败次数、平均响应时间等,帮助分析系统的运行状况。

  3. 资源使用情况:监控注册中心自身的CPU、内存、磁盘、网络等资源使用情况,确保注册中心稳定运行。

  4. 数据同步情况:对于集群部署的注册中心,需要监控各节点的数据同步情况,确保数据的一致性。

  5. 报警机制:当监控到异常情况时,可以通过邮件、短信、电话等方式及时通知运维人员。

常见的RPC注册中心如Zookeeper、Eureka、Consul、Nacos等,它们都提供了一定的监控功能或者有第三方工具支持其监控。

如果你需要更详细的信息或者对某个具体的RPC注册中心的监控有兴趣,可以告诉我,我会为你提供更多的资料。

11.1.2 consul和nacos分别如何实现注册中心的监控的

Consul和Nacos都是流行的服务注册与发现中心,它们都提供了一系列的监控和健康检查机制。以下是它们分别如何实现注册中心的监控的简要描述:

Consul:
  1. 健康检查:Consul内置了健康检查机制,允许定义多种检查方式,如HTTP、TCP、脚本等。当服务的健康状态发生变化时,Consul会自动更新服务的状态。

  2. UI界面:Consul提供了一个Web UI界面,可以在其中查看集群的健康状态、服务列表、节点信息等。

  3. Metrics接口:Consul提供了一个/metrics HTTP端点,可以获取Consul的运行指标,如请求率、请求延迟、集群领导选举次数等。

  4. 集成第三方监控工具:Consul的指标可以与Prometheus、Grafana等监控工具集成,以提供更丰富的监控视图和报警机制。

  5. 日志:Consul可以输出详细的日志,帮助诊断问题。

Nacos:
  1. 健康检查:Nacos也提供了健康检查机制,可以定期检查服务的健康状态,并根据结果更新服务的状态。

  2. 控制台:Nacos提供了一个管理控制台,可以在其中查看服务列表、健康状态、配置信息等。

  3. Metrics接口:Nacos也提供了指标接口,可以获取Nacos的运行指标。

  4. 集成第三方监控工具:Nacos的指标可以与Prometheus、Grafana等监控工具集成。

  5. 日志:Nacos可以输出详细的日志,帮助运维人员诊断问题。

  6. 扩展性:Nacos提供了丰富的扩展点,允许用户自定义健康检查逻辑、数据源等。

总的来说,Consul和Nacos都提供了完善的监控和健康检查机制,可以确保服务的健康和稳定。但具体的实现细节和功能可能会有所不同,需要根据实际需求选择合适的工具。

11.1.3 详细讲讲consul和nacos实现注册中心健康检查的过程

当我们谈论服务注册中心的健康检查,我们主要是指如何确定注册的服务实例是否健康、是否能够正常提供服务。Consul和Nacos都提供了健康检查的机制,但它们的实现方式和细节有所不同。以下是Consul和Nacos实现健康检查的详细过程:

Consul:
  1. 定义健康检查:在Consul中,服务可以在注册时定义其健康检查的方式。这些方式包括HTTP、TCP、脚本和TTL。

    • HTTP:Consul会定期向指定的HTTP端点发送请求,根据响应的HTTP状态码判断服务的健康状态。
    • TCP:Consul会尝试建立到指定的TCP端口的连接,如果连接成功,则认为服务是健康的。
    • 脚本:Consul会定期执行指定的脚本,并根据脚本的退出状态判断服务的健康状态。
    • TTL:服务需要在指定的TTL时间内向Consul发送心跳,否则Consul会认为服务不健康。
  2. 健康状态更新:当服务的健康状态发生变化时,Consul会自动更新服务的状态。例如,如果一个服务的健康检查失败,Consul会将该服务标记为不健康,并从服务发现的结果中排除该服务。

  3. 健康状态查询:用户可以通过Consul的API或UI查询服务的健康状态。

Nacos:
  1. 心跳机制:Nacos主要依赖于心跳机制来检查服务的健康状态。当服务实例注册到Nacos后,它需要定期向Nacos发送心跳来表示它仍然是活跃的。

  2. 心跳超时:如果Nacos在指定的时间内没有收到服务实例的心跳,它会认为该服务实例不健康,并将其从服务列表中移除。

  3. 健康状态查询:用户可以通过Nacos的控制台或API查询服务的健康状态。

  4. 健康检查扩展:Nacos提供了健康检查的扩展点,允许用户自定义健康检查的逻辑。

总结:Consul提供了多种健康检查的方式,可以根据服务的特性选择合适的方式。而Nacos主要依赖于心跳机制来检查服务的健康状态,但它也提供了健康检查的扩展点,允许用户自定义健康检查的逻辑。两者都能够有效地确保服务的健康和稳定。

11.2 你整个的这个rpc调用,有考虑过它的限流嘛

对于一个QPS为2的服务,我们可以使用令牌桶、漏桶和滑动窗口计数器算法来实现限流。以下是每种算法的简单实现:

11.3 比如现在有两个服务,比如说qps只有2,现在达到限流的目的,分别使用令牌桶、漏桶和滑动窗口计数器算法,你如何实现呢

1. 令牌桶算法:

  • 初始化一个容量为2的桶,并以每500ms放入一个令牌的速率填充桶。
  • 当请求到来时,尝试从桶中取出一个令牌。
    • 如果取出成功,请求继续。
    • 如果取出失败(桶中无令牌),请求被限制。
import java.util.concurrent.locks.ReentrantLock;public class TokenBucket {private final int capacity;private int tokens;private long lastRefillTime;private final int refillRate;private final ReentrantLock lock = new ReentrantLock();public TokenBucket(int capacity, int refillRate) {this.capacity = capacity;this.refillRate = refillRate;this.tokens = capacity;this.lastRefillTime = System.currentTimeMillis();}public boolean tryConsume() {lock.lock();try {refill();if (tokens > 0) {tokens--;return true;}return false;} finally {lock.unlock();}}private void refill() {long now = System.currentTimeMillis();int tokensToAdd = (int) ((now - lastRefillTime) / 1000 * refillRate);if (tokensToAdd > 0) {tokens = Math.min(capacity, tokens + tokensToAdd);lastRefillTime = now;}}
}

2. 漏桶算法:

  • 初始化一个容量为2的桶,并以每500ms处理一个请求的速率流出。
  • 当请求到来时,尝试放入桶中。
    • 如果放入成功,请求继续。
    • 如果放入失败(桶已满),请求被限制。
import java.util.concurrent.locks.ReentrantLock;public class LeakyBucket {private final int capacity;private int water;private long lastLeakTime;private final int leakRate;private final ReentrantLock lock = new ReentrantLock();public LeakyBucket(int capacity, int leakRate) {this.capacity = capacity;this.leakRate = leakRate;this.water = 0;this.lastLeakTime = System.currentTimeMillis();}public boolean tryConsume() {lock.lock();try {leakWater();if (water < capacity) {water++;return true;}return false;} finally {lock.unlock();}}private void leakWater() {long now = System.currentTimeMillis();int waterToLeak = (int) ((now - lastLeakTime) / 1000 * leakRate);if (waterToLeak > 0) {water = Math.max(0, water - waterToLeak);lastLeakTime = now;}}
}

3. 滑动窗口计数器算法:

  • 基于您的描述,我理解您希望使用一个滑动窗口计数器,其中每一秒都有一个独立的计数器。当请求到来时,我们将检查过去1秒内的请求计数。如果这个计数超过2,请求将被限制。

    以下是基于这个想法的Java代码实现:

    import java.util.LinkedList;public class SlidingWindowRateLimiter {private final LinkedList<RequestCounter> counters;private final int limit;public SlidingWindowRateLimiter(int limit) {this.counters = new LinkedList<>();this.limit = limit;}public synchronized boolean tryConsume() {long now = System.currentTimeMillis();long oneSecondAgo = now - 1000;// 清除1秒前的计数器while (!counters.isEmpty() && counters.getFirst().timestamp < oneSecondAgo) {counters.removeFirst();}// 获取过去1秒内的请求总数int totalCount = counters.stream().mapToInt(c -> c.count).sum();if (totalCount < limit) {// 如果当前秒的计数器不存在,创建一个if (counters.isEmpty() || counters.getLast().timestamp != now / 1000 * 1000) {counters.addLast(new RequestCounter(now / 1000 * 1000));}counters.getLast().count++;return true;}return false;}private static class RequestCounter {long timestamp;int count;RequestCounter(long timestamp) {this.timestamp = timestamp;this.count = 0;}}public static void main(String[] args) {SlidingWindowRateLimiter limiter = new SlidingWindowRateLimiter(2);System.out.println(limiter.tryConsume());  // trueSystem.out.println(limiter.tryConsume());  // trueSystem.out.println(limiter.tryConsume());  // false}
    }
    

    这个实现确保在任何给定的1秒窗口内,请求的数量都不会超过2。

11.4 你给的滑动窗口计数器方案中,qps的速率固定死了,如果说某一个服务有异常,你的qps为2也达不到,只有1呢?而且服务恢复后,qps的速率能不能恢复到2

我的答案:配置一个灵活的限流器,每次读取限定的qps阈值的时候,可以读取根据从配置中心读取到的参数限制qps,至于是谁发出的调整阈值信号,则应该是注册中心。这种情况应对的是所有的服务调用不走注册中心,也不走负载均衡器或者其他第三方服务器,而是可以直接打到服务提供者,所以限流器得在服务的提供者端生效

gpt4答案:

您提到的问题确实是滑动窗口计数器在实际应用中可能会遇到的挑战。为了解决这个问题,我们可以引入动态调整QPS的机制。以下是一个简化的策略:

  1. 动态调整QPS:我们可以根据服务的健康状况动态调整QPS。例如,如果服务出现异常,我们可以降低QPS限制;当服务恢复正常时,我们可以逐渐提高QPS限制,直到达到原始的限制。

  2. 健康检查:我们可以定期检查服务的健康状况。如果服务响应时间增加或失败率上升,我们可以认为服务可能出现了问题,并相应地调整QPS限制。

  3. 平滑恢复:当服务恢复正常后,我们不应该立即将QPS限制提高到原始值,而应该逐渐提高,以确保服务不会再次被过载。

以下是一个简化的Java代码实现,展示如何动态调整QPS:

import java.util.LinkedList;public class DynamicSlidingWindowRateLimiter {private final LinkedList<RequestCounter> counters;private int currentLimit;private final int maxLimit;public DynamicSlidingWindowRateLimiter(int maxLimit) {this.counters = new LinkedList<>();this.currentLimit = maxLimit;this.maxLimit = maxLimit;}public synchronized boolean tryConsume() {long now = System.currentTimeMillis();long oneSecondAgo = now - 1000;// 清除1秒前的计数器while (!counters.isEmpty() && counters.getFirst().timestamp < oneSecondAgo) {counters.removeFirst();}// 获取过去1秒内的请求总数int totalCount = counters.stream().mapToInt(c -> c.count).sum();if (totalCount < currentLimit) {if (counters.isEmpty() || counters.getLast().timestamp != now / 1000 * 1000) {counters.addLast(new RequestCounter(now / 1000 * 1000));}counters.getLast().count++;return true;}return false;}public void adjustLimitBasedOnHealth(boolean isServiceHealthy) {if (isServiceHealthy) {currentLimit = Math.min(maxLimit, currentLimit + 1);} else {currentLimit = Math.max(1, currentLimit - 1);}}private static class RequestCounter {long timestamp;int count;RequestCounter(long timestamp) {this.timestamp = timestamp;this.count = 0;}}public static void main(String[] args) {DynamicSlidingWindowRateLimiter limiter = new DynamicSlidingWindowRateLimiter(2);System.out.println(limiter.tryConsume());  // trueSystem.out.println(limiter.tryConsume());  // trueSystem.out.println(limiter.tryConsume());  // false// 假设服务出现异常limiter.adjustLimitBasedOnHealth(false);System.out.println(limiter.tryConsume());  // trueSystem.out.println(limiter.tryConsume());  // false// 假设服务恢复正常limiter.adjustLimitBasedOnHealth(true);System.out.println(limiter.tryConsume());  // trueSystem.out.println(limiter.tryConsume());  // true}
}

这只是一个简化的示例,展示了如何根据服务的健康状况动态调整QPS。在实际应用中,可能需要更复杂的策略和实现。

12 rpc事务(用友云产品部二面)

12.1 你有没有考虑在rpc框架这一层面统一解决分布式事务呢?比如说A调用B,B事务是在另一台机器上执行的,执行失败后B会回滚,则你的rpc框架会告诉消费者服务事务B回滚了吗?这样的机制有考虑过嘛?

13 使用你的rpc框架后,tps测试了嘛(重要)(用友云产品部二面)

使用你的rpc框架后,tps测试了嘛(重要)

相关文章:

深度思考rpc框架面经之五:rpc限流:rpc事务:tps测试

11 注册中心监控和rpc限流&#xff08;用友云产品部二面&#xff09; 11.1 你这个注册中心有实现相关的监控吗 11.1.1 如何实现注册中心有实现相关的监控 是的&#xff0c;我可以为你提供关于RPC注册中心及其监控的相关信息。RPC注册中心是用于管理微服务之间调用关系的中心…...

[AIGC] Java序列化利器 gson

前言&#xff1a; 本篇文章主要介绍了Gson库&#xff0c;从是什么、为什么、怎么用三个方面进行了详细的介绍。在是什么部分&#xff0c;介绍了Gson库的作用和特点&#xff1b;在为什么部分&#xff0c;介绍了为什么要使用Gson库&#xff1b;在怎么用部分&#xff0c;介绍了如何…...

VMware 虚拟机删除+重建

由于本人暴力地关闭虚拟机&#xff0c;导致虚拟机出现了一些问题&#xff0c;并且还没有给虚拟机拍快照&#xff0c;虽然还能用&#xff0c;但本人不想将就&#xff0c;于是乎打算重新新建一个虚拟机 一、删除 1.打开workstation,选择虚拟机&#xff0c;右键选择移除。 虽然虚…...

环面上 FHE 的快速自举:LUT/Automata Blind Rotate

参考文献&#xff1a; [AP14] Alperin-Sheriff J, Peikert C. Faster bootstrapping with polynomial error[C]//Advances in Cryptology–CRYPTO 2014: 34th Annual Cryptology Conference, Santa Barbara, CA, USA, August 17-21, 2014, Proceedings, Part I 34. Springer B…...

VScode配置文件launch.json 和 tasks.json配置项详细说明

tasks.json tasks.json为编译配置文件 {"version": "2.0.0", // tasks.json 文件的版本号"tasks": [ // 任务数组&#xff0c;包含一个编译任务配置对象{"type": "cppbuild", // 任务类型&#xff0c;这里是 cppbuild …...

DNSlog 注入简单笔记

无回显的盲注可以想办法回显到 dns 日志上&#xff1a; 1、打开 http://www.dnslog.cn 获取域名 2、注入&#xff1a; ?id1 and (select load_file(concat(//,(select database()),.3.mw0gxd.dnslog.cn/a)))-- 3、点击刷新得到回显&#xff1a;...

HDLbits: Dualedge

FPGA没有双边缘触发触发器&#xff0c;&#xff08;posedge clk或negedge clk&#xff09;会报错 “FPGA&#xff08;以及其他任何地方&#xff09;上的触发器是一个具有一个时钟且仅对该时钟的一个边缘敏感的器件。”参考verilog为什么不能双边沿触发 实现双边沿的两种方法 …...

网络安全_黑客(自学)

想自学网络安全&#xff08;黑客技术&#xff09;首先你得了解什么是网络安全&#xff01;什么是黑客&#xff01;&#xff01;&#xff01; 网络安全可以基于攻击和防御视角来分类&#xff0c;我们经常听到的 “红队”、“渗透测试” 等就是研究攻击技术&#xff0c;而“蓝队…...

AI 大框架分析基于python之TensorFlow(归一化处理,多类别分类的概率)

AI 大框架分析基于python之TensorFlow(归一化处理,多类别分类的概率) AI&#xff08;人工智能&#xff09;的大框架有很多种&#xff0c;以下是一些常见的AI框架&#xff1a; TensorFlow&#xff1a;由谷歌开发的开源机器学习框架&#xff0c;支持各种任务&#xff0c;包括图像…...

C++day01(QT简介、C++)

今日任务&#xff1a; 代码&#xff1a; #include <iostream>using namespace std;int main() {/** 输入字符串统计大写、小写、数字、空格以及其他字符的个数**/string s;cout << "请输入一个字符串" << endl;//cin >> s;getline(cin,s);i…...

Web server failed to start. Port 8080 was already in use

一、问题 package com.djc.boot;import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annota…...

new和malloc的区别

new 和 malloc 都是在 C 中用于动态分配内存的方式&#xff0c;但它们之间有一些重要的区别 对象类型的区别&#xff1a; new&#xff1a;new 是 C 的关键字&#xff0c;用于动态分配对象。它可以调用对象的构造函数进行初始化&#xff0c;并返回指向所分配对象的指针。mallo…...

python:openpyxl 读取 Excel文件,显示在 wx.grid 表格中

pip install openpyxl openpyxl-3.1.2-py2.py3-none-any.whl (249 kB) et_xmlfile-1.1.0-py3-none-any.whl (4.7 kB) 摘要&#xff1a;A Python library to read/write Excel 2010 xlsx/xlsm files pip install wxpython4.2 wxPython-4.2.0-cp37-cp37m-win_amd64.whl (18.0 M…...

12P2532X152 KJ3222X1-BA1 CE4003S2B1 EMERSON DELTAV

12P2532X152 KJ3222X1-BA1 CE4003S2B1 EMERSON DELTAV 除了标准的实时计算、通信和控制&#xff0c;边缘设备和关键网络应用的fog通常执行人工智能(AI)、虚拟现实(VR)和增强现实(AR)解决方案。 目前&#xff0c;制药商和医疗保健机构对它们的需求快速增长&#xff0c;因为它们…...

P1014 [NOIP1999 普及组] Cantor 表

#include <bits/stdc.h> using namespace std; int main() {int n,k1;cin>>n;while (n>k) {nn-k;k;}if(k%20) cout<<n<<"/"<<(k1-n);else cout<<k1-n<<"/"<<n;return 0; }...

JMeter性能分析实战一:日常登录接口

负载测试 日常需求&#xff1a;负载测试&#xff01; 对于桥的负载测试&#xff1a;我给你20t的一排车辆&#xff0c;看你能不能撑得住20t&#xff01; 对于系统的负载测试&#xff1a; 逐步增加负载&#xff0c;便于问题的发现和定位&#xff0c;不要操之过急。逐步增加负载…...

内外网结合的多服务发布架构

1. 需求 1&#xff09;有多个独立的web服务需要对外发布。 2&#xff09;有AIGC的大模型服务需要在内网图形工作站上运行&#xff0c;也需要对外发布接口。 3&#xff09;所有服务需要通过域名访问。 2. 现有资源 1&#xff09;阿里云上的ECS云服务器一台&#xff0c;考虑…...

Unity中Shader的光照模型Lambert

文章目录 前言一、Lambert光照模型1、公式可以使用图形计算器来看出这个点积对于结果的影响 前言 Unity中Shader的光照模型Lambert 一、Lambert光照模型 1、公式 A&#xff1a;可以理解为环境光的颜色 K&#xff1a;反射系数 LC&#xff1a;主要的入射光的颜色 N&#xff1a;…...

(一)Log4Net - 介绍

0、相关概念 Log4j 几乎每个大型应用程序都包含自己的日志记录或跟踪 API。根据这一规则&#xff0c;E.U. SEMPER &#x1f339;项目决定编写自己的跟踪 API。那是在 1996 年初。经过无数次的增强、几个化身和大量的工作&#xff0c;API 已经发展成为 log4j —— 一个流行的 Ja…...

[bug] mysql 时间与本地不一致

通过 select now() 查询到的时间比本机少了8个小时。 show variables like %time_zone%; //查询当前时区set global time_zone8:00; //在标准时区上加8小时,即东8区时间flush privileges; # 立即生效...

论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一)

宇树机器人多姿态起立控制强化学习框架论文解析 论文解读&#xff1a;交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架&#xff08;一&#xff09; 论文解读&#xff1a;交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化…...

实现弹窗随键盘上移居中

实现弹窗随键盘上移的核心思路 在Android中&#xff0c;可以通过监听键盘的显示和隐藏事件&#xff0c;动态调整弹窗的位置。关键点在于获取键盘高度&#xff0c;并计算剩余屏幕空间以重新定位弹窗。 // 在Activity或Fragment中设置键盘监听 val rootView findViewById<V…...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

鸿蒙DevEco Studio HarmonyOS 5跑酷小游戏实现指南

1. 项目概述 本跑酷小游戏基于鸿蒙HarmonyOS 5开发&#xff0c;使用DevEco Studio作为开发工具&#xff0c;采用Java语言实现&#xff0c;包含角色控制、障碍物生成和分数计算系统。 2. 项目结构 /src/main/java/com/example/runner/├── MainAbilitySlice.java // 主界…...

关键领域软件测试的突围之路:如何破解安全与效率的平衡难题

在数字化浪潮席卷全球的今天&#xff0c;软件系统已成为国家关键领域的核心战斗力。不同于普通商业软件&#xff0c;这些承载着国家安全使命的软件系统面临着前所未有的质量挑战——如何在确保绝对安全的前提下&#xff0c;实现高效测试与快速迭代&#xff1f;这一命题正考验着…...

Java + Spring Boot + Mybatis 实现批量插入

在 Java 中使用 Spring Boot 和 MyBatis 实现批量插入可以通过以下步骤完成。这里提供两种常用方法&#xff1a;使用 MyBatis 的 <foreach> 标签和批处理模式&#xff08;ExecutorType.BATCH&#xff09;。 方法一&#xff1a;使用 XML 的 <foreach> 标签&#xff…...

代码随想录刷题day30

1、零钱兑换II 给你一个整数数组 coins 表示不同面额的硬币&#xff0c;另给一个整数 amount 表示总金额。 请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额&#xff0c;返回 0 。 假设每一种面额的硬币有无限个。 题目数据保证结果符合 32 位带…...

前端中slice和splic的区别

1. slice slice 用于从数组中提取一部分元素&#xff0c;返回一个新的数组。 特点&#xff1a; 不修改原数组&#xff1a;slice 不会改变原数组&#xff0c;而是返回一个新的数组。提取数组的部分&#xff1a;slice 会根据指定的开始索引和结束索引提取数组的一部分。不包含…...

《Offer来了:Java面试核心知识点精讲》大纲

文章目录 一、《Offer来了:Java面试核心知识点精讲》的典型大纲框架Java基础并发编程JVM原理数据库与缓存分布式架构系统设计二、《Offer来了:Java面试核心知识点精讲(原理篇)》技术文章大纲核心主题:Java基础原理与面试高频考点Java虚拟机(JVM)原理Java并发编程原理Jav…...

Linux基础开发工具——vim工具

文章目录 vim工具什么是vimvim的多模式和使用vim的基础模式vim的三种基础模式三种模式的初步了解 常用模式的详细讲解插入模式命令模式模式转化光标的移动文本的编辑 底行模式替换模式视图模式总结 使用vim的小技巧vim的配置(了解) vim工具 本文章仍然是继续讲解Linux系统下的…...