地址: tmux-plugins/tpm
tmux 的插件管理器,方便安装 tmux 插件
需同时安装 tmux 插件和 vim 插件
多面板模式下,在 vim 和 tmux 之间使用相同的快捷键移动焦点
如果 tmux 中打开多个面板,其中一个面板打开了 vim,vim 也打开了多个面板,可以使用同一套快捷键在 vim 面板和 tmux 面板之间来回移动焦点
地址: tmux-copycat
文档: 帮助文档
特性: * 正则搜索 * 搜索结果高亮 * 预定义搜索
插件可以在 .tmux.conf 文件中预定义搜索表达式,并指定快捷键,按下 prefix + 快捷键之后会在 tmux 窗口文本中搜索满足正则表达式的文本,并高亮显示。同时支持快速复制高亮文本,或者在搜索结果之间跳转
例如使用快捷键在 tmux 窗口历史文本中搜索所有的 ip 地址,并在搜索结果列表中跳转
地址: tmux-yank
通过快捷键复制文本到系统剪贴板,在复制模式下可以复制选中区域
地址: tmux-resurrect
使用快捷键保存或者恢复 tmux 现场,当系统重启或者进程意外退出,可以利用保存的文件还原现场,继续之前的工作
地址: tmux-continuum
借助 tmux-resurrect 自动保存和恢复 tmux 现场
地址: tmux-urlview
使用快捷键列出面板中所有的 url,在浏览器中打开选中的链接
地址: tmux-open
在复制模式下,打开外部应用中打开选中的文件,例如选中的文件路径是以 pdf 结尾,则在 pdf 阅读器中打开该文件
地址: tmux-logging
保存面板中的命令和输出到文件中
地址: tmux-fpp
封装了 facebook 的 fpp 工具
地址: tmux-sensible
一些通用配置
和面板操作相关的快捷键
地址: tmux-sessionist
管理 tmux 的 session
按下 prefix 按键以后,在状态栏显示 prefix 被按下的提示符号
地址: tmux-sidebar
在左侧显示当前路径的目录树
在状态栏显示网络链接状况
地址: tmux-cpu
在状态栏显示 cpu 使用状况
地址: tmux-battery
在 tmux 状态栏显示电池电量
配合 OfflineIMAP,在状态栏显示目录中的邮件数量
motan 没有暴露 resteasy 提供的 @Provider 机制来处理异常,如果想利用这种机制,需要自己实现一个 EndpointFactory 来替换 motan 中自带的,插入自己实现的 @Provider 类
新建一个 maven 工程,添加 motan restful 协议的 jar 包依赖到 pom 文件,注意 scope 为 provided
<dependency>
<groupId>com.weibo</groupId>
<artifactId>motan-protocol-restful</artifactId>
<version>0.3.1</version>
<scope>provided</scope>
</dependency>
ExampleExceptionMapper
,实现可以参照com.weibo.api.motan.protocol.restful.support.RpcExceptionMapper
,注意接口ExceptionMapper<Exception>
支持泛型EndpointFactory
实现类,例如ExampleEndpointFactory
,继承com.weibo.api.motan.protocol.restful.support.AbstractEndpointFactory
类,在类上添加@SpiMeta
注解,指定 name 属性值,例如 ‘example’。实现AbstractEndpointFactory
类中的protected abstract RestServer innerCreateServer(URL url);
方法,大部分代码可以照搬com.weibo.api.motan.protocol.restful.support.netty.NettyEndpointFactory
类中的实现,需要修改下面的一行代码,其余可以保持不变
# 把 RpcExceptionMapper.class.getName() 替换为自己实现的统一异常处理类,例如上面实现的`ExampleExceptionMapper`类
deployment.getProviderClasses().add(RpcExceptionMapper.class.getName());
com.weibo.api.motan.protocol.restful.EndpointFactory
的文件 文件内容为自己实现的EndpointFactory
实现类的全名通过 maven 发布这个 jar 包,在需要统一异常处理的工程中依赖,修改其 motan.xml 文件的 <motan:protocol>
标签,指定endpointFactory
的值为@SpiMeta
中指定的 name 属性的值
<motan:protocol id="restfulProtocol" name="restful" endpointFactory="example"/>
github issue 中 motan 开发人员给出的建议: 在service端,怎么处理 统一异常处理机制
原理类似,这里简单介绍实现方式
com.weibo.api.motan.filter.Filter
接口中的Response filter(Caller<?> caller, Request request);
方法,通过 @SpiMeta
注解在类上设置 name 属性META-INF/services
目录中添加名为com.weibo.api.motan.filter.Filter
的文件,内容为 Filter 接口实现类带有包路径的全名motan.xml
中修改对应的<motan:service>
标签,添加属性filter
,值为第一步中自定义实现类@SpiMeta
中指定的 name 属性值业务逻辑抛出的原始异常可以通过下面方法获得
Response response = caller.call(request);
if (response.getException() != null) {
Throwable cause = response.getException().getCause();
}
参考:
在使用 rxjava 的过程中不可避免的会遇到上游的 Observable 生产数据的速度大于下游 Observer 消费的速度,这个时候需要选择一些策略来解决这个问题,按照 rxjava 官方 wiki 的说明,应对方式有三种,分别为丢弃或缓存、阻塞、back-pressure。
在了解这三种应对方式之前需要先了解 hot Observable 和 cold Observable,因为有些应对方式适用于不同类型的 Observable。
hot Observable: Observable 在创建完成时就可以发出数据,Observer 收到的数据序列是从订阅关系建立这一刻起的子序列,并且 Observable 按照自己的速度发出数据,Observer 无法控制发出数据的速度,必须自己解决消费速度问题,比如用户鼠标和键盘事件、系统事件或股票价格。
cold Observable: Observable 发出的数据序列是固定的,可以按照 Observer 的需要的时间和速度发出数据,比如数据库查询出的结果集、文件检索或网络请求。但是需要注意的是当一个 cold Observable 是 multicast (转换为一个 ConnectableObservable 并且 connect() 方法被调用过) 的,那么它应该被看作 hot Observable。
对于 cold Observable 的生产者速度过快问题,可以使用 back-pressure 策略,而 hot Observable 需要使用丢弃或者缓存。阻塞的情况比较特殊,下面再讲。
通过 Operator 来缓存或者丢弃 Observable 发出的数据,使其速度小于消费者消费的速度,这样就可以不使用 backpressure 策略来让 Observable 降速。
丢弃:
使用 sample() 或者类似功能的 Operator throttleLast()、throttleFirst() 等,来过滤生产者发出的数据,把最终到达 Observer 的数据控制在一个合适的范围之内,被过滤掉的数据会被丢弃。比如某些不重要的日志,如果生产者速率过快,可以采取这种策略,丢掉部分日志。也可以作为某些不重要服务的降级策略。
缓存:
使用 buffer() 或者 window() Operator 缓存 Observable 发出的数据,稍后把这些数据批量发出,再由消费者决定怎么消费这些数据。
生产者发出的数据是均匀分布的:
假如生产者在 10 秒钟内均匀发出了需要保存到数据库的 10000 条用户数据,由于发出数据的速度过快,超过下游消费者保存到数据库的速度,那么可以用 buffer() Operator 将这 10000 条数据按照 100 毫秒为时间段收集为 100 个 集合,每个集合包含该时间段内的全部数据。然后再把这些集合发送给消费者,消费者可以选择把这些数据批量保存到数据库或者进行其他处理,从而达到降低速度的目的。
生产者发出的数据不是均匀分布的:
官方文档中介绍了 buffer() 配合 debounce() 来应对突发型数据的方法,假如生产者发出的数据不是均匀的,而是爆发式的,那么需要用 debounce() Operator 来监控 Observable ,在发现过了一个固定时间后 Observable 没有发出任何数据,就把当前 buffer() 内的数据作为一个集合发送给消费者。具体可以看官方的图,很直观。
通过调用栈阻塞的方式,阻塞 Observable,使其无法发出数据。这种方式有一个缺点是违背了『响应式』的初衷和非阻塞模型,但是假如被阻塞的线程不重要,可以被安全的阻塞(不影响其他部分),那么这也是一个可选的方案,不过现在的 rxjava 提供的 Operator 不会利用这种方式。
如果一个 Observable,所有操作它的 Operator ,所有订阅它的 Observer 都是在同一个线程上,那么实际上是通过调用栈阻塞形成了一种阻塞 back-pressure。不过要注意很多 Operator 默认情况下是在不同的线程,文档中有说明。
消费者通过 “reactive pull” 来把生产数据速度过快的问题上移到生产者那里,让生产者去解决问题。
这个词在网络上有很多解释,这里只贴一下 ReactiveManifesto 术语表中的解释。
When one component is struggling to keep-up, the system as a whole needs to respond in a sensible way. It is unacceptable for the component under stress to fail catastrophically or to drop messages in an uncontrolled fashion. Since it can’t cope and it can’t fail it should communicate the fact that it is under stress to upstream components and so get them to reduce the load. This back-pressure is an important feedback mechanism that allows systems to gracefully respond to load rather than collapse under it. The back-pressure may cascade all the way up to the user, at which point responsiveness may degrade, but this mechanism will ensure that the system is resilient under load, and will provide information that may allow the system itself to apply other resources to help distribute the load, see Elasticity.
当系统中某些组件消费速度跟不上生产者生产的速度时,如果不想让组件崩溃或者以一种无法控制的方式丢弃消息,那么需要一种机制来把消费者组件的压力向上传递给上游的生产者组件,让生产者来减轻消费者的负荷。back-pressure 就是这样的一个让系统可以优雅的对负荷进行响应而不是被压垮的重要机制,把压力一直通知到用户那里,由系统维护者制定解决方案。
具体到 Operator 上就是利用 Subscriber.request(n)
的方式来向 Observable 请求数据,把获得数据从 push 模式转换为 pull 模式,从而控制生产者发送数据的速度。而 onBackpressureBuffer()、onBackpressureDrop() 等是为了应对没有实现 reactive pull 模式的 Observable 实现的辅助 Operator 。
在知乎回答的一个问题,贴在这里 CPU与硬盘关系的几点疑问? - 中央处理器 (CPU) - 知乎
CPU 和硬盘的关系是不太好描述,CPU 本质上只是用来执行指令,具体的读取文件的操作是操作系统来做的,从操作系统的角度来说可能要方便一些。像其他答案说的,你的这些疑问应该去看操作系统和计算机组成原理相关的教材,形成一个整体上认识,而不应该片面的了解某一个方面。
我下面简单叙述一下操作系统在从硬盘读文件的流程。
为简单起见,假设场景是一个x86体系的32位Linux操作系统中运行的进程 P 需要读取文件 /home/user/test.txt,文件系统使用 ext3。
home 3 etc 4 bin 5 eg.txt 5
后面的数字就是目录或者文件对应的 inode 编号,通过检索可知,我们需要的找到 home 目录的inode 编号为3,重复这个过程,直到定位到 /home/user/test.txt 的 inode 编号。文件系统所有的 inode 信息也是存储在硬盘上的,也就是说硬盘中不仅有文件内容,还有文件系统的数据,这可以解释你的第二、三个问题,为什么换了硬盘仍然能够开机和识别文件,开机是存储在主板上的 BIOS 引导的,操作系统启动以后从硬盘读取文件系统的数据就可以获得整个磁盘的文件信息,CPU 只是执行操作系统的指令。