【 Spring Boot 实践 】FEMON监控平台项目

来源:互联网 发布:vscode golang 配置 编辑:程序博客网 时间:2024/06/10 00:56

转载自:http://blog.sina.com.cn/s/blog_7d553bb50102w9jj.html


2016年3月14日 11:32:40


1. 项目背景


监控整个测试环境的核心http服务,服务的进程(自动重启),服务器的资源(cpu,mem,disk)

2. 技术框架


服务端:
Java / Spring Boot / JPA / Mysql

参考:

【Spring Boot 开发笔记】2 Spring Boot 环境安装 : http://blog.sina.com.cn/s/blog_7d553bb50102w98j.html

【Spring Boot 开发笔记】 4 Spring Data JPA实践笔记 4.0 Java持久层API(JPA): http://blog.sina.com.cn/s/blog_7d553bb50102w98k.html


前端:
JavaScript / Css /Html / Ajax / Jquery / Bootstrap

参考:菜鸟教程-学的不仅是技术,更是梦想: http://www.runoob.com/


3. 系统架构


功能模块




技术架构





4 系统原型
































5 核心功能实现






http执行引擎


package com.femon.engine;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.femon.config.Constant;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Request.Builder;
import okhttp3.RequestBody;
import okhttp3.Response;
public class OKHttpEngine {
    
    private static final String LOGIN_API_ALL "http://user.wacaiyun.com/login_api/all";
    public static void xmain(String[] args{
        String jsonParamsStr "{"password":"" Constant.LOGIN_PASSWORD_APP "","username":""
                Constant.LOGIN_USERNAME_APP ""}";
        System.out.println(jsonString2paramsMap(jsonParamsStr));
        String loginResult postJson(LOGIN_API_ALLjsonParamsStr);
        System.out.println("postJson====================================================\n" loginResult);
        String cardCountUrl "http://192.168.3.128:7103/cd/card/count";
        Map<String, String> headerMap new HashMap<String, String>();
        Map<String, String> appLoginServiceNodeOutput appLoginServiceNode(Constant.LOGIN_USERNAME_APP,
                Constant.LOGIN_PASSWORD_APP);
        String token appLoginServiceNodeOutput.get("token");
        String refreshToken appLoginServiceNodeOutput.get("refreshToken");
        headerMap.put("accessToken"token);
        headerMap.put("refreshToken"refreshToken);
        headerMap.put("appPlatform""21");
        headerMap.put("appVersion""5.3.0");
        headerMap.put("channelType""1,2,3");
        headerMap.put("deviceId""14FBE92C0BA95144E0D85867A29D4947");
        headerMap.put("mcCode""21000020");
        headerMap.put("systemInfo""iphone 6s plus");
        String qresult getWithQueryParams(cardCountUrlheaderMap);
        System.out.println("qresult==============================================" qresult);
        String hresult getWithHeaderParams(cardCountUrlheaderMap);
        System.out.println("hresult==============================================" hresult);
        ///////////////////////////////// post form////////////////////////////
        String h5LoginUrl "http://8.wacaiyun.com/finance/h5/finance/h5/ulogin.action";
        String formParams "loginMedium=15868187925&loginPwd=123456";
        String formResult postForm(h5LoginUrlformParams);
        System.out.println("formResult==============================================" formResult);
    }
    public static Map<String, String> appLoginServiceNode(String usernameString password{
        Map<String, String> outputMap new HashMap<String, String>();
        String appLoginUrl LOGIN_API_ALL;
        String jsonParamsStr "{"password":"" password "","username":"" username ""}";
        String loginResponse postJson(appLoginUrljsonParamsStr);
        Map loginResponseMap com.alibaba.fastjson.JSON.parseObject(loginResponseMap.class);
        String code (String) loginResponseMap.get("code");
        JSONArray userJSONArray (JSONArray) loginResponseMap.get("users");
        Map usersMap (MapuserJSONArray.get(0);
        if ("0".equals(code)) {
            outputMap.put("token"(String) usersMap.get("token"));
            outputMap.put("refreshToken"(String) usersMap.get("refreshToken"));
        }
        return outputMap;
    }
    
    public static String get(String url{
        OkHttpClient client new OkHttpClient();
        Request request new Request.Builder().url(url).build();
        Response response;
        String result null;
        try {
            response client.newCall(request).execute();
            result response.body().string();
        catch (IOException e{
            e.printStackTrace();
        }
        return result;
    }
    
    public static String getWithQueryParams(String urlMap<String, String> queryMap{
        String queryString paramsMap2QueryStr(queryMap);
        String qurl url "?" queryString;
        return get(qurl);
    }
    
    public static String getWithHeaderParams(String urlMap<String, String> headerMap{
        OkHttpClient client new OkHttpClient();
        // 用平台token替换填写的失效token
        String loginUrl "http://user.wacaiyun.com/login_api/all";
        Map<String, String> appLoginServiceNodeOutput appLoginServiceNode(Constant.LOGIN_USERNAME_APP,
                Constant.LOGIN_PASSWORD_APP);
        String token appLoginServiceNodeOutput.get("token");
        String refreshToken appLoginServiceNodeOutput.get("refreshToken");
        headerMap.put("accessToken"token);
        headerMap.put("refreshToken"refreshToken);
        Builder builder new Request.Builder();
        for (String name headerMap.keySet()) {
            String value headerMap.get(name);
            builder.addHeader(namevalue);
        }
        builder.url(url);
        Request request builder.build();
        Response response;
        String result null;
        try {
            response client.newCall(request).execute();
            result response.body().string();
        catch (IOException e{
            e.printStackTrace();
        }
        return result;
    }
    
    public static String postWithHeaderParams(String apiUrlString jsonParamsStr{
        OkHttpClient client new OkHttpClient();
        Map<String, String> headerMap jsonString2paramsMap(jsonParamsStr);
        // 用平台token替换填写的失效token
        String loginUrl "http://user.wacaiyun.com/login_api/all";
        Map<String, String> appLoginServiceNodeOutput appLoginServiceNode(Constant.LOGIN_USERNAME_APP,
                Constant.LOGIN_PASSWORD_APP);
        String token appLoginServiceNodeOutput.get("token");
        String refreshToken appLoginServiceNodeOutput.get("refreshToken");
        headerMap.put("accessToken"token);
        headerMap.put("refreshToken"refreshToken);
        Builder builder new Request.Builder();
        for (String name headerMap.keySet()) {
            String value headerMap.get(name);
            builder.addHeader(namevalue);
        }
        RequestBody requestBody RequestBody.create(JSON"");
        builder.url(apiUrl).post(requestBody);
        Request request builder.build();
        Response response;
        String result null;
        try {
            response client.newCall(request).execute();
            result response.body().string();
        catch (IOException e{
            e.printStackTrace();
        }
        return result;
    }
    
    public static String postJson(String urlString json{
        OkHttpClient client new OkHttpClient();
        RequestBody body RequestBody.create(JSONjson);
        Request request new Request.Builder().url(url).post(body).build();
        String result null;
        Response response;
        try {
            response client.newCall(request).execute();
            result response.body().string();
        catch (IOException e{
            e.printStackTrace();
        }
        return result;
    }
    
    public static String postForm(String urlString formParams{
        OkHttpClient client new OkHttpClient();
        RequestBody body RequestBody.create(FORMformParams);
        Request request new Request.Builder().url(url).post(body).build();
        String result null;
        Response response;
        try {
            response client.newCall(request).execute();
            result response.body().string();
        catch (IOException e{
            e.printStackTrace();
        }
        return result;
    }
    
    private static String paramsMap2QueryStr(Map<String, String> paramsMap{
        StringBuilder qstr new StringBuilder();
        for (String key paramsMap.keySet()) {
            qstr.append(key);
            qstr.append("=");
            qstr.append(URLEncoder.encode(paramsMap.get(key)));
            // qstr.append(paramsMap.get(key));
            qstr.append("&");
        }
        return qstr.toString();
    }
    private static Map<String, String> jsonString2paramsMap(String jsonString{
        Map<String, String> map com.alibaba.fastjson.JSON.parseObject(jsonStringMap.class);
        return map;
    }
    public static final MediaType JSON MediaType.parse("application/json; charset=utf-8");
    public static final MediaType FORM MediaType.parse("application/x-www-form-urlencoded;charset=utf-8");
}

创建服务前端


 #include("header.html")
<div class="nav-guide">
    <a href="/service">服务管理</a> > 创建服务
</div>
<hr width="96%">
<div class="form-horizontal">
    <div class="form-group">
        <label class="col-sm-2 control-label">测试环境</label>
        <div class="col-sm-3">
            <select name="s-host" class="form-control ">
                <option value="1" selected="selected">一套</option>
                <option value="2">二套</option>
            </select>
        </div>
    </div>
    <div class="form-group">
        <label class="col-sm-2 control-label">域名</label>
        <div class="col-sm-3">
            <input type="text" class="form-control " name="s-hostname"
                value="http://8.wacaiyun.com">
        </div>
    </div>
    <div class="form-group">
        <label class="col-sm-2 control-label">服务名称</label>
        <div class="col-sm-3">
            <input type="text" class="form-control " name="s-name">
        </div>
    </div>
    <div class="form-group">
        <label class="col-sm-2 control-label">URL</label>
        <div class="col-sm-3">
            <input type="text" class="form-control " name="s-url">
        </div>
    </div>
    <div class="form-group">
        <label class="col-sm-2 control-label">请求方法</label>
        <div class="col-sm-3">
            <select name="s-method" class="form-control ">
                <option value="GET">GET</option>
                <option value="POST">POST</option>
            </select>
        </div>
    </div>
    <div class="form-group">
        <label class="col-sm-2 control-label">期望输出</label>
        <div class="col-sm-3">
            <input type="text" class="form-control" name="s-output"
                placeholder='"code":0'></input>
        </div>
    </div>
    <div class="form-group">
        <label class="col-sm-2 control-label">参数类型</label>
        <div class="col-sm-3">
            <select name="param-type" class="form-control">
                <option selected="selected" value="1">普通参数</option>
                <option value="2">json</option>
                <option value="3">header参数</option>
                <option value="4">body参数</option>
            </select>
        </div>
    </div>
    <div class="form-group">
        <label class="col-sm-2 control-label">参数内容</label>
        <div class="col-sm-3">
            <textarea name="param-content" class="form-control"
                placeholder='{"username":"boshu","password":"123456"}'></textarea>
        </div>
    </div>
    <div class="form-group">
        <label class="col-sm-2 control-label">负责人</label>
        <div class="col-sm-3">
            <input type="text" class="form-control" name="s-owner"></input>
        </div>
    </div>
    <div class="form-group">
        <label class="col-sm-2 control-label">邮箱</label>
        <div class="col-sm-3">
            <input type="text" class="form-control" name="s-email"
                placeholder='meiyu@wacai.com'></input>
        </div>
    </div>
    <div class="form-group">
        <div class="col-sm-offset-2 col-sm-10 " style="margin-top30px">
            <a class="btn btn-success col-sm-1" id="bt-service-new">   </a>
        </div>
    </div>
</div>
#include("footer.html")
<script type="text/javascript">
    $(function() {
        serviceSelection();
        $("select[name='s-host']").change(function() {
            var item $(this).val();
            if (item == '1'{
                $("input[name='s-hostname']").val('http://8.wacaiyun.com');
            }
            else {
                $("input[name='s-hostname']").val('http://qa8.wacaiyun.com');
            }
        });
        $("#bt-service-new").on('click'function() {
            var host $("input[name='s-hostname']").val();
            var hostCode $("select[name='s-host']").val();
            var serviceName $("input[name='s-name']").val();
            var requestUrl $("input[name='s-url']").val();
            var requestMethod $("select[name='s-method']").val();
            var expectOutput $("input[name='s-output']").val();
            var owner $("input[name='s-owner']").val();
            var email $("input[name='s-email']").val();
            // 1: 普通参数  2:json串
            var paramType parseInt($("select[name='param-type']").val());
            var paramContent $("textarea[name='param-content']").val();
            if (paramContent == ''{
                paramType 0; //表示没有传参数
            }
            if (serviceName != '' && requestUrl != '' && expectOutput != '' && owner != '' && email != ''{
                $.post("/service/new"{
                    name serviceName,
                    host host,
                    hostCode hostCode,
                    requestUrl requestUrl,
                    expect expectOutput,
                    method requestMethod,
                    paramsType paramType,
                    paramsMap paramContent,
                    owner owner,
                    email email
                }, function(data) {
                    if (data) {
                        window.location.href "/service";
                    }
                    else {
                        alert("Fail");
                    }
                });
            }
            else {
                alert("信息不全!");
            }
        });
    });
</script>  

进程重启

当进程down之后,执行重启脚本:

package com.femon.engine;
import com.jcraft.jsch.Channel;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
import java.io.OutputStream;
import java.io.PrintStream;
public class ShellChannelExecutor {
    public static void runCommands(String usernameString passwordString ipint portString command{
        try {
            JSch jsch new JSch();
            Session session jsch.getSession(usernameipport);
            session.setPassword(password);
            setUpHostKey(session);
            session.connect();
            Channel channel session.openChannel("shell");// only shell
            channel.setOutputStream(System.out);
            OutputStream outputStream channel.getOutputStream();
            PrintStream shellStream new PrintStream(outputStream); // printStream
                                                                     // for
                                                                     // convenience
            channel.connect();
            shellStream.println(command);
            shellStream.flush();
            Thread.sleep(5000);
            channel.disconnect();
            session.disconnect();
        catch (Exception e{
            e.printStackTrace();
        }
    }
    private static void setUpHostKey(Session session{
        java.util.Properties config new java.util.Properties();
        config.put("StrictHostKeyChecking""no");
        session.setConfig(config);
    }
}


远程SSH登录执行shell代码:

package com.femon.engine;
import com.jcraft.jsch.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Properties;
import org.springframework.util.StringUtils;
 
public class RemoteShell {
    private Session session;
    public static final String LINE_SEPARATOR System.getProperty("line.separator");
    public String runRemoteShell(String command{
        if (StringUtils.isEmpty(command))
            return null;
        StringBuilder stringBuffer;
        String result null;
        BufferedReader reader null;
        Channel channel null;
        try {
            stringBuffer new StringBuilder();
            channel session.openChannel("exec"); // execshell
            ((ChannelExec) channel).setCommand(command);
            channel.connect(3000);
            InputStream in channel.getInputStream();
            reader new BufferedReader(new InputStreamReader(in));
            String buf;
            while ((buf reader.readLine()) != null{
                stringBuffer.append(buf.trim()).append(LINE_SEPARATOR);
            }
            result stringBuffer.toString();
        catch (Exception e{
            e.printStackTrace();
        finally {
            try {
                if (reader != null)
                    reader.close();
            catch (IOException e{
                e.printStackTrace();
            }
            if (channel != null)
                channel.disconnect();
        }
        return result;
    }
    public boolean connect(String userString passwdString host{
        JSch jsch new JSch();
        try {
            session jsch.getSession(userhost22);
            session.setPassword(passwd);
            Properties config new Properties();
            config.put("StrictHostKeyChecking""no");
            session.setConfig(config);
            session.connect();
        catch (JSchException e{
            e.printStackTrace();
            return false;
        }
        return true;
    }
    public void disconnect() {
        try {
            session.disconnect();
        catch (Exception e{
            e.printStackTrace();
        }
    }
}

邮件通知

package com.femon.engine;
import java.util.Properties;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
 
public class MailClient {
    private static final String USERNAME "*******";
    private static final String PASSWORD "*******";
    public static void sendMail(String toString titleString content{
        Properties props new Properties();
        props.setProperty("mail.transport.protocol""smtp");
        props.put("mail.smtp.auth""true");
        props.put("mail.smtp.host""mail.xxxx.com");
        props.put("mail.smtp.port""25");
        Session session Session.getInstance(propsnew javax.mail.Authenticator() {
            protected PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication(USERNAMEPASSWORD);
            }
        });
        try {
            Message message new MimeMessage(session);
            message.setFrom(new InternetAddress("qa_notification@xxx.com"));
            message.setRecipients(Message.RecipientType.TOInternetAddress.parse(to));
            message.setSubject(title);
            message.setText(content);
            // MimeMultipart类是一个容器类,包含MimeBodyPart类型的对象
            Multipart mainPart new MimeMultipart();
            MimeBodyPart messageBodyPart new MimeBodyPart();// 创建一个包含附件内容的MimeBodyPart
            // 设置HTML内容
            messageBodyPart.setContent(content"text/html; charset=utf-8");
            mainPart.addBodyPart(messageBodyPart);
            message.setContent(mainPart);
            Transport.send(message);
            System.out.println("Done");
        catch (MessagingException e{
            throw new RuntimeException(e);
        }
    }
}

监控数据统计jpa代码

package com.femon.dao;
import com.femon.entity.ProcessData;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.PagingAndSortingRepository;
import java.util.Date;
import java.util.List;

public interface ProcessDataDao extends PagingAndSortingRepository<ProcessData, Integer> {
    @Query(value "select from fm_process_data where process_id ?1 order by sample_time desc limit 1"nativeQuery true)
    ProcessData findOneByProcessId(int processId);
    @Query(value "select from fm_process_data where process_id ?1 order by sample_time desc limit 40"nativeQuery true)
    List<ProcessData> findByProcessId(int processId);
    @Query(value "select count(*) from fm_process_data where process_id ?1 and sample_time like ?2% and state order by sample_time desc"nativeQuery true)
    int countOfTodaySuccess(int processIdString curDate);
    @Query(value "select count(*) from fm_process_data where process_id ?1 and sample_time like ?2% and state order by sample_time desc"nativeQuery true)
    int countOfTodayFailure(int processIdString curDate);
    
    @Query(value "select count(*) FROM femon.fm_process_data as pd where process_id=?1 and state=?2 and datediff(now(),pd.sample_time )<=?3 order by sample_time desc"nativeQuery true)
    int countStateOfDays(int processIdint stateint days);
    @Query(value "select FROM femon.fm_process_data as pd where process_id=?1 and state=0 and datediff(now(),pd.sample_time )<=?3 order by sample_time desc"nativeQuery true)
    List<ProcessData> findFailsByProcessIdOfDays(int processIdint days);
}






来自为知笔记(Wiz)


附件列表

  • cemon.zip
  • femon2.zip

 


0 0
原创粉丝点击