最近因为发布方面的原因,需要对项目进行一次改造,趁着这次机会,对云平台项目进行了彻底的重构,迁移到了Spring Boot上。改造过程中,从传统的Spring项目迁移到Spring Boot上,还是碰到了一些问题的,也因此留下了这个系列的笔记。其中的内容,应该对希望把传统的Spring项目迁移到Spring Boot的人会有所帮助。
Apache HttpClient 使用(上)
HttpClient是Apache Jakarta Common下的子项目,用来提供高效的、最新的、功能丰富的支持HTTP协议的客户端编程工具包,并且它支持HTTP协议最新的版本和建议。HttpClient已经应用在很多的项目中,比如Apache Jakarta上很著名的另外两个开源项目Cactus和HTMLUnit都使用了HttpClient。
目前最新的版本是4.5,支持HTTP 1.0/HTTP 1.1协议。正在开发中的5.0版本(还在Beta阶段)支持HTTP/2协议。
1. 特性
- 基于标准、纯净的java语言。实现了Http1.0和Http1.1
- 以可扩展的面向对象的结构实现了Http全部的方法(GET, POST, PUT, DELETE, HEAD, OPTIONS, and TRACE)。
- 支持HTTPS协议。
- 通过Http代理建立透明的连接。
- 利用CONNECT方法通过Http代理建立隧道的https连接。
- Basic, Digest, NTLMv1, NTLMv2, NTLM2 Session, SNPNEGO/Kerberos认证方案。
- 插件式的自定义认证方案。
- 便携可靠的套接字工厂使它更容易的使用第三方解决方案。
- 连接管理器支持多线程应用。支持设置最大连接数,同时支持设置每个主机的最大连接数,发现并关闭过期的连接。
- 自动处理Set-Cookie中的Cookie。
- 插件式的自定义Cookie策略。
- Request的输出流可以避免流中内容直接缓冲到socket服务器。
- Response的输入流可以有效的从socket服务器直接读取相应内容。
- 在http1.0和http1.1中利用KeepAlive保持持久连接。
- 直接获取服务器发送的response code和 headers。
- 设置连接超时的能力。
- 实验性的支持http1.1 response caching。
- 源代码基于Apache License 可免费获取。
Apache HttpClient 使用(下)
4. 链接池
通常我们可以使用PoolingHttpClientConnectionManager
来创建一个链接池。
4.1 对于链接池的管理
1PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
2// 设置最大连接数
3cm.setMaxTotal(200);
4// 设置每个主机地址的并发数
5cm.setDefaultMaxPerRoute(20);
6// 通过PoolingHttpClientConnectionManager,来获取CloseableHttpClient
7CloseableHttpClient httpClient = HttpClients.custom().setConnectionManager(cm).build();
8
9// 创建http GET请求
10HttpGet httpGet = new HttpGet("http://www.baidu.com/");
11// 执行请求
12response = httpClient.execute(httpGet);
Spring应用因Session Timeout设置引起的GC问题
最近在客户的要求下,对系统进行了压测。自己压测的时候一切指标都挺正常。但是客户却反馈说压测的时候有时候会碰到性能衰减很厉害,不稳定。于是有了下面这次的排查过程。客户反馈说问题是发生在多次连续压测之后碰到的,所以进行了一系列的测试。
先说一下测试环境的一些信息:测试主机是阿里云的ECS,配置是2C + 16G。为了方便,数据库采用的是Docker搭建的,版本是5.6.X。另外,这台机器上还安装了Zookeeper 3.4.X 和Kafka 1.0。系统本身是一个标准的Spring + CXF的应用,提供给客户使用的服务是标准的Restful接口。
1. 重现问题
因为客户反馈是多次压测之后碰到的,因此首先尝试连续压测多次看看能不能重现问题。为了可能存在的数据库性能问题,临时申请了RDS作为数据库;另外为了尽快发现问题,将程序占用内存缩小到1G。这次测试测出了客户所说的问题,通过jconsole监控也发现了问题原因,应该是因为GC导致的。
看图表可以发现,压测5~6分钟之后,Java的GC占用了大量的CPU时间(左上图中的蓝色线),而且内存占用一直居高不下(右上图)。
使用Docker运行Jenkins(二)
Gitea 是一款极易搭建的自助 Git 服务,最初是fork子Gogs项目(Gogs 的目标是打造一个最简单、最快速和最轻松的方式搭建自助 Git 服务)。Gitea使用 Go 语言开发。使用 Go 语言开发使得 Gitea 能够通过独立的二进制分发,并且支持 Go 语言支持的 所有平台,包括 Linux、Mac OS X、Windows 以及 ARM 平台。
Gitea占用资源小,比起Gitlab这种庞然大物来说简直是精致得要命。但是作为小团队的项目管理用来替代Gitlab还是基本能够满足需求的。而且Gitea(包括Gogs)社区还是挺活跃的,新功能也在逐渐增加中,个人很看好它的前景。
使用Docker运行Jenkins服务(一)
1. Jenkins是什么?
某百科的解释是:
Jenkins是一个开源软件项目,是基于Java开发的一种持续集成工具,用于监控持续重复的工作,旨在提供一个开放易用的软件平台,使软件的持续集成变成可能。
这个解释大体上是靠谱的,Jenkins的核心作用就是一个CI(持续集成)工具。CI的概念是:持续集成指的是,频繁地(一天多次)将代码集成到主干。持续集成的目的,就是让产品可以快速迭代,同时还能保持高质量。它的核心措施是,代码集成到主干之前,必须通过自动化测试。只要有一个测试用例失败,就不能集成。而Jenkins能够完成这些自动化构建、测试的大部分工作。
Jenkins的前身是Hudson。这其中的渊源涉及到Oracle收购Java引起的版权纷争。有兴趣的可以看附录里面的相关链接。
Shell脚本中的一些特殊变量
Shell脚本的一些参数总是感觉记不住,特此记录一下,以备后查。
1. 参数说明
参数 | 说明 |
---|---|
$0 | 当前脚本的文件名 |
— | — |
$n | 传递给脚本或函数的参数。n 是一个数字,表示第几个参数。例如,第一个参数是$1,第二个参数是$2。 |
$# | 传递给脚本或函数的参数个数。 |
$* | 传递给脚本或函数的所有参数。 |
$@ | 传递给脚本或函数的所有参数。被双引号(" “)包含时,与 $* 稍有不同,下面将会讲到。 |
$? | 上个命令的退出状态,或函数的返回值。 |
$$ | 当前Shell进程ID。对于 Shell 脚本,就是这些脚本所在的进程ID。 |
xargs使用复杂参数
一般情况下xargs只处理一个参数,因此可以这样使用,最后的rm会自动补齐一个参数:
1find . | grep hello | xargs rm
但是有时候需要多个参数才能够正常运行,这时候怎么办呢?可以这样:
1ls -1 2016*.log | xargs -I % -t tar czvf %.tar.gz % --remove-files
上述命令的意思是将当前目录中所有2016*.log
文件使用tar打包成tar.gz文件,并删除源文件。其中:
如何无密码登录SSH
我们在用Jenkins
做发布工具的时候,经常用到的功能是通过SSH
通道完成各种功能。例如使用scp
命令拷贝安装包到服务器上,通过ssh -t
命令执行服务器上的脚本等。
这时就需要配置无密码登录,否则无法做到自动执行命令。如果每次都手动输入密码,想想都不现实。要实现无密码登录,需要配置好SSH允许证书登录。
其原理是使用了公钥体系,假设有服务器Server,用户在服务器Client上,用户在服务器Client上有私钥Private Key,在服务器Server上有对应的公钥Public Key。这样访问的时候Server就能够通过公钥体系进行验证:要求用户使用其私钥进行签名,从而确保用户拥有私钥,以此验证用户身份。如下图:
在alias命令中使用单引号
Linux中的alias命令可以将一条复杂的命令缩短为一个简单的指令,实际工作中经常会用到。使用alias的时候命令本身需要使用单引号包括起来。但是如果命令本身中包含单引号怎么办呢?
例如,下面这条命令:
1ps -ef | grep shadowsocks/server.py | grep -v grep | awk '{print $2}'
其作用是获取任务的pid。其中用到的awk
的参数需要用到单引号。alias也可以使用双引号,但是如果用双引号,其中的内容会被转义解释成具体获得的值。而不是命令本身。