|
|
|
|
top
命令用于快速了解当前系统的负载情况。
比较常用的交互式命令:
1
:查看每个 CPU 的时间分配情况H
:查看每个线程的资源占用情况P
:执行任务按 CPU 占用降序排序M
:执行任务按内存占用降序排序行号 | 字段 | 意义 |
---|---|---|
1 | top | 程序名 |
14:59:20 | 当前时间 | |
up 6:30 | 指计算机从上次启动到现在所运行的时间 | |
2 users | 指有多少用户登录系统 | |
load average | 指等待运行的进程数,三个数字分别是最近的 1 分钟、5 分钟、15 分钟的平均值 | |
2 | Tasks | 描述了进程数目和各种进程状态 |
3 | Cpu(s) | 描述了 CPU 时间分配统计 |
us | user 的缩写,CPU 消耗在 User space 的时间百分比 | |
sy | system 的缩写,CPU 消耗在 Kernel space 的时间百分比 | |
ni | niceness 的缩写,CPU 消耗在 nice 进程(低优先级)的时间百分比 | |
id | idle 的缩写,CPU 消耗在闲置进程的时间百分比,这个值越低,表示 CPU 越忙 | |
wa | wait 的缩写,CPU 等待外部 I/O 的时间百分比,这段时间 CPU 不能干其他事,但是也没有执行运算,这个值太高就说明外部设备有问题 | |
hi | hardware interrupt 的缩写,CPU 响应硬件中断请求的时间百分比 | |
si | software interrupt 的缩写,CPU 响应软件中断请求的时间百分比 | |
st | stole time 的缩写,该项指标只对虚拟机有效,表示分配给当前虚拟机的 CPU 时间之中,被同一台物理机上的其他虚拟机偷走的时间百分比 | |
4 | Mem | 描述物理内存的使用情况 |
5 | Swap | 描述交换分区(虚拟内存)的使用情况 |
TODO
Cmd + O
: 根据类名搜索类Cmd + Shift + O
: 搜索文件名搜索文件Cmd + .
: 代码提示Cmd + L
: 跳到某一行Cmd + Opt + L
: 格式化当前代码Cmd + Shift + U
: 将当前字符转变成大写或小写Cmd + F12
: 显示当前的文件结构Cmd + B
: 直接跳转到接口的实现方法Cmd + E
: 显示最近编辑的文件列表Cmd + [
: 跳到大括号开头Cmd + ]
: 跳到大括号结尾Cmd + W
: 关闭当前文件试图Cmd + D
: 复制整行或块Cmd + Delete
: 删除整行Cmd + Shift + Up
:将当前整段代码移动到上一个位置Cmd + Shift + Down
:将当前整段代码移动到上一个位置Opt + Shift + Up
:将当前整行移动到上一行位置Opt + Shift + Down
:将当前整行移动到下一行位置Opt + Up
: 根据符号选择文本打开 shell,执行 sudo visudo
,修改以下部分内容:
|
|
|
|
|
|
|
|
|
|
编辑文件 $HOME/.m2/settings.xml
,修改成适合自己的内容(比如包含公司私服设置等)。
NVM
是一个 Node.js 版本管理,通过它可以方便的切换 Node.js 版本。
|
|
|
|
一些工具说明:
编辑 ~/.zshrc
,添加如下内容:
|
|
注意:保存 zsh 配置后,需要执行 source ~/.zshrc
或重建 Shell 窗口才会生效。
编辑 ~/.gitconfig
,内容如下:
|
|
具体情况是这样的,我们有个产品的安卓端将某个 WebView 截图后上传给服务端,服务端为了节省存储空间和带宽,会对图片进行缩放处理。而某些安卓机型上传的 JPEG 图片被服务端处理后变成了黑色。我用图像处理工具查看这些图片,发现它们其实只是背景变黑了。
通过分析安卓端和服务端的相关代码以及 Google 搜索相关资料,我终于发现了问题所在。
首先简单说一下 PNG 和 JPEG 的一些区别。JPEG 是一种有损压缩的图片格式,以 24 位颜色存储单个位图,不支持动画、不支持透明色。PNG 是一种无损压缩的图片格式,有 8 位、24 位、32 位三种形式,其中 8 位 PNG 支持两种不同的透明形式(索引透明和 Alpha 透明),24 位 PNG 不支持透明,32 位 PNG 在 24 位基础上增加了 8 位透明通道。
我们安卓端的截图是 32 位的 PNG 图片,但命名时的后缀名却是 .jpg
。经过测试,有些安卓机型所截图片的背景色是白色的,有些则是透明的。我们的服务端接受到图片后,会根据图片的后缀名进行处理,目的是保持原有的格式。在这种情况下,对于背景透明的 PNG 图片,因为被服务端当做 JPEG 处理,所以 32 位色彩被强制转换成了 24 位色彩,背景就变黑了。
知道了问题产生的原因后就好办了。我最后的解决办法是修改了服务端的图片处理代码,在处理原图片时判断图片的背景是否透明,如果背景透明而目标文件又是 JPEG 格式,则通过处理丢弃原图片中的 Alpha 通道。具体的实现代码如下:
|
|
由于业务上有调用互联网 API 的需求(比如调用微信开放平台的接口),我用 Node.js 写了一个简单的 HTTP API 代理,部署在开通外网带宽的 ECS 上。其他 ECS 上的业务系统调用互联网 API 时均通过这个代理进行,功能上虽然满足了但是不够通用。
为了解决这个问题,我今天换了一种实现方案:在开通外网带宽的 ECS 上安装 Squid
实现正向代理,让业务系统通过 Squid 请求互联网 API。选用 Squid 的原因是它是一个高性能的代理缓存服务器,支持 FTP、gopher 和 HTTP 协议,它使用一个单独的、非模块化的、I/O 驱动的进程来处理所有的客户端请求。
|
|
在没有外网带宽的 ECS 添加配置文件 http-proxy.sh:
|
|
文件内容如下:
|
|
其中的 proxy.mydomain.com
是作为 HTTP 代理的 ECS 服务器名称。
|
|
测试结果:
|
|
从结果中可以看出请求时通过 proxy.mydomain.com
服务器完成的。
对于 Java 应用,最简单的方式是修改 JRE 安装目录下的网络配置文件 lib/net.properties
,启用系统代理:
|
|
配置项 http.nonProxyHosts
的目的是对本地接口的调用不通过代理。
比上述方式更灵活的方式是在应用的启动命令上添加相关参数:
|
|
最灵活的方式是在程序中指定代理,示例代码如下:
|
|
对于 Node.js 应用,如果使用了 http
进行接口调用,则代码类似如下:
|
|
目前支持的特性如下:
|
|
初始化 Evermark 文件夹,保存配置信息到 evermark.json
文件。
|
|
developerToken
并复制;developerToken
。developerToken
的生成链接:
|
|
创建一个 markdown 文件,存放在 Evermark 文件夹的 notes
目录下。
|
|
将 markdown 文件发布到 Evernote,对于已发布过的文件会采取更新操作。
|
|
在 Evernote 中删除 markdown 文件对应的笔记,markdown 文件不会删除。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
这部分功能使用 Mermaid 实现,具体可以参考它的文档。
|
|
|
|
|
|
When $a \ne 0$, there are two solutions to $ax^2 + bx + c = 0$ and they are
$x = {-b \pm \sqrt {b^2-4ac} \over 2a}$.
$$
\displaystyle \left( \sum_{k=1}^n a_k bk \right)^2 \leq
\left( \sum{k=1}^n ak^2 \right) \left( \sum{k=1}^n b_k^2 \right)
$$
|
|
@(笔记本)[标签A|标签B]
语法, 以选择笔记本和添加标签。上述问题其实可以很简单的通过 include 指令来简化配置文件,下面就通过一个配置文件的例子来说明如何简化配置。
|
|
conf/proxy.conf
)
|
|
conf/status.conf
)
|
|
conf/misc.conf
)
|
|
|
|
为了方便描述,假设目前需要修改的各个值如下表:
Hostname | IP | Gateway | DNS |
---|---|---|---|
demo-server | 192.168.0.10 | 192.168.0.1 | 8.8.8.8 |
修改 /etc/hosts
,添加如下内容:
|
|
修改 /etc/sysconfig/network
,将 HOSTNAME
设置为:
|
|
修改 /etc/rc.conf
,将 HOSTNAME
设置为:
|
|
修改 /etc/sysconfig/network-script
,添加如下内容(二选一):
|
|
|
|
修改 /etc/network/interface
,添加如下内容(二选一):
|
|
|
|
修改 /etc/rc.conf
,添加如下内容(二选一):
|
|
|
|
DNS 配置都通用。
修改 /etc/resolve.conf
,添加如下内容:
|
|
一般现在很多 Linux 默认将 IPv6 开启。但实际目前 IPv4 仍然是主流,而且对于我们来说,在开发测试中并不需要 IPv6,因此可以关闭。
修改 /etc/sysconfig/network
,将 NETWORKING_IPV6
设置为:
|
|
修改 /etc/sysctl.conf
,添加如下内容:
|
|
最后执行命令:
|
|
修改 /etc/modprobe.d/modprobe.conf
,添加如下内容:
|
|
修改 /etc/modprobe.d/modprobe.conf
,添加如下内容:
|
|
DFA
算法,所以比较高效。具体实现时在 DFA 算法基础上做了一些改进,如英文词汇的检测改造:单词 have
不会检测出 av
,而单词 av
则能检测到。
|
|
另外,如果想自己定义敏感词汇,可以在项目的 src 下面建立一个名为 tabooed.words 的敏感词汇文件。文件内容为每行一个敏感词,例如:
|
|
这样 TabooedUtils
就会使用自定义的词汇文件,而不用框架中默认的文件。
敏感词汇会在工具类 TabooedUtils
被 JVM 加载的时候载入并缓存。如果想临时修改词汇文件而又不想重启应用就生效,可以在程序中调用 reload 敏感词汇文件的方法,例如:
|
|
根据初步的测试结果,在 1000 多敏感词汇的情况下,连续过滤 1378 字的文章 1000 次,耗时 200 ms。
在实际使用中,内容缓存可以和数据缓存搭配使用,这种使用方式其实很能够体现缓存应该是分层次的思想。例如缓存的层次可以如下:
|
|
|
|
可用参数解释:
|
|
可用参数解释:
上述配置中,只针对页面 /cachedPage.htm
的内容进行缓存,并且设置 Last-Modified
由系统自动生成,客户端缓存有效时间为 4 小时。
我想了一下,写了一个 Servlet Filter,可以实现在 HTTP 响应内容中的某个节点(比如 </body>
)前添加 HTML 代码,优雅的解决了这个问题。
|
|
|
|
|
|
这样,对于所有的 .htm
请求,只要响应消息中包含了 </head>
节点,都会自动添加 HtmlContentProviderImpl.getContent(request)
中返回的内容,即一段 CNZZ 脚本。
在使用此过滤器和不使用此过滤器的情况下,对常规的页面(1M 以内)做了压力测试,发现吞吐量相差不大,基本可以忽略添加过滤器的影响。对于数据量比较大的页面,比如超过 1M 的页面,那么可能比较服务器消耗内存,同时在查找节点时速度也会慢一些,从而对页面性能造成一些影响。从另外一方面来说,出于性能的考虑,也应该尽可能保持页面小一些,超过 100K 的页面都值得考虑是否只能这么大。
]]>简单特性:
|
|
使用举例:
|
|
先用 df -h
命令查看磁盘分区使用情况:
|
|
显示结果如下:
|
|
我们发现 /opt 分区只有 99% 了,需要马上增大空间。
出于安全考虑,最好将所有相关的服务停止之后再操作:
|
|
之后执行如下命令:
|
|
我们先将 /opt 扩展到 200G,然后我们需要将 /opt umount
之后再调整大小:
|
|
最后我们再运行 df -h
命令查看,结果显示如下:
|
|
成功了!
最后把停止的服务重新启动即可:
|
|
通过以下命令获得 Subversion 代码库的作者列表:
|
|
在此输出结果的基础之上,创建 user.txt
文件,将 Subversion 中的用户映射到 Git 中的提交者。为 git svn
提供该文件可以使它更精确的映射作者数据,例如:
|
|
在 git svn clone
后面添加 --no-metadata
来阻止 git svn
包含那些 Subversion 的附加信息。
可以指定 -s
参数来告诉 Git 该 Subversion 仓库遵循了基本的分支和标签命名法则,即:trunk/branches/tags
示例:
|
|
最后一步要清理一下 git svn
创建的那些怪异的索引结构。
首先要移动标签,把它们从奇怪的远程分支变成实际的标签,然后把剩下的分支移动到本地。进入到刚刚 clone 的项目跟目录下执行如下命令:
|
|
该命令将原本以 tag/
开头的远程分支的索引变成真正的(轻巧的)标签。
接下来,把 refs/remotes
下面剩下的索引变成本地分支:
|
|
现在所有的旧分支都变成真正的 Git 分支,所有的旧标签也变成真正的 Git 标签。
最后一项工作就是把新建的 Git 服务器添加为远程服务器并且向它推送。下面是新增远程服务器的例子:
|
|
为了让所有的分支和标签都得到上传,使用这条命令:
|
|
现在,所有的分支和标签都应该整齐干净的躺在新的 Git 服务器里了。
生成公钥,然后添加到 Git 服务器的 authorized_keys
文件中,示例命令如下:
|
|
关于公钥认证参考:SSH 公钥认证使用指南
变量名 | 解释 |
---|---|
$? | 最后运行的命令的结束代码(返回值) |
$* | 所有参数列表。如 “$*” 用「”」括起来的情况、以 “$1 $2 … $n” 的形式输出所有参数 |
$@ | 所有参数列表。如 “$@” 用「”」括起来的情况、以 “$1” “$2” … “$n” 的形式输出所有参数 |
$# | 添加到 Shell 的参数个数 |
$0 | Shell 本身的文件名 |
$1-$n | 添加到 Shell 的各参数值。$1 是第 1 参数、$2 是第 2 参数…。 |
$- | 使用 Set 命令设定的 Flag 一览 |
$_ | 保存之前执行的命令的最后一个参数 |
$! | Shell 最后运行的后台 Process 的 PID |
$$ | Shell 本身的 PID(ProcessID) |
为了提高客户端 javascript 文件的加载速度,我们将所有的 javascript 代码通过 nginx、tomcat 等进行 gzip 压缩后再发给浏览器。这样原来可能 200 KB 多的脚本文件压缩后之只有 30 KB 多,浏览加载速度提高之后,用户体验就会更好。
但是最近工作中遇到了奇怪的问题,在 IE7、Firefox、Chrome 等浏览器下运行的非常良好的脚本到了 IE6 下有时候就会没有反应,需要刷新网页后才脚本才能运行。
Google 之后发现微软的官方文档里对 IE6 有提到一点:”Do not enable HTTP compression for the script files”。
如果应用程序只采用了 tomcat
部署,那么可以通过配置 Connector,只关闭对 IE6 的 javascript 压缩。
以下是一个以 Http11NioProtocol Connector
为例的配置:
|
|
如果应用程序采用了 nginx + tomcat
部署,那么可以通过以下配置只关闭对 IE6 的 javascript 压缩。
|
|
虽然 IE6 在国外已经被埋葬了,但国内仍然有大量的用户在使用它,做为 Web 开发人员的我们仍需要对它有足够的认识。
]]>出于安全性的考虑,我们想要屏蔽掉客户端以 OPTIONS、TRACE、HEAD、DELETE、PUT 等方式请求 Web 应用,只保留最常用的 GET、POST。
nginx 里设置这个比较简单,只需要在 location
节点中添加如下配置即可:
|
|
如果想要对个别 IP 开放,可以这样设置:
|
|
具体可以参考 nginx 文档:http://wiki.nginx.org/NginxHttpCoreModule#limit_except
这种方式适用于应用系统是通过 nginx 做反向代理访问的情况,同时后端的 tomcat 不暴露外网 IP。
经过测试,对于只要允许 GET、POST 请求,HEAD 请求也是支持的,所以这种方式无法在允许 GET、POST 的前提下屏蔽 HEAD。
如果是 tomcat 直接暴露外网 IP 的情况,那么只能通过修改 web.xml
来实现屏蔽相关 method 的请求。
在 web.xml
中添加如下代码:
|
|
这样应用系统就只会接受 GET、POST 方式的请求了。
经过测试,如果 <security-constraint>
中没有 <auth-constraint>
子元素的话,配置实际上是不起中用的。
如果加入了 <auth-constraint>
子元素,但是其内容为空,这表示所有身份的用户都被禁止访问相应的资源。
在一台 Memcached 服务器上开启了 3 个不同端口的进程,Memcached 客户端以相同的权重访问这三个进程。
测试客户端使用 2000 个并发线程,其中 1000 个执行 PUT 操作,另外 1000 个执行 GET 操作,每个线程中的 PUT 和 GET 操作均执行 1000 次。存入缓存的值为长度在 20 到 256 之间的随机字符串。
类型 | CPU | 内存 | IP |
---|---|---|---|
Memcached 服务端 | Intel(R) Pentium(R) 4 CPU 1.80GHz | 1G | 192.168.1.174 |
测试客户端 | Intel(R) Pentium(R) Dual-Core CPU E2210 2.2GHz | 2.75G | 192.168.0.68 |
|
|
批次 | 通讯协议 | 哈希算法 | 200并发耗时 (ms) | 2000并发耗时 (ms) |
---|---|---|---|---|
1 | Binary | Native | 1547 | 127719 |
2 | Binary | Native | 1546 | 128313 |
3 | Binary | Native | 1531 | 127465 |
4 | Binary | Ketama | 2046 | 164797 |
5 | Binary | Ketama | 2015 | 170344 |
6 | Binary | Ketama | 2063 | 167788 |
7 | Binary | Election | 2625 | 238531 |
8 | Binary | Election | 2718 | 236359 |
9 | Binary | Election | 2641 | 232672 |
10 | Text | Native | 1578 | 133639 |
11 | Text | Native | 1547 | 137562 |
12 | Text | Native | 1594 | 142497 |
13 | Text | Ketama | 2016 | 177922 |
14 | Text | Ketama | 2110 | 170917 |
15 | Text | Ketama | 2078 | 165625 |
16 | Text | Election | 2735 | 244797 |
17 | Text | Election | 2859 | 231329 |
18 | Text | Election | 2781 | 243453 |
按照目前公司产品中数据同步采用的发布订阅的规则,假设以下的场景:
|
|
最终,B 和 A、C 中的同一条记录内容并不相同,A、B、C 三个系统的数据出现了不一致的情况。
如果 A、B、C 系统都能够按照 MQ 中的数据的顺序去修改记录,那么该条记录最终在各个系统中都将是 stu_B1,即可以实现最终一致性。
这要求 A、B、C 系统都必须订阅 MQ 中的数据,包括自身系统发送到 MQ 中的数据。
优点:可以实现数据的最终一致性。
缺点:
以上述场景为例,我们给学生记录添加一个全局的版本号,假设初始数据为 stu_0,数据同步流程如下:
优点:在数据在各个系统同步时,可以避免一些过期数据的更新操作。
缺点:必须添加版本字段,并且要管理全局版本号,系统的复杂度和开发、测试工作量都会增加。
最终三个系统中该条记录均为 stu_2,保持了数据的最终一致性。
]]>