详情
rsyslog的基本架构图如下。
这个实验的需求是测试两台服务器之间,使用rsyslog进行日志传输的性能。
rsyslog网上的资料非常少,使用java进行rsyslog收发的资料就更少了。
java是有一个jar包可以进行rsyslog编程的,在pom中引入如下坐标
<!-- https://mvnrepository.com/artifact/org.syslog4j/syslog4j -->
<dependency>
<groupId>org.graylog2</groupId>
<artifactId>syslog4j</artifactId>
<version>0.9.60</version>
</dependency>
我们使用这个jar包可以搭建syslog服务器和客户端,其中服务器是用来接收日志的,客户端是用来发送日志的,核心的代码有一下三个
客户端
public class ClientClass implements Runnable{
//控制循环结束的
private boolean flag = true;
private static ClientClass ClientClass = null;
private String host;
private int port;
// 用来记录发送数量
public static int num = 0;
// 记录开始时间
private static Long starttime = null;
public static long getspeed(){
if(starttime == null){
return 0L;
}
long endtime = System.currentTimeMillis();
if((endtime-starttime)/1000==0){
return 0L;
}
long speed = num / ((endtime-starttime)/1000);
return speed;
}
private static SyslogIF syslogIF;
private ClientClass (String host, int port) {
this.host = host;
this.port = port;
}
private ClientClass(){
}
public static synchronized ClientClass getClient(String host, int port)
{
if(ClientClass == null) {
ClientClass = new ClientClass(host, port);
}
return ClientClass ;
}
@Override
public void run() {
starttime = System.currentTimeMillis();
try {
//初始化标识位
flag = true;
//获取syslog的操作类,使用udp协议。syslog支持"udp", "tcp", "unix_syslog", "unix_socket"协议
SyslogIF syslog = Syslog.getInstance("tcp");
//设置syslog服务器端地址 地址为之前你服务器的地址
syslog.getConfig().setHost(host);
//设置syslog接收端口,默认514
syslog.getConfig().setPort(port);
//拼接syslog日志
System.out.println("+++++++++++++start++++++++++++");
while(flag) {
// 等级为debug
// 这句话就是发送数据
String str = "[" + num + "]->" + "operator Protocol "+ Thread.currentThread().getName();
syslog.log(SyslogConstants.LEVEL_DEBUG, URLDecoder.decode(str,"utf-8"));
num++;
// 给程序缓冲时间,没有缓冲时间接受不到数据
//Thread.sleep(100);
}
//System.out.println(Thread.currentThread().getName()+" end");
} catch (Exception e) {
System.err.println("出错了");
e.printStackTrace();
}
}
public void shutdown() {
try {
//线程停止
Thread.sleep(2000);
//改变标识位
flag = false;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
服务器
服务器分为服务器的代码和处理器的代码
public class SyslogServerEventHandler implements SyslogServerSessionEventHandlerIF {
private String syslog ;
// 记录接收的数量
public int num = 0;
//重写event方法
public void event(Object session, SyslogServerIF syslogServer, SocketAddress socketAddress, SyslogServerEventIF event) {
//判断传输时间是否存在,不存在将现在的时间设置为传输时间
String date = (event.getDate() == null ? new Date() : event.getDate()).toString();
//将解析日志的生成端,<<3是要该数左移动三位计算
String facility = SyslogUtility.getFacilityString(event.getFacility()<<3);
//讲解析日志的级别,级别越大越低
String level = SyslogUtility.getLevelString(event.getLevel());
//获取当前的源设备IP
String sourceIP = getIPAddress(socketAddress.toString());
//获取到信息主体
String msg = event.getMessage();
// 放入信息
// 这里就是接收到的所有消息
// ######################
setSyslog("这是一条记录 {" + facility + "} " + date + " " + level + " " + event.getMessage()+ " " +sourceIP );
// ######################
num++;
try {
// 生成一个实体类保存日志
LogEntity logEntity = new LogEntity();
logEntity.setUidrecordid(IdUtil.randomUUID());
logEntity.setContent(getSyslog());
Date date1 = new Date();
SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
logEntity.setDttime(formatter.format(date1));
GetList.addLogEntityList(logEntity);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
/*
try {
//打印信息
// 这里是对于消息的处理
System.out.println(getSyslog());
} catch (UnsupportedEncodingException e) {
System.err.println("UnsupportedEncodingException");
}
*/
}
public String getSyslog() throws UnsupportedEncodingException {
return new String(syslog.getBytes(),"UTF-8");
}
public void setSyslog(String syslog) {
this.syslog = syslog;
}
//获取到该字符串里的ip地址
private String getIPAddress(String bString)
{
String regEx="((2[0-4]\\d|25[0-5]|[01]?\\d\\d?)\\.){3}(2[0-4]\\d|25[0-5]|[01]?\\d\\d?)";
Pattern p = Pattern.compile(regEx);
Matcher m = p.matcher(bString);
String result = "";
while (m.find()) {
result=m.group();
break;
}
return result;
}
@Override
public void initialize(SyslogServerIF syslogServer) {
System.out.println("实例化一个处理器");
}
@Override
public void destroy(SyslogServerIF syslogServer) {}
@Override
public Object sessionOpened(SyslogServerIF syslogServer, SocketAddress socketAddress) {return null;}
@Override
public void exception(Object session, SyslogServerIF syslogServer, SocketAddress socketAddress,Exception exception) {
System.out.println("报错啦");
}
@Override
public void sessionClosed(Object session, SyslogServerIF syslogServer, SocketAddress socketAddress,boolean timeout) {}
}
public class TCPSyslogServerFinal implements Runnable {
private static TCPSyslogServerFinal TCPSyslogServerFinal = null;
private static SyslogServerIF serverIF;
public static SyslogServerEventHandler eventHandler = new SyslogServerEventHandler();
//syslog服务器配置文件用于服务器关闭
private SyslogServerIF serverIf = null ;
private Long starttime = null;
// 获取当前速率
public long getspeed(){
if(starttime == null){
return 0L;
}
long endtime = System.currentTimeMillis();
if((endtime-starttime)/1000==0){
return 0L;
}
long speed = eventHandler.num / ((endtime-starttime)/1000);
return speed;
}
public SyslogServerIF getServerIF() {
return serverIf;
}
private void setServerIF(SyslogServerIF serverIF) {
this.serverIf = serverIF;
}
private TCPSyslogServerFinal(){}
//用单例模式去书写
public static synchronized TCPSyslogServerFinal getTCPSyslogServer()
{
if(TCPSyslogServerFinal == null)
{
TCPSyslogServerFinal = new TCPSyslogServerFinal();
//实例化接收处理方法
//传入TCP协议参数实例化具体服务器
serverIF = SyslogServer.getInstance("tcp");
//从服务器里获取配置信息变量
SyslogServerConfigIF config = serverIF.getConfig();
//设置监听地址0.0.0.0为监听网络内全部地址
config.setHost("0.0.0.0");
//设置监听地址为514,514为syslog默认地址
config.setPort(515);
//放入接收方法
config.addEventHandler(eventHandler);
//初始化服务器
serverIF.initialize("tcp",config);
}
return TCPSyslogServerFinal;
}
@Override
public void run() {
starttime = System.currentTimeMillis();
System.out.println("server start tcp");
//设置服务器变量,用来外部调用关闭
setServerIF(serverIF);
//服务器启动
serverIF.run();
}
}
前端页面
为了方便进行测试,我写了一个前端页面进行控制。
目录的层级关系如下
使用到的页面是 manager.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>rsyslog测试</title>
<!---->
<!-- <link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/4.3.1/css/bootstrap.min.css">
<script src="https://cdn.staticfile.org/jquery/3.2.1/jquery.min.js"></script>
<script src="https://cdn.staticfile.org/popper.js/1.15.0/umd/popper.min.js"></script>
<script src="https://cdn.staticfile.org/twitter-bootstrap/4.3.1/js/bootstrap.min.js"></script>-->
<!-- 新 Bootstrap4 核心 CSS 文件 -->
<link rel="stylesheet" href="/static/css/bootstrap.css">
<!-- jQuery文件。务必在bootstrap.min.js 之前引入 -->
<script src="/static/js/jquery-3.2.1.js"></script>
<!-- bootstrap.bundle.min.js 用于弹窗、提示、下拉菜单,包含了 popper.min.js -->
<script src="/static/js/bootstrap.bundle.js"></script>
<!-- 最新的 Bootstrap4 核心 JavaScript 文件 -->
<script src="/static/js/bootstrap.js"></script>
<!-- ECharts单文件引入 -->
<script src="/static/js/echarts.min.js"></script>
</head>
<script type="text/javascript">
// 监控信息,比如cpu,内存,接收速率和发送速率
var cpuinfo = []
var meminfo = []
var sendinfo = []
var acceptinfo = []
// 进入管理页面后,查询本机ip地址
function getip() {
$.post({
url: "/server/getmsg",
data: {},
success: function(data) {
var spanElement = document.getElementById("ip");
spanElement.innerText = data.ip;
var spancpu = document.getElementById("cpu");
spancpu.innerText = data.cpu + "%";
var spanmem = document.getElementById("mem");
spanmem.innerText = data.mem + "%";
cpuinfo.push(data.cpu)
meminfo.push(data.mem)
}
})
}
// 每隔1s更新一下内存和cpu的使用率
function update(){
window.setInterval("getip()", 1000);
}
//window.onload = getip();
window.onload = update();
// 检查服务器的状态
function checktcpserver(){
$.get({
url: "/server/tcpstate",
data: {},
success: function(data){
var spanElement = document.getElementById("tcpstate");
if(data.state==0) {
spanElement.innerText = "关闭";
} else {
spanElement.innerText = "开启";
}
}
})
}
function checkudpserver(){
$.get({
url: "/server/udpstate",
data: {},
success: function(data){
var spanElement = document.getElementById("udpstate");
if(data.state==0) {
spanElement.innerText = "关闭";
} else {
spanElement.innerText = "开启"
}
}
})
}
window.onload = checktcpserver();
//window.onload = checkudpserver();
// 开启TCP服务器
function starttcp(){
var url = "/server/startTCPServier";
$.get({
url: url,
data: {},
success: function(data) {
alert(data.msg);
checktcpserver();
}
})
}
// 开启UDP服务器
function startudp(){
$.get({
url: "/server/startUDPServier",
data: {},
success: function(data) {
alert(data.msg);
checkudpserver();
}
})
}
// 关闭TCP服务器
function shutdowntcp(){
$.get({
url: "/server/shutdownTCPServier",
data: {},
success: function(data) {
alert(data.msg);
checktcpserver();
}
})
}
// 关闭UDP服务器
function shutdownudp() {
$.get({
url: "/server/shutdownUDPServier",
data: {},
success: function(data) {
alert(data.msg);
checkudpserver();
}
})
}
// 检查客户端的情况
function checkclient() {
$.get({
url: "/client/getClientState",
data: {},
success: function(data){
var spanElement = document.getElementById("clientstate");
if(data.state==0) {
spanElement.innerText = "关闭";
} else {
spanElement.innerText = "开启"
}
}
})
}
window.onload = checkclient();
// 开启客户端
function startclient() {
var host = document.getElementById("host").value;
var port = document.getElementById("port").value;
var url = "/client/startClient/" + host + "/" + port;
$.get({
url: url,
data: {},
success: function(data) {
alert(data.msg);
checkclient();
}
})
}
// 关闭客户端
function shutdownclient() {
$.get({
url: "/client/shutdownClient",
data: {},
success: function(data) {
alert(data.msg);
checkclient();
}
})
}
// 获取发送和接收速率
function getspeedser(){
$.get({
url: "/server/getspeed",
data: {},
success: function(data) {
data = JSON.parse(data)
var spanElement = document.getElementById("speed-ser");
spanElement.innerText = data.speed
acceptinfo.push(data.speed)
}
})
}
function getspeedcli(){
$.get({
url: "/client/getspeed",
data: {},
success: function(data) {
data = JSON.parse(data)
var spanElement = document.getElementById("speed-cli");
spanElement.innerText = data.speed
sendinfo.push(data.speed)
}
})
}
window.setInterval("getspeedcli()", 1000);
window.setInterval("getspeedser()", 1000);
function shujuruku(){
$.get({
url: "/server/start",
data: {},
success: function(data) {
}
})
}
window.onload = shujuruku();
</script>
<body>
<div class="container">
<div class="row">
<div class="col-md-2"></div>
<div class="col-md-8">
<h3 align="center">rsyslog测试控制面板</h3>
<h5 align="center">
<div class="row">
<div class="col-md-4">
本机ip:<span id="ip"> </span>
</div>
<div class="col-md-4">
cpu使用率:<span id="cpu"> </span>
</div>
<div class="col-md-4">
内存使用率:<span id="mem"> </span>
</div>
</div>
</h5>
<div align="center">
</div>
</div>
<div class="col-md-2"></div>
</div>
<div class="row">
<div class="col-md-2"></div>
<div class="col-md-8"><input name="host" id="host" type="text" class="form-control" placeholder="输入连接的ip"></div>
<div class="col-md-2"></div>
</div>
<div class="row">
<div class="col-md-2"></div>
<div class="col-md-8"><input name="port" id="port" type="text" class="form-control" placeholder="输入连接的端口号"></div>
<div class="col-md-2"></div>
</div>
<div class="row">
<div class="col-md-2"></div>
<div class="col-md-8">
<table class="table table-striped table-bordered table-hover" id="tableL01">
<tr>
<td>名称</td>
<td>状态</td>
<td>操作</td>
</tr>
<tr>
<td>TCP服务器</td>
<td><span id="tcpstate"></span></td>
<td>
<button type="button" class="btn btn-primary" onclick="starttcp()">开启</button>
<button type="button" class="btn btn-danger" onclick="shutdowntcp()">关闭</button>
</td>
</tr>
<!--
<tr>
<td>DUP服务器</td>
<td><span id="udpstate"></span></td>
<td>
<button type="button" class="btn btn-primary" onclick="startudp()">开启</button>
<button type="button" class="btn btn-danger" onclick="shutdownudp()">关闭</button>
</td>
</tr>
-->
<tr>
<td>客户端</td>
<td><span id="clientstate"></span></td>
<td>
<button type="button" class="btn btn-primary" onclick="startclient()">开启</button>
<button type="button" class="btn btn-danger" onclick="shutdownclient()">关闭</button>
</td>
</tr>
</table>
</div>
<div class="col-md-2"></div>
</div>
<!-- 记录发送速率和接收速率 -->
<div class="row">
<div class="col-md-2"></div>
<div class="col-md-4">
服务器接收速率:<span id="speed-ser"></span> 条/秒
</div>
<div class="col-md-4">
客户端发送速率:<span id="speed-cli"></span> 条/秒
</div>
<div class="col-md-2"></div>
</div>
</div>
</body>
</html>
服务器controller
@RestController
@RequestMapping("/server")
public class ServerController {
// 表示tcp服务器是否开启
// 0表示没有开启
// 1表示开启
private int tcpServerState = 0;
// 同上,表示udp服务器是否开启
private int udpServerState = 0;
@Autowired
private RsyslogServiceImpl rsyslogService;
private static OperatingSystemMXBean osmxb = (OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean();
public static void main(String[] args) {
}
// 获取系统信息
@RequestMapping(value = "getmsg", method = RequestMethod.POST, produces = "application/json;charset=UTF-8")
public String getmsg(HttpServletRequest request) throws UnknownHostException {
// 获取ip
//String clientIP = ServletUtil.getClientIP(request, null);
String ip = NetUtil.getLocalhost().getHostAddress();
Map<String, Object> result = new HashMap<>();
result.put("ip", ip);
// 获取cpu占用
double cpuLoad = osmxb.getSystemCpuLoad();
int percentCpuLoad = (int) (cpuLoad * 100);
result.put("cpu", percentCpuLoad);
// 获取内存占用
double totalvirtualMemory = osmxb.getTotalPhysicalMemorySize();
double freePhysicalMemorySize = osmxb.getFreePhysicalMemorySize();
double value = freePhysicalMemorySize/totalvirtualMemory;
int percentMemoryLoad = (int) ((1-value)*100);
result.put("mem", percentMemoryLoad);
return JSON.toJSONString(result);
}
// 获取tcp服务器状态
@RequestMapping(value = "tcpstate", method = RequestMethod.GET, produces = "application/json;charset=UTF-8")
public String tcpstate(){
Map<String, Object> result = new HashMap<>();
result.put("state", tcpServerState);
return JSON.toJSONString(result);
}
// 获取udp服务器状态
@RequestMapping(value = "udpstate", method = RequestMethod.GET, produces = "application/json;charset=UTF-8")
public String udpstate(){
Map<String, Object> result = new HashMap<>();
result.put("state", udpServerState);
return JSON.toJSONString(result);
}
// 开启TCP服务器
@RequestMapping(value ="startTCPServier", method = RequestMethod.GET, produces = "application/json;charset=UTF-8")
public String startTCPServier(){
new Thread(TCPSyslogServerFinal.getTCPSyslogServer(), "基于TCP的syslog服务器").start();
tcpServerState = 1;
Map<String, Object> result = new HashMap<>();
result.put("msg", "TCP服务器启动...");
return JSON.toJSONString(result);
}
// 关闭TCP服务器
@RequestMapping(value ="shutdownTCPServier", method = RequestMethod.GET, produces = "application/json;charset=UTF-8")
public String shutdownTCPServier(){
TCPSyslogServerFinal.getTCPSyslogServer().getServerIF().shutdown();
tcpServerState = 0;
Map<String, Object> result = new HashMap<>();
result.put("msg", "TCP服务器关闭...");
return JSON.toJSONString(result);
}
// 获取服务器接收数据的速率
@RequestMapping(value="getspeed", method = RequestMethod.GET)
public String getspeed(){
long speed = TCPSyslogServerFinal.getTCPSyslogServer().getspeed();
//System.out.println(speed);
Map<String, Object> result = new HashMap<>();
result.put("speed", speed);
return JSON.toJSONString(result);
}
// 获取服务器接收数据的速率
@RequestMapping(value="start", method = RequestMethod.GET)
public void start(){
rsyslogService.check();
}
/*
// 开启UDP服务器
@RequestMapping(value ="startUDPServier", method = RequestMethod.GET, produces = "application/json;charset=UTF-8")
public String startUDPServier(){
new Thread(UDPSyslogServerFinal.getUDPSyslogServer(), "基于UDP的syslog服务器").start();
udpServerState = 1;
Map<String, Object> result = new HashMap<>();
result.put("msg", "UDP服务器启动...");
return JSON.toJSONString(result);
}
// 关闭UDP服务器
@RequestMapping(value ="shutdownUDPServier", method = RequestMethod.GET, produces = "application/json;charset=UTF-8")
public String shutdownUDPServier(){
UDPSyslogServerFinal.getUDPSyslogServer().getServerIF().shutdown();
udpServerState = 0;
Map<String, Object> result = new HashMap<>();
result.put("msg", "UDP服务器关闭...");
return JSON.toJSONString(result);
}
*/
}
客户端controller
@RestController
@RequestMapping("/client")
public class ClientController {
private Integer clientState = 0;
@RequestMapping(value = "getClientState" , method = RequestMethod.GET, produces = "application/json;charset=UTF-8")
public String getClientState(){
Map<String, Object> result = new HashMap<>();
result.put("state", clientState);
return JSON.toJSONString(result);
}
// 开启客户端
@RequestMapping(value ="startClient/{host}/{port}", method = RequestMethod.GET, produces = "application/json;charset=UTF-8")
public String startClient(@PathVariable("host") String host,
@PathVariable("port") int port){
new Thread(ClientClass.getClient(host, port),"客户端").start();
clientState = 1;
Map<String, Object> result = new HashMap<>();
result.put("msg", "客户端启动...");
return JSON.toJSONString(result);
}
// 关闭客户端
@RequestMapping(value ="shutdownClient", method = RequestMethod.GET, produces = "application/json;charset=UTF-8")
public String shutdownClient(){
ClientClass.getClient("127.0.0.1", 514).shutdown();
clientState = 0;
Map<String, Object> result = new HashMap<>();
result.put("msg", "客户端关闭...");
return JSON.toJSONString(result);
}
// 获取客户端发送数据的速率
@RequestMapping(value="getspeed", method = RequestMethod.GET)
public String getspeed(){
long speed = ClientClass.getspeed();
//System.out.println(speed);
Map<String, Object> result = new HashMap<>();
result.put("speed", speed);
return JSON.toJSONString(result);
}
}
以上就是项目的基本架构,你需要什么其他的功能,只需要添加即可。
使用方法
控制页面如下所示
两个输入框分别代表客户端要连接的ip地址和端口号。
填入了之后点击开启客户端与服务器即可开始收发信息。
使用java读取到的本机ip地址不太准,这个我也不知道是为什么。
最下面有显示当前的收发速率,计算方法为收发的总数除以现在到开始时的持续时间,可能不太准确,但是大概能知道收发的速率如何。
我测试得到的数据如下
可能是网路或者优化等等问题,服务器双机测试的时候接收速率不太高。
总结
rsyslog感觉用的人不是很多,网上的资料很少,而且发送和接收的代码都需要自己编写,不如消息队列来得方便。