快速重拾 Tmux

Posted AaronLin

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了快速重拾 Tmux相关的知识,希望对你有一定的参考价值。

Tmux 是一个 Linux (Mac OS也支持)下的终端复用器,相较于 Screen 更为强大,但快捷键和操作逻辑也更复杂,一段时间不用,就很容易忘记相关的命令和快捷键。本文旨在通过一个简单的场景,快速重拾 Tmux

Tmux 通常用来保持会话(session),如果我们通过 ssh 连接服务器处理打包等的耗时操作,那么网络波动可能会导致连接断开,使得操作失败,使用 Tmux 会话会被保持,任务依然会继续,我们可以随时恢复会话

Tmux 另一个常用的功能是分屏,快速地创建 WindowPane,方便地在不同的任务间穿梭

修改配置

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 有 SessionWindowPane 这三个比较重要的概念

会话 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

  1. 使用 tmux 创建新的 Session,并指定名称为:run-c
# 使用 alias 的话可以用 tnew run-c
tmux new -s run-c
  1. 我们可以使用 prefix + , 将 Windows 名称修改为 hello-world

  2. 使用 vim 编辑 hello.c

vim hello.c

i 进入 vim 的编辑模式,输入:

#include<stdio.h>

int main()
    printf("hello world\\n");

ESC 退出编辑模式,键入 :w 保存输入

  1. 使用 prefix + % (修改了配置则可以使用 prefix + h)在右侧添加一个新的 Pane 用于编译

  2. 新增的 Pane 将屏幕一分为二,但是编译不需要这么大,我们可以通过 prefix + Alt + 右方向键 缩小 Pane 宽度,按完 prefix 后,可以多次按 Alt + 右方向键 持续缩小 Pane 宽度

  3. 在右侧 Pane 我们可以使用 gcc hello.c 编译 hello.c

  4. 使用 ./a.out 运行 hello world 程序

  5. 使用 prefix + ;,将光标切换回左侧 Pane,如果觉想暂时收起右侧的 Pane,可以用 prefix + z,最大化或取消最大化当前 Pane

  6. 我们可以继续编辑文件,输入 i 进入 vim 编辑模式,将 world,修改为 tmux,按ESC 退出编辑模式,键入 :w 保存输入

  7. 使用 prefix + ;,将光标切换回右侧 Pane,完成编译和运行

gcc hello.c
./a.out
  1. 使用 prefix + x,关闭右侧 Pane,按 y 确认关闭

  2. 使用 prefix + d(tmux detach),将当前会话与窗口分离,回到我们自己的 Shell

  3. 使用 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
bq1.jpg

Dubbo入门

分布式系统

Web应用的演进

随着互联网的发展,Web应用的规模不断扩大,其发展经历了以下阶段

  • 单一应用架构 ,一个应用,将所有功能都部署在一起。
  • 垂直应用架构 ,将应用拆成互不相干的几个应用
  • 分布式服务架构 ,当垂直应用越来越多,应用之间交互不可避免,将核心业务抽取出来,作为独立的服务,逐渐形成稳定的服务中心,使前端应用能更快速的响应多变的市场需求。 此时,用于提高业务复用及整合的分布式服务框架(RPC)是关键。
  • 流动计算架构 ,当服务越来越多,容量的评估,小服务资源的浪费等问题逐渐显现,此时需增加一个调度中心基于访问压力实时管理集群容量,提高集群利用率。 此时,用于提高机器利用率的资源调度和治理中心(SOA)是关键。

什么是分布式系统

分布式系统是若干个独立运行的系统的集合,使得用户使用起来像是在用一个系统。

Dubbo是什么

一款高性能、轻量级的开源 Java RPC 分布式服务框架。它提供了三大核心能力:面向接口的远程方法调用,智能容错和负载均衡,以及服务自动注册和发现。RPC一般指远程过程调用。RPC是远程过程调用(Remote Procedure Call)的缩写形式

Dubbo能做什么

  • 当服务越来越多时,服务 URL 配置管理变得非常困难,F5 硬件负载均衡器的单点压力也越来越大。
  • 当进一步发展,服务间依赖关系变得错踪复杂,甚至分不清哪个应用要在哪个应用之前启动,架构师都不能完整的描述应用的架构关系。
  • 服务的调用量越来越大,服务的容量问题就暴露出来,这个服务需要多少机器支撑?什么时候该加机器?

Dubbo架构

模块 描述
Provider              服务提供者
Consumer 服务消费者
Registry 服务注册中心
Monitor 服务的调用次数和调用时间的监控中心
Container 服务运行容器
重拾Dubbo

调度过程

  • 0.start : 服务容器负责启动,加载,运行服务提供者。

  • 1.register : 服务提供者在启动时,向注册中心注册自己提供的服务。

  • 2.subscribe:服务消费者在启动时,向注册中心订阅自己所需的服务。

  • 5.count: 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。

Dubbo 整合SpringBoot 入门

以Zookeeper为注册中心,首先要安装并启动Zookeeper

项目结构

重拾Dubbo

服务者和消费者共同依赖的接口(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

配置覆盖关系

方法级优先,接口级次之,全局配置再次之。
如果级别一样,则消费方优先,提供方次之。官方文档给出了以设置timeout为例,配置覆盖的从高到低的关系如下图

重拾Dubbo

负载均衡

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的主要内容,如果未能解决你的问题,请参考以下文章

tmux常用命令 IDEA工具连接远程服务器主机快速操作与上传文件

改进风格迁移,重拾《星空》梦!

Linux笔记:终端复用与管理工具screen和tmux

重拾Dubbo

重拾安卓_00_资源帖

重拾HTML