TonglinkQ8配置SSL
1.自建生成ssl证书
生成CA私钥
cd /tmp
mkdir ca && cd ca
#创建私钥 (建议设置密码)
openssl genrsa -des3 -out myCA.key 2048
生成CA证书
# 20 年有效期
openssl req -x509 -new -nodes -key myCA.key -sha256 -days 7300 -out myCA.crt
查看证书信息命令 openssl x509 -in myCA.crt -noout -text
创建ssl证书私钥
# 此文件夹存放待签名的证书
mkdir certs
cd certs
openssl genrsa -out localhost.key 2048
创建ssl证书CSR
openssl req -new -key localhost.key -out localhost.csr
创建域名附加配置文件cert.ext
vim cert.ext
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names
[alt_names]
DNS.1 = localhost
IP.2 = 127.0.0.1
DNS.3 = test.com
DNS.4 = *.test.com
使用CA签署ssl证书
# ssl证书有效期10年,此步骤需要输入CA私钥的密码
openssl x509 -req -in localhost.csr -out localhost.crt -days 3650 \
-CAcreateserial -CA ../myCA.crt -CAkey ../myCA.key \
-CAserial serial -extfile cert.ext
查看签署的证书信息
openssl x509 -in localhost.crt -noout -text
使用CA验证一下证书是否通过
[tlq@harbor certs]$ openssl verify -CAfile ../myCA.crt localhost.crt
localhost.crt: OK
把服务端代码转换浏览器可以识别的PCS12格式,密码使用上面输入的密码
openssl pkcs12 -export -in localhost.crt -inkey localhost.key -out server.p12 -passout pass:123456
[tlq@harbor ca]$ tree
.
├── certs
│ ├── cert.ext
│ ├── localhost.crt
│ ├── localhost.csr
│ ├── localhost.key
│ ├── serial
│ └── server.p12
├── myCA.crt
└── myCA.key
2.部署TLQ8
省略部署,此次使用是:
Install_TLQ_Standard_Linux2.6.32_x86_64_8.1.15.2_P12_SP1.tar.gz
Install_TLQ_Standard_Linux2.6.32_x86_64_8.1.15.2_P12.tar.gz
3.配置TLQ8
执行tlqcertpwd
输入密码为生成.p12
文件的密码
本次是两台机器都配置了/home/tlq/TLQ8/etc/tlsys.conf
SSLCertFileName = /tmp/ca/certs/server.p12 # 节点个人证书全路径
SSLCAFileName = /tmp/ca/myCA.crt # ca证书全路径
SSLCertPwd = 4B48494E4F4C # p12的密码(转码保存)
配置发送节点
一台机器信息:
#
[SendConnRecord] # 发送连接小节
ConnName = conn1 # 连接名称
SendQueName = sq # 连接对应的发送队列名称
ConnStatus = 1 # 发送连接状态,0禁用,1正常
HostName = 192.168.111.156 # 被连接节点的IP地址
ConnPort = 11003 # 被连接节点的端口号,端口号需大于1024
ConnType = 0 # 连接类型,0为常连接,1为按需连接
SendBlockSize = 8 # 单个数据块大小,单位kbytes
SendBuff = 65536 # 连接发送缓冲区大小,单位byte
LineType = LINE1000M # 线路类型
DiscInterval = 60 # 线路维持时间,单位为秒
BeatInterval = 20 # 线路检测时间(只适用于常连接),单位为秒
SecExitFlag = # 出口标志 Net|Transport|ByRecv
SecExitNetData = # 网络层出口用户数据,类型为字符串(最大长度为48字节)
SecExitTransportData = # 传输层出口用户数据,类型为字符串(最大长度为48字节)
SSLFlag = 1 # 是否使用 SSL 安全传输
SSLProtocolVersion = 1 # SSL 协议版本 0 :GMTLSv1; 1:TLS v1.2
SSLSessionTimeout = -1 # 超时时间,单位分钟
SSLCipher = AES128-SHA256 # 协商算法(协商算法具体的列表可以参见 TongLINK /Q 手册)
配置接收进程小节
一台机器信息:
[RcvProcessRecord] #
RcvProcID = 10 # 接收进程编号
RcvProcStatus = 1 # 接收进程状态,0禁用,1正常
ListenPort = 11003 # 监听端口,端口号需大于1024
LocalAddr = # 本地通信地址,如果有此项,则接收进程绑定
SSLFlag = 1 # 是否使用 SSL 安全传输
SSLProtocolVersion = 1 # SSL 协议版本 0 :GMTLSv1; 1:TLS v1.2
SSLNegoFlag = 1 # 单双向认证标志 0:单向,1:双向
SSLSessionTimeout = -1 # 超时时间,单位分钟
SSLCipher = AES128-SHA256 # 协商算法
重启节点
tlq -cstop -y
tlq
4.验证
登录控制台验证查看是否存在异常
5.Java Base 接口验证发送/消费
客户端配置
安装TLQCli8客户端
安装部署步骤省略,参考手册
客户端代理小节配置
因为是模拟发送(生产)和消费,因此两台客户代理小节
的配置都要配置
注意:SSLCipher加密参数需和发送节点/接收进程节点
一致
!
[ClientBroker] # 瘦客户代理小节
#
[ClientBrokerRecord] # 瘦客户代理
CliBrokerID = 2 # 代理进程编号
CliBrokerStatus = 1 # 启动节点时代理的启动状态,0:不启动,1:启动
ListenPort = 10261 # 代理监听的端口号,端口号需大于1024
HisRecMaxNum = 10 # 历史文件中历史记录的最大数(支持断点续传)
LocalAddr = # 本地通信地址,如果有此项,则瘦客户代理进程绑定
Protocol = 0 # Ip协议类型 0(默认值):Ipv4; 1:Ipv4和Ipv6
SSLFlag = 1 # 是否使用SSL安全传输
SSLProtocolVersion = 1 # SSL协议版本 0 :SSL v3; 1:TLS v1
SSLNegoFlag = 1 # 单双向认证标志 0:单向,1:双向
SSLCipher = AES128-SHA256 # 协商算法(协商算法具体的列表可以参见TongLINK /Q 手册)
DebugQueName = # 限流队列名
DebugMsgNum = 0 # 限制消息条数
DebugSleepTime = 0 # 指定队列消息数超限后的Sleep毫秒数
#
重启节点修改配置才生效
tlq -cstop -y
tlq
生产者测试代码
import com.tongtech.tlq.base.*;
import java.util.*;
import java.io.*;
public class SendMsgCli {
private String myQcuName;
private String myQueName;
private String myMsgType;
private int myCount;
private int reConnect;
private int SleepTime;
private String myFileName;
private TlqConnContext tlqConnContext = null;
private TlqConnection tlqConnection = null;
private TlqSSLContext tlqSSLContext = null;
private TlqQCU tlqQcu = null;
static int id = 0;
public SendMsgCli(String QcuName, String QName, String MsgType,
String FileName) throws TlqException {
myQcuName = QcuName;
myQueName = QName;
myMsgType = MsgType;
myFileName = FileName;
myCount = 2;
reConnect = 200;
SleepTime = 3000;
tlqConnContext = new TlqConnContext();
tlqConnContext.BrokerId = -1;
tlqConnContext.HostName = "192.168.111.176";
tlqConnContext.ListenPort = 10261;
tlqSSLContext = new TlqSSLContext();
tlqSSLContext.SSLCAFileName = "/tmp/ca/myCA.crt";
tlqSSLContext.SSLCertFileName = "/tmp/ca/certs/server.p12";
tlqSSLContext.SSLCertPwd = "4B48494E4F4C";
tlqSSLContext.SSLFlag = 1;
tlqSSLContext.SSLProtocolVersion = 1;
tlqSSLContext.SSLCipher = "AES128-SHA256";
tlqConnection = new TlqConnection(tlqConnContext, tlqSSLContext);
System.out.println("qcuname="+myQcuName);
tlqQcu = tlqConnection.openQCU(myQcuName);
}
public static synchronized String createID() {
StringBuffer sb = new StringBuffer();
sb.append(System.currentTimeMillis());
sb.append("_");
sb.append(id);
++id;
return sb.toString();
}
public static byte[] createBytes(int size) { //构造Buffer消息内容
StringBuffer sb = new StringBuffer(size);
for (int i = 0; i < size; i++) {
sb.append('a');
}
return sb.toString().getBytes();
}
void sendBuffMsg(int size) throws TlqException { //发送Buffer消息 size 消息大小
TlqMessage msgInfo = new TlqMessage();
TlqMsgOpt msgOpt = new TlqMsgOpt();
msgInfo.MsgType = TlqMessage.BUF_MSG; //消息类型
msgInfo.MsgSize = size; //消息大小
byte[] msgContent = createBytes(msgInfo.MsgSize); //消息内容
msgInfo.setMsgData(msgContent);
msgInfo.Persistence = TlqMessage.TLQPER_Y; //持久性
msgInfo.Priority = TlqMessage.TLQPRI_NORMAL; //优先级
msgInfo.Expiry = 1000; //生命周期
msgOpt.QueName = myQueName; //队列名
tlqQcu.putMessage(msgInfo, msgOpt);
}
void sendFileMsg(String fName) throws TlqException { //发送文件消息
TlqMessage msgInfo = new TlqMessage();
TlqMsgOpt msgOpt = new TlqMsgOpt();
msgInfo.MsgType = TlqMessage.FILE_MSG;
fName = myFileName + " " + createID() + "_" + myFileName;
msgInfo.MsgSize = fName.getBytes().length;
msgInfo.setMsgData(fName.getBytes());
msgOpt.RemoveFileFlag = TlqMsgOpt.NOTREMOVEFILE; //是否删除源文件标志
msgInfo.Persistence = TlqMessage.TLQPER_Y;
msgInfo.Priority = TlqMessage.TLQPRI_NORMAL;
msgInfo.Expiry = 1000;
msgOpt.QueName = myQueName;
tlqQcu.putMessage(msgInfo, msgOpt);
}
public void sendMsg() {
System.out.println("myMsgType is :" + myMsgType);
try {
for (int i = 0; i < myCount; i++) {
if (myMsgType.equals("B") == true) {
sendBuffMsg(10);
} else {
sendFileMsg(myFileName);
}
}
System.out.println("--------------共发送消息" + myCount +
"条!-----------");
System.out.println("-----------sendmsg over!!-----------");
} catch (TlqException tlqEx) {
tlqEx.printStackTrace();
} finally {
try {
tlqQcu.close();
tlqConnection.close();
} catch (TlqException e) {
e.printStackTrace();
}
}
}
public static void main(String[] argv) throws Exception {
String QcuName;
String QName;
String FileName;
String MsgType;
if (argv.length < 1) {
System.out.println("---------请输入参数!---------");
System.out.println(
"---------注:如果消息类型为B,则FileName输入为no!---------");
System.out.println(
"SendMsgCli QcuName QueName MsgType(B/F) FileName");
return;
}
if (argv.length != 4) {
System.out.println("---------您输入的参数格式不对,请重新输入!---------");
System.out.println(
"---------注:如果消息类型为B,则FileName输入为no!---------");
System.out.println(
"SendMsgCli QcuName QueName MsgType(B/F) FileName");
return;
} else {
QcuName = argv[0];
QName = argv[1];
MsgType = argv[2];
FileName = argv[3];
}
SendMsgCli sm = new SendMsgCli(QcuName, QName, MsgType, FileName);
sm.sendMsg();
}
}
生产者关键代码:
tlqConnContext = new TlqConnContext(); tlqConnContext.BrokerId = -1; tlqConnContext.HostName = "192.168.111.176"; tlqConnContext.ListenPort = 10261; tlqSSLContext = new TlqSSLContext(); tlqSSLContext.SSLCAFileName = "/tmp/ca/myCA.crt"; tlqSSLContext.SSLCertFileName = "/tmp/ca/certs/server.p12"; tlqSSLContext.SSLCertPwd = "4B48494E4F4C"; tlqSSLContext.SSLFlag = 1; tlqSSLContext.SSLProtocolVersion = 1; tlqSSLContext.SSLCipher = "AES128-SHA256"; tlqConnection = new TlqConnection(tlqConnContext, tlqSSLContext);
编译测试
/usr/java/jdk1.8.0_131/bin/javac SendMsgCli.java
模拟生成测试
[tlq@harbor base]$ more run.sh
#!/bin/bash
for ((i=1; i<=10000; i++))
do
echo "这是第 $i 次循环"
java SendMsgCli qcu1 sq B no
sleep 1
done
消费者测试代码
import com.tongtech.tlq.base.*;
import java.util.*;
import java.io.*;
public class GetMsgCli {
static int MyMsgCount = 0;
private String myQcuName;
private String myQueName;
private int myWaitInterval;
private int reConnCount;
private int sleepTime;
private TlqConnection tlqConnection = null;
private TlqConnContext tlqConnContext = null;
private TlqSSLContext tlqSSLContext = null;
private TlqQCU tlqQcu = null;
public GetMsgCli(String QcuName, String QueName, int WaitInterval) throws
TlqException {
myQcuName = QcuName;
myQueName = QueName;
myWaitInterval = WaitInterval;
tlqConnContext = new TlqConnContext();
tlqConnContext.BrokerId = -1;
tlqConnContext.HostName = "192.168.111.156";
tlqConnContext.ListenPort = 10261;
reConnCount = 200;
sleepTime = 3000;
tlqSSLContext = new TlqSSLContext();
tlqSSLContext.SSLCAFileName = "/tmp/ca/myCA.crt";
tlqSSLContext.SSLCertFileName = "/tmp/ca/certs/server.p12";
tlqSSLContext.SSLCertPwd = "4B48494E4F4C";
tlqSSLContext.SSLFlag = 1;
tlqSSLContext.SSLProtocolVersion = 1;
tlqSSLContext.SSLCipher = "AES128-SHA256";
tlqConnection = new TlqConnection(tlqConnContext, tlqSSLContext);
tlqQcu = tlqConnection.openQCU(myQcuName);
}
static public void printMsgInfo(TlqMessage msgInfo) {
if ((int) msgInfo.MsgType == 1) {
System.out.println("Received a File Msg");
System.out.print("msgInfo.MsgId=" + new String(msgInfo.MsgId));
System.out.println(" msgInfo.MsgSize=" + (int) msgInfo.MsgSize);
} else {
System.out.println("Received a Buffer Msg");
System.out.print("msgInfo.MsgId=" + new String(msgInfo.MsgId));
System.out.println(" msgInfo.MsgSize=" + (int) msgInfo.MsgSize);
}
}
public void recvMsg() {
int msgCount = 0;
try {
while (true) {
TlqMessage msgInfo = new TlqMessage();
TlqMsgOpt msgOpt = new TlqMsgOpt();
msgOpt.QueName = myQueName;
msgOpt.WaitInterval = myWaitInterval;
/* msgOpt.MatchOption = TlqMsgOpt.TLQMATCH_PRIORITY; //条件接收
msgInfo.Priority = 5;*/
/* msgOpt.AckMode = TlqMsgOpt.TLQACK_USER;*/
//用户确认模式
msgOpt.OperateType = TlqMsgOpt.TLQOT_GET;
tlqQcu.getMessage(msgInfo, msgOpt);
msgCount = msgCount + 1;
printMsgInfo(msgInfo);
if (msgOpt.AckMode == TlqMsgOpt.TLQACK_USER) {
int acktype = TlqMsgOpt.TLQACK_COMMIT;
tlqQcu.ackMessage(msgInfo, msgOpt, acktype);
}
}
} catch (TlqException e) {
e.printStackTrace();
} finally {
MyMsgCount = msgCount;
try {
tlqQcu.close();
tlqConnection.close();
} catch (TlqException e) {
e.printStackTrace();
}
}
System.out.println("----------GetMsg is over!------------\n");
}
public static void main(String[] argv) throws Exception {
String QcuName;
String QueName;
int WaitInterval = 0;
if (argv.length < 1) {
System.out.println("--------------请输入参数!--------------\n");
System.out
.println("GetMsgCli QcuName QueName WaitInterval");
return;
}
if (argv.length != 3) {
System.out.println("---------您输入的参数格式不对,请重新输入!---------");
System.out
.println("GetMsgCli QcuName QueName WaitInterval");
} else {
QcuName = argv[0];
QueName = argv[1];
WaitInterval = Integer.parseInt(argv[2]);
System.out.println(
"--------------------receive message begin------------------");
GetMsgCli GM = new GetMsgCli(QcuName, QueName, WaitInterval);
GM.recvMsg();
}
System.out.println("-------共接收消息" + MyMsgCount + "条-------");
}
}
消费者重点代码:
tlqConnContext = new TlqConnContext(); tlqConnContext.BrokerId = -1; tlqConnContext.HostName = "192.168.111.156"; tlqConnContext.ListenPort = 10261; reConnCount = 200; sleepTime = 3000; tlqSSLContext = new TlqSSLContext(); tlqSSLContext.SSLCAFileName = "/tmp/ca/myCA.crt"; tlqSSLContext.SSLCertFileName = "/tmp/ca/certs/server.p12"; tlqSSLContext.SSLCertPwd = "4B48494E4F4C"; tlqSSLContext.SSLFlag = 1; tlqSSLContext.SSLProtocolVersion = 1; tlqSSLContext.SSLCipher = "AES128-SHA256"; tlqConnection = new TlqConnection(tlqConnContext, tlqSSLContext);
编译测试
/usr/java/jdk1.8.0_131/bin/javac GetMsgCli.java
模拟消费测试
java GetMsgCli qcu1 lq 1000