快速重拾 Tmux
Posted AaronLin
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了快速重拾 Tmux相关的知识,希望对你有一定的参考价值。
Tmux
是一个 Linux (Mac OS也支持)下的终端复用器,相较于 Screen
更为强大,但快捷键和操作逻辑也更复杂,一段时间不用,就很容易忘记相关的命令和快捷键。本文旨在通过一个简单的场景,快速重拾 Tmux
Tmux
通常用来保持会话(session),如果我们通过 ssh 连接服务器处理打包等的耗时操作,那么网络波动可能会导致连接断开,使得操作失败,使用 Tmux
会话会被保持,任务依然会继续,我们可以随时恢复会话
Tmux
另一个常用的功能是分屏,快速地创建 Window
和 Pane
,方便地在不同的任务间穿梭
修改配置
vim ~/.tmux.conf
# 将默认修饰键(prefix) ctrl + b 修改:ctrl + a
set -g prefix C-a
unbind C-b
bind C-a send-prefix
# 激活鼠标模式
set-option -g -q mouse on
# 修改分屏快捷键
# 左右分屏
bind h split-window -h
# 上下分屏
bind v split-window -v
# 可以取消默认的分屏快捷键映射
# unbind \'"\'
# unbind %
# 将 tmux 的复制模式键绑定设置为 vi 模式
setw -g mode-keys vi
重新加载 Tmux 配置文件
tmux source-file ~/.tmux.conf
命令 & 快捷键
命令
这些命令大多是用于 tmux Session 的增删改查,一些命令进入 tmux 后将无法使用
# 创建新的 session
tmux new -s <session-name>
# 删除 seesion
tmux kill-session -t 0
# 重命名 seesion
tmux rename-session -t 0 <new-name>
# 查看 所有 session
tmux ls
# 进入最近使用的 session
tmux attach
# 进入编号为 1 的 session
tmux attach -t 1
可以定义一些 alias 简化输入
# 添加到 shell 初始化脚本中
# Bash Shell 是 ~/.bashrc
# Zsh Shell 是 ~/.zshrc
alias tnew=\'tmux new -s\'
alias tatt=\'tmux attach\'
alias tkill=\'tmux kill-session -t\'
alias tkillall=\'tmux kill-session -a\'
alias tname=\'tmux rename-session -t\'
alias tls=\'tmux ls\'
快捷键
在使用下面的快捷键之前,都需要先按 tmux 的修饰键(prefix),修改后的修饰键为:Ctrl + a;具体做法是:先按住 Ctrl 再按一下 a,这时可以松开 Ctrl 和 a,这时 prefix 已经生效了,我们可以加上下面的任意按键以实现对应的功能
tmux 有 Session
、Window
、Pane
这三个比较重要的概念
会话 Seesion
- d:分离会话(detach)
- $:修改当前 Session 名称
- s:显示 Session 列表(session)
窗口 Window
- c:创建一个新的 Window (create)
- p:切换到上一个 Window(previous)
- n:切换到下一个 Window(next)
- w:显示 Window 列表(window)
- ,:修改当前 Window 的名称
- 数字键:切换到对应编号的 Window,比如 prfix + 0 就是切换到编号为 0 的 Window
窗格 Pane
- %:创建一个 Pane(水平排布),使用前面的配置后,可以使用 h(horizontal)
- ":创建一个 Pane(垂直排布),使用前面的配置后,可以使用 v(vertical)
- 空格:Pane 的垂直排布和水平排布之间相互转换
- x:移除当前 Pane,会出现提示是否需要 kill-pane,输入 y 确认,也可以使用 ctrl + d(无需按 prefix)直接终止 pane
- z:全屏当前 Pane
- ;:将光标移动到上次使用的 Pane
- o:将光标移动到下一个 Pane(顺时针)
- Ctrl + o:旋转当前窗口的pane,下一个 Pane 会代替上一 Pane 的位置,光标会保持在原 Pane
- Alt + 方向键:以 5 个单元格为单位移动边缘以调整当前面板大小
复制文本
- [:进入复制模式,因为我们配置了
setw -g mode-keys vi
所以我们可以直接用 vim 的快捷键跳转单词或者行
我们可以通过 空格键
开始选中,这时移动光标可以扩大选取,按 回车
完成文本复制
- ]:粘贴复制的文本
进入复制模式后,可以通过 q
退出复制模式
场景
tmux 就像 vim 一样,如果不经常使用,就很容易忘记快捷键,可以通过一个场景把这些零碎的知识串起来,同时场景也方便重复练习和举一反三
我们可以在 tmux 里,编译运行一个 c 的 hello world,prefix
默认为 Ctrl + b
,配置里我们修改为 Ctrl + a
- 使用 tmux 创建新的 Session,并指定名称为:run-c
# 使用 alias 的话可以用 tnew run-c
tmux new -s run-c
-
我们可以使用
prefix + ,
将 Windows 名称修改为hello-world
-
使用 vim 编辑 hello.c
vim hello.c
按 i
进入 vim 的编辑模式,输入:
#include<stdio.h>
int main()
printf("hello world\\n");
按ESC
退出编辑模式,键入 :w
保存输入
-
使用
prefix + %
(修改了配置则可以使用 prefix + h)在右侧添加一个新的 Pane 用于编译 -
新增的 Pane 将屏幕一分为二,但是编译不需要这么大,我们可以通过
prefix + Alt + 右方向键
缩小 Pane 宽度,按完 prefix 后,可以多次按Alt + 右方向键
持续缩小 Pane 宽度 -
在右侧 Pane 我们可以使用
gcc hello.c
编译 hello.c -
使用
./a.out
运行 hello world 程序 -
使用
prefix + ;
,将光标切换回左侧 Pane,如果觉想暂时收起右侧的Pane
,可以用prefix + z
,最大化或取消最大化当前Pane
-
我们可以继续编辑文件,输入
i
进入 vim 编辑模式,将world
,修改为tmux
,按ESC
退出编辑模式,键入:w
保存输入 -
使用
prefix + ;
,将光标切换回右侧 Pane,完成编译和运行
gcc hello.c
./a.out
-
使用
prefix + x
,关闭右侧 Pane,按y
确认关闭 -
使用
prefix + d
(tmux detach),将当前会话与窗口分离,回到我们自己的 Shell -
使用
tmux attach
(修改了配置则可以使用tatt
),回到我们刚出 detach 的 Session
参考资料
tmux: some considerations, some best practices
How to Boost 10X Productivity with Tmux
Tmux 使用教程 - 阮一峰
手把手教你使用终端复用神器 tmux
Tmux + Vim 工作流! 同时操作多个项目, 追求极致的丝滑流畅!
「TMUX」十分钟掌握 tmux -- 高效的终端复用工具 : )
十分钟掌握 TMUX
Y分钟速成X,其中 X=tmux
Tmux的快捷键,包括调整窗口大小
重拾Dubbo
楔子
第一次接触Dubbo, 是在毕业后第一家公司,那时候阿里停止了对Dubbo的维护,但是还是有相当多的公司在使用。当当在他的基础上开发Dubbox,而后Dubbo在沉寂几年之后,阿里又开始了对他的升级维护,2018 年 1 月 8 日发布 Dubbo 2.6.0 版本,与之前当当网开源的Dubbox 进行了合并,实现了 Dubbo 版本的统一整合。后来 阿里将Dubbo 开源贡献给 Apache,即 incubator-dubbo,如今已成为Apache的顶级项目。
Dubbo入门
分布式系统
Web应用的演进
随着互联网的发展,Web应用的规模不断扩大,其发展经历了以下阶段
-
单一应用架构 ,一个应用,将所有功能都部署在一起。
-
垂直应用架构 ,将应用拆成互不相干的几个应用
-
分布式服务架构 ,当垂直应用越来越多,应用之间交互不可避免,将核心业务抽取出来,作为独立的服务,逐渐形成稳定的服务中心,使前端应用能更快速的响应多变的市场需求。 此时,用于提高业务复用及整合的分布式服务框架(RPC)是关键。
-
流动计算架构 ,当服务越来越多,容量的评估,小服务资源的浪费等问题逐渐显现,此时需增加一个调度中心基于访问压力实时管理集群容量,提高集群利用率。 此时,用于提高机器利用率的资源调度和治理中心(SOA)是关键。
什么是分布式系统
分布式系统是若干个独立运行的系统的集合,使得用户使用起来像是在用一个系统。
Dubbo是什么
一款高性能、轻量级的开源 Java RPC 分布式服务框架。它提供了三大核心能力:面向接口的远程方法调用,智能容错和负载均衡,以及服务自动注册和发现。RPC一般指远程过程调用。RPC是远程过程调用(Remote Procedure Call)的缩写形式
Dubbo能做什么
-
当服务越来越多时,服务 URL 配置管理变得非常困难,F5 硬件负载均衡器的单点压力也越来越大。 -
当进一步发展,服务间依赖关系变得错踪复杂,甚至分不清哪个应用要在哪个应用之前启动,架构师都不能完整的描述应用的架构关系。 -
服务的调用量越来越大,服务的容量问题就暴露出来,这个服务需要多少机器支撑?什么时候该加机器?
Dubbo架构
模块 | 描述 |
---|---|
Provider | 服务提供者 |
Consumer | 服务消费者 |
Registry | 服务注册中心 |
Monitor | 服务的调用次数和调用时间的监控中心 |
Container | 服务运行容器 |
调度过程
-
0.start : 服务容器负责启动,加载,运行服务提供者。
-
1.register : 服务提供者在启动时,向注册中心注册自己提供的服务。
-
2.subscribe:服务消费者在启动时,向注册中心订阅自己所需的服务。
-
-
-
5.count: 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。
Dubbo 整合SpringBoot 入门
以Zookeeper为注册中心,首先要安装并启动Zookeeper
项目结构
服务者和消费者共同依赖的接口(dubbo-interface)
package com.wuzhu.service;
public interface HelloService {
public String sayHello(String name);
}
服务提供者 (dubbo-provider)
dubbo-provider的pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<artifactId>dubbo-provider</artifactId>
<groupId>com.wuzhu</groupId>
<version>1.0-SNAPSHOT</version>
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.0.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--服务提供接口-->
<dependency>
<groupId>com.wuzhu</groupId>
<artifactId>dubbo-interface</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!--引入dubbo的依赖-->
<dependency>
<groupId>com.alibaba.spring.boot</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>2.0.0</version>
</dependency>
<!-- 引入zookeeper的依赖 -->
<dependency>
<groupId>com.101tec</groupId>
<artifactId>zkclient</artifactId>
<version>0.10</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
dubbo-provider的配置文件application.yml
配置服务提供者的端口,和相应的dubbo配置,注册中心配置
server:
port: 8847
spring:
dubbo:
application:
name: dubbo-provider
registry: zookeeper://localhost:2181
如果不使用Zookeeper注册中心,采用点对点直连,设置registry如下
server:
port: 8847
spring:
dubbo:
application:
name: dubbo-provider
registry:
register: false
实现接口
在服务提供方实现接口,注意这里使用的@Service注解是Dubbo的,不是Spring的。
package com.wuzhu.service;
import com.alibaba.dubbo.config.annotation.Service;
import org.springframework.stereotype.Component;
@Service
@Component
public class HelloServiceImpl implements HelloService {
@Override
public String sayHello(String name) {
return "Hello, " + name;
}
}
启动类
package com.wuzhu;
import com.alibaba.dubbo.spring.boot.annotation.EnableDubboConfiguration;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@EnableDubboConfiguration
public class DubboProviderApplication {
public static void main(String[] args) {
SpringApplication.run(DubboProviderApplication.class, args);
}
}
服务消费者
dubbo-consumer的pom.xml
消费方和提供方都共同依赖dubbo-interface,dubbo-provider负责实现,dubbo-consumer端用来远程调用。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.wuzhu</groupId>
<artifactId>dubbo-consumer</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.0.RELEASE</version>
<relativePath/>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--引入接口项目jar包-->
<dependency>
<groupId>com.wuzhu</groupId>
<artifactId>dubbo-interface</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!--引入dubbo的依赖-->
<dependency>
<groupId>com.alibaba.spring.boot</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>2.0.0</version>
</dependency>
<!-- 引入zookeeper的依赖 -->
<dependency>
<groupId>com.101tec</groupId>
<artifactId>zkclient</artifactId>
<version>0.10</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
启动类
package com.wuzhu;
import com.alibaba.dubbo.spring.boot.annotation.EnableDubboConfiguration;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@EnableDubboConfiguration
public class DubboConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(DubboConsumerApplication.class, args);
}
}
消费者的配置application.yml
消费者同样也要注册到注册中心
server:
port: 8848
spring:
dubbo:
application:
name: dubbo-consumer
registry: zookeeper://localhost:2181
服务调用
使用@Reference注解
package com.wuzhu.controller;
import com.alibaba.dubbo.config.annotation.Reference;
import com.wuzhu.service.HelloService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@Reference
private HelloService helloService;
@GetMapping("/hello")
public String hello(){
return helloService.sayHello("Dubbo");
}
}
如果不使用注册中心,采用点对点直连的方式,可以添加参数url,指定服务提供方的url。去掉yml文件中的registry配置
@Reference(url = "dubbo://localhost:8847")
private HelloService helloService;
配置篇
启动时检测
Dubbo 缺省会在启动时检查依赖的服务是否可用,不可用时会抛出异常,阻止 Spring 初始化完成,以便上线时,能及早发现问题,默认 check="true"。可以通过 check="false" 关闭检查。关闭所有服务的启动时检查 (没有提供者时报错):
## 关闭某个服务的启动时检查
dubbo.reference.com.wuzhu.HelloService.check=false
## 关闭所有服务的启动时检查,关闭没有服务提供者时报错
dubbo.reference.check=false
dubbo.consumer.check=false
关闭注册中心启动时检查
dubbo.registry.check=false
配置覆盖关系
负载均衡
Dubbo 提供了多种均衡策略:
-
Random 随机, -
RoundRobin 轮询, -
LeastActive 最少活跃调用数,相同活跃数的随机 -
ConsistentHash,一致性 Hash,相同参数的请求总是发到同一提供者。
缺省为 random 随机调用
服务降级
什么是服务降级
服务降级是当服务器压力剧增的情况下,根据当前业务情况及流量对一些服务和页面有策略的降级,以此释放服务器资源以保证核心任务的正常运行。比如服务器上运行着三个服务,其中一个服务运行异常,造成大量线程堆积,占用服务器资源,导致其他两个服务无法正常运行,可以采取降级的措施,将异常的服务降级,保证了其他服务的正常运行。
Dubbo提供的两种服务降级
-
强制返回为null,(mock=force:return+null)消费方对该服务的方法调用都直接返回 null 值,不发起远程调用。用来屏蔽不重要服务不可用时对调用方的影响。 -
当调用失败时返回为null,( mock=fail:return+null) 表示消费方对该服务的方法调用在失败后,再返回 null 值,不抛异常。用来容忍不重要服务不稳定时对调用方的影响。
向注册中心写入动态配置覆盖规则:
RegistryFactory registryFactory = ExtensionLoader.getExtensionLoader(RegistryFactory.class).getAdaptiveExtension();
Registry registry = registryFactory.getRegistry(URL.valueOf("zookeeper://10.20.153.10:2181"));
registry.register(URL.valueOf("override://0.0.0.0/com.foo.BarService?category=configurators&dynamic=false&application=foo&mock=force:return+null"));
集群容错
在集群调用失败时,Dubbo 提供了多种容错方案:
-
Failover Cluster(缺省为该模式) 失败自动切换,当出现失败,重试其它服务器。通常用于读操作,但重试会带来更长延迟。可通过 retries="2" 来设置重试次数(不含第一次)。
<dubbo:service retries="2" />
或
<dubbo:reference retries="2" />
或
//设置方法的重试次数
<dubbo:reference>
<dubbo:method name="findFoo" retries="2" />
</dubbo:reference>
-
Failfast Cluster 快速失败,只发起一次调用,失败立即报错。通常用于非幂等性的写操作,比如新增记录。
-
Failsafe Cluster 失败安全,出现异常时,直接忽略。通常用于写入审计日志等操作。
-
Failback Cluster 失败自动恢复,后台记录失败请求,定时重发。通常用于消息通知操作。
-
Forking Cluster 并行调用多个服务器,只要一个成功即返回。通常用于实时性要求较高的读操作,但需要浪费更多服务资源。可通过 forks="2" 来设置最大并行数。
-
Broadcast Cluster 广播调用所有提供者,逐个调用,任意一台报错则报错。通常用于通知所有提供者更新缓存或日志等本地资源信息。
配置集群容错
<dubbo:service cluster="failsafe" />
或
<dubbo:reference cluster="failsafe" />
支持多协议
Dubbo 支持dubbo、rmi、thrift、hessain、http,redis等多种协议,允许配置多协议,在不同服务上支持不同协议或者同一服务上同时支持多种协议。
<!-- 多协议配置 (不同服务不同协议) -->
<dubbo:protocol name="dubbo" port="20880" />
<dubbo:protocol name="rmi" port="1099" />
<!-- 使用dubbo协议暴露服务 -->
<dubbo:service interface="com.alibaba.hello.api.HelloService" version="1.0.0" ref="helloService" protocol="dubbo" />
<!-- 使用rmi协议暴露服务 -->
<dubbo:service interface="com.alibaba.hello.api.DemoService" version="1.0.0" ref="demoService" protocol="rmi" />
<!-- 多协议配置 多协议暴露服务 -->
<dubbo:protocol name="dubbo" port="20880" />
<dubbo:protocol name="hessian" port="8080" />
<!-- 使用多个协议暴露服务 -->
<dubbo:service id="helloService" interface="com.alibaba.hello.api.HelloService" version="1.0.0" protocol="dubbo,hessian" />
序列化
dubbo 支持 hession、Java 二进制序列化、json、SOAP 文本序列化多种序列化协议。默认hessian序列化协议。
并发控制
Dubbo 中的并发控制,可以通过配置service的executes参数和actives来实现控制 比如:限制 HelloService 的每个方法,服务器端并发执行(或占用线程池线程数)不能超过 10 个:
<dubbo:service interface="com.wuzhu.HelloService" executes="10" />
限制 HelloService 的每个方法,每客户端并发执行(或占用连接的请求数)不能超过 10 个:
<dubbo:service interface="com.wuzhu.HelloService" actives="10" />
或Dubbo的@Service注解
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Inherited
public @interface Service {
Class<?> interfaceClass() default void.class;
......
int executes() default 0;
......
int actives() default 0;
}
尾声
相比与近些年流行的SpringCloud,Dubbo更关注于服务治理RPC框架,使用 Netty 这个的NIO框架, 底层 TCP 协议传输, Hession 序列化实现 RPC。而SpringCloud则是一套微服务系统解决方案,由多种组件构成。Dubbo官方文档从入门到配置,再到原理介绍的比较全面。这里建议大家在学习的时候多查阅。
参考资料:官方文档
点个在看你最好看
以上是关于快速重拾 Tmux的主要内容,如果未能解决你的问题,请参考以下文章