linux+jenkins+jmeter+ant持续集成
0、安装jdk
1、下载jdk8 登录网址:http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html 选择对应jdk版本下载。(Tips:可在Windows下载完成后,通过FTP或者SSH到发送到Linux上) 2、 登录Linux,切换到root用户 su root 获取root用户权限,当前工作目录不变(需要root密码) 或者 sudo -i 不需要root密码直接切换成root(需要当前用户密码) 3、在usr目录下建立java安装目录 cd /usr mkdir java 4、将jdk-8u60-linux-x64.tar.gz拷贝到java目录下 cp /mnt/hgfs/linux/jdk-8u60-linux-x64.tar.gz /usr/java/ 5、解压jdk到当前目录,得到文件夹 jdk1.8.0_* (注意:下载不同版本的JDK目录名不同!) tar -zxvf jdk-8u60-linux-x64.tar.gz 6、安装完毕为他建立一个链接以节省目录长度 ln -s /usr/java/jdk1.8.0_60/ /usr/jdk 7、编辑配置文件,配置环境变量 vim /etc/profile 在文本的末尾添加如下内容: JAVA_HOME=/usr/jdk CLASSPATH=$JAVA_HOME/lib/ PATH=$PATH:$JAVA_HOME/bin export PATH JAVA_HOME CLASSPATH 8、重启机器或执行命令 :source /etc/profile sudo shutdown -r now 9、查看安装情况 java -version java version "1.8.0_60" Java(TM) SE Runtime Environment (build 1.8.0_60-b27) Java HotSpot(TM) Client VM (build 25.60-b23, mixed mode)
1、安装jenkins
自行BAIDU
2、安装jmeter
下载地址:http://jmeter.apache.org/download_jmeter.cgi,选择binaries下2.9版本。 解压完成后,添加环境变量: vi /etc/profile 添加下述两行: export JMETER="/usr/local/jmeter/apache-jmeter-2.9" export CLASSPATH="$JMETER/lib/ext/ApacheJMeter_core.jar:$JMETER/lib/jorphan.jar:$JMETER/lib/logkit-2.0.jar:$CLASSPATH" 完成添加后下述命令使配置生效: source /etc/profile
3、安装ant
1、从http://ant.apache.org 上下载tar.gz版ant
2、复制到/usr下
3、tar -vxzf apahce-ant-1.9.2-bin.tar.gz 解压
4、chown -R yjdabc apahce-ant-1.9.2 改变权限
chown -R :users apahce-ant-1.9.2
chmod -R +x apahce-ant-1.9.2
5、vi /etc/profile 修改系统配置文件
#set Ant enviroment
export ANT_HOME=/usr/apache-ant-1.9.2
export PATH=$PATH:$ANT_HOME/bin
6、source /etc/proifle 立刻将配置生效
7、ant -version 测试ant是否生效
4、配置
a、将 jmeter的extras目录中ant-jmeter-1.1.1.jar包拷贝至ant安装目录下的lib目录中
b、复制jmeter的lib目录下的xalan-2.7.2.jar和serializer-2.7.2.jar copy到Ant的lib包里
c、生成报告模板jmeter-results-detail-report_21.xsl,放到jmeter_home/extras下(优化排版)
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<!--
Stylesheet for processing 2.1 output format test result files
To uses this directly in a browser, add the following to the JTL file as line 2:
<?xml-stylesheet type="text/xsl" href="../extras/jmeter-results-detail-report_21.xsl"?>
and you can then view the JTL in a browser
-->
<xsl:output method="html" indent="yes" encoding="UTF-8" doctype-public="-//W3C//DTD HTML 4.01 Transitional//EN" />
<!-- Defined parameters (overrideable) -->
<xsl:param name="showData" select="'n'"/>
<xsl:param name="titleReport" select="'Load Test Results'"/>
<xsl:param name="dateReport" select="'date not defined'"/>
<xsl:template match="testResults">
<html>
<head>
<title><xsl:value-of select="$titleReport" /></title>
<style type="text/css">
body {
font:normal 68% verdana,arial,helvetica;
color:#000000;
}
table tr td, table tr th {
font-size: 68%;
}
table.details tr th{
color: #ffffff;
font-weight: bold;
text-align:center;
background:#2674a6;
white-space: nowrap;
}
table.details tr td{
background:#eeeee0;
white-space: nowrap;
}
h1 {
margin: 0px 0px 5px; font: 165% verdana,arial,helvetica
}
h2 {
margin-top: 1em; margin-bottom: 0.5em; font: bold 125% verdana,arial,helvetica
}
h3 {
margin-bottom: 0.5em; font: bold 115% verdana,arial,helvetica
}
.Failure {
font-weight:bold; color:red;
}
img
{
border-width: 0px;
}
.expand_link
{
position=absolute;
right: 0px;
width: 27px;
top: 1px;
height: 27px;
}
.page_details
{
display: none;
}
.page_details_expanded
{
display: block;
display/* hide this definition from IE5/6 */: table-row;
}
</style>
<script language="JavaScript"><![CDATA[
function expand(details_id)
{
document.getElementById(details_id).className = "page_details_expanded";
}
function collapse(details_id)
{
document.getElementById(details_id).className = "page_details";
}
function change(details_id)
{
if(document.getElementById(details_id+"_image").src.match("expand"))
{
document.getElementById(details_id+"_image").src = "collapse.png";
expand(details_id);
}
else
{
document.getElementById(details_id+"_image").src = "expand.png";
collapse(details_id);
}
}
]]></script>
</head>
<body>
<xsl:call-template name="pageHeader" />
<xsl:call-template name="summary" />
<hr size="1" width="95%" align="center" />
<xsl:call-template name="pagelist" />
<hr size="1" width="95%" align="center" />
<xsl:call-template name="detail" />
</body>
</html>
</xsl:template>
<xsl:template name="pageHeader">
<h1><xsl:value-of select="$titleReport" /></h1>
<!--<table width="100%">
<tr>
<td align="left">Date report: <xsl:value-of select="$dateReport" /></td>
<td align="right">Designed for use with <a href="http://jmeter.apache.org/">JMeter</a> and <a href="http://ant.apache.org">Ant</a>.</td>
</tr>
</table>-->
<hr size="1" />
</xsl:template>
<xsl:template name="summary">
<h2>Summary</h2>
<table align="center" class="details" border="0" cellpadding="5" cellspacing="2" width="95%">
<tr valign="top">
<th># Samples</th>
<th>Failures</th>
<th>Success Rate</th>
<th>Average Time</th>
<th>Min Time</th>
<th>Max Time</th>
</tr>
<tr valign="top">
<xsl:variable name="allCount" select="count(/testResults/*)" />
<xsl:variable name="allFailureCount" select="count(/testResults/*[attribute::s='false'])" />
<xsl:variable name="allSuccessCount" select="count(/testResults/*[attribute::s='true'])" />
<xsl:variable name="allSuccessPercent" select="$allSuccessCount div $allCount" />
<xsl:variable name="allTotalTime" select="sum(/testResults/*/@t)" />
<xsl:variable name="allAverageTime" select="$allTotalTime div $allCount" />
<xsl:variable name="allMinTime">
<xsl:call-template name="min">
<xsl:with-param name="nodes" select="/testResults/*/@t" />
</xsl:call-template>
</xsl:variable>
<xsl:variable name="allMaxTime">
<xsl:call-template name="max">
<xsl:with-param name="nodes" select="/testResults/*/@t" />
</xsl:call-template>
</xsl:variable>
<xsl:attribute name="class">
<xsl:choose>
<xsl:when test="$allFailureCount > 0">Failure</xsl:when>
</xsl:choose>
</xsl:attribute>
<td align="center">
<xsl:value-of select="$allCount" />
</td>
<td align="center">
<xsl:value-of select="$allFailureCount" />
</td>
<td align="center">
<xsl:call-template name="display-percent">
<xsl:with-param name="value" select="$allSuccessPercent" />
</xsl:call-template>
</td>
<td align="center">
<xsl:call-template name="display-time">
<xsl:with-param name="value" select="$allAverageTime" />
</xsl:call-template>
</td>
<td align="center">
<xsl:call-template name="display-time">
<xsl:with-param name="value" select="$allMinTime" />
</xsl:call-template>
</td>
<td align="center">
<xsl:call-template name="display-time">
<xsl:with-param name="value" select="$allMaxTime" />
</xsl:call-template>
</td>
</tr>
</table>
</xsl:template>
<xsl:template name="pagelist">
<h2>Pages</h2>
<table align="center" class="details" border="0" cellpadding="5" cellspacing="2" width="95%">
<tr valign="top">
<th>URL</th>
<th># Samples</th>
<th>Failures</th>
<th>Success Rate</th>
<th>Average Time</th>
<th>Min Time</th>
<th>Max Time</th>
<th></th>
</tr>
<xsl:for-each select="/testResults/*[not(@lb = preceding::*/@lb)]">
<xsl:variable name="label" select="@lb" />
<xsl:variable name="count" select="count(../*[@lb = current()/@lb])" />
<xsl:variable name="failureCount" select="count(../*[@lb = current()/@lb][attribute::s='false'])" />
<xsl:variable name="successCount" select="count(../*[@lb = current()/@lb][attribute::s='true'])" />
<xsl:variable name="successPercent" select="$successCount div $count" />
<xsl:variable name="totalTime" select="sum(../*[@lb = current()/@lb]/@t)" />
<xsl:variable name="averageTime" select="$totalTime div $count" />
<xsl:variable name="minTime">
<xsl:call-template name="min">
<xsl:with-param name="nodes" select="../*[@lb = current()/@lb]/@t" />
</xsl:call-template>
</xsl:variable>
<xsl:variable name="maxTime">
<xsl:call-template name="max">
<xsl:with-param name="nodes" select="../*[@lb = current()/@lb]/@t" />
</xsl:call-template>
</xsl:variable>
<tr valign="top">
<xsl:attribute name="class">
<xsl:choose>
<xsl:when test="$failureCount > 0">Failure</xsl:when>
</xsl:choose>
</xsl:attribute>
<td>
<xsl:if test="$failureCount > 0">
<a><xsl:attribute name="href">#<xsl:value-of select="$label" /></xsl:attribute>
<xsl:value-of select="$label" />
</a>
</xsl:if>
<xsl:if test="0 >= $failureCount">
<xsl:value-of select="$label" />
</xsl:if>
</td>
<td align="center">
<xsl:value-of select="$count" />
</td>
<td align="center">
<xsl:value-of select="$failureCount" />
</td>
<td align="right">
<xsl:call-template name="display-percent">
<xsl:with-param name="value" select="$successPercent" />
</xsl:call-template>
</td>
<td align="right">
<xsl:call-template name="display-time">
<xsl:with-param name="value" select="$averageTime" />
</xsl:call-template>
</td>
<td align="right">
<xsl:call-template name="display-time">
<xsl:with-param name="value" select="$minTime" />
</xsl:call-template>
</td>
<td align="right">
<xsl:call-template name="display-time">
<xsl:with-param name="value" select="$maxTime" />
</xsl:call-template>
</td>
<td align="center">
<a href="">
<xsl:attribute name="href"><xsl:text/>javascript:change('page_details_<xsl:value-of select="position()" />')</xsl:attribute>
<img src="expand.png" alt="expand/collapse"><xsl:attribute name="id"><xsl:text/>page_details_<xsl:value-of select="position()" />_image</xsl:attribute></img>
</a>
</td>
</tr>
<tr class="page_details">
<xsl:attribute name="id"><xsl:text/>page_details_<xsl:value-of select="position()" /></xsl:attribute>
<td colspan="8" bgcolor="#FF0000">
<div align="center">
<b>Details for Page "<xsl:value-of select="$label" />"</b>
<table bordercolor="#000000" bgcolor="#2674A6" border="0" cellpadding="1" cellspacing="1" width="95%">
<tr>
<th>Thread</th>
<th>Iteration</th>
<th>Time (milliseconds)</th>
<th>Bytes</th>
<th>Success</th>
</tr>
<xsl:for-each select="../*[@lb = $label and @tn != $label]">
<tr>
<td><xsl:value-of select="@tn" /></td>
<td align="center"><xsl:value-of select="position()" /></td>
<td align="right"><xsl:value-of select="@t" /></td>
<!-- TODO allow for missing bytes field -->
<td align="right"><xsl:value-of select="@by" /></td>
<td align="center"><xsl:value-of select="@s" /></td>
</tr>
</xsl:for-each>
</table>
</div>
</td>
</tr>
</xsl:for-each>
</table>
</xsl:template>
<xsl:template name="detail">
<xsl:variable name="allFailureCount" select="count(/testResults/*[attribute::s='false'])" />
<xsl:if test="$allFailureCount > 0">
<h2>Failure Detail</h2>
<xsl:for-each select="/testResults/*[not(@lb = preceding::*/@lb)]">
<xsl:variable name="failureCount" select="count(../*[@lb = current()/@lb][attribute::s='false'])" />
<xsl:if test="$failureCount > 0">
<h3><xsl:value-of select="@lb" /><a><xsl:attribute name="name"><xsl:value-of select="@lb" /></xsl:attribute></a></h3>
<table align="center" class="details" border="0" cellpadding="5" cellspacing="2" width="95%">
<tr valign="top">
<!--<th>Response</th>-->
<th>Failure Message</th>
<xsl:if test="$showData = 'y'">
<th>Response Data</th>
</xsl:if>
</tr>
<xsl:for-each select="/testResults/*[@lb = current()/@lb][attribute::s='false']">
<tr>
<!--<td><xsl:value-of select="@rc | @rs" /> - <xsl:value-of select="@rm" /></td>-->
<td><pre style="white-space: pre-wrap;word-wrap: break-word;"><xsl:value-of select="assertionResult/failureMessage" /></pre></td>
<xsl:if test="$showData = 'y'">
<td><xsl:value-of select="./binary" /></td>
</xsl:if>
</tr>
</xsl:for-each>
</table>
</xsl:if>
</xsl:for-each>
</xsl:if>
</xsl:template>
<xsl:template name="min">
<xsl:param name="nodes" select="/.." />
<xsl:choose>
<xsl:when test="not($nodes)">NaN</xsl:when>
<xsl:otherwise>
<xsl:for-each select="$nodes">
<xsl:sort data-type="number" />
<xsl:if test="position() = 1">
<xsl:value-of select="number(.)" />
</xsl:if>
</xsl:for-each>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="max">
<xsl:param name="nodes" select="/.." />
<xsl:choose>
<xsl:when test="not($nodes)">NaN</xsl:when>
<xsl:otherwise>
<xsl:for-each select="$nodes">
<xsl:sort data-type="number" order="descending" />
<xsl:if test="position() = 1">
<xsl:value-of select="number(.)" />
</xsl:if>
</xsl:for-each>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="display-percent">
<xsl:param name="value" />
<xsl:value-of select="format-number($value,'0.00%')" />
</xsl:template>
<xsl:template name="display-time">
<xsl:param name="value" />
<xsl:value-of select="format-number($value,'0 ms')" />
</xsl:template>
</xsl:stylesheet>
d、修改jmeter的bin目录下的jmeter.properties文件的配置:jmeter.save.saveservice.output_format=xml
e、对于生成详细报告的测试数据需要在jmeter的bin目录下的jmeter.properties文件的配置:
jmeter.save.saveservice.assertion_results=none # jmeter.save.saveservice.data_type=true jmeter.save.saveservice.label=true jmeter.save.saveservice.response_code=true # response_data is not currently supported for CSV output jmeter.save.saveservice.response_data=true # Save ResponseData for failed samples jmeter.save.saveservice.response_data.on_error=true jmeter.save.saveservice.response_message=true jmeter.save.saveservice.successful=true jmeter.save.saveservice.thread_name=true jmeter.save.saveservice.time=true jmeter.save.saveservice.subresults=true jmeter.save.saveservice.assertions=true jmeter.save.saveservice.latency=true # Only available with HttpClient4 jmeter.save.saveservice.connect_time=false jmeter.save.saveservice.samplerData=false jmeter.save.saveservice.responseHeaders=false jmeter.save.saveservice.requestHeaders=false jmeter.save.saveservice.encoding=false jmeter.save.saveservice.bytes=true # Only available with HttpClient4 jmeter.save.saveservice.sent_bytes=true jmeter.save.saveservice.url=true jmeter.save.saveservice.filename=false jmeter.save.saveservice.hostname=false jmeter.save.saveservice.thread_counts=true jmeter.save.saveservice.sample_count=false jmeter.save.saveservice.idle_time=false
f、创建build.xml,放到jmeter_home/extras下或ant_home/bin下
<?xml version="1.0" encoding="utf-8"?>
<project name="JmeterTest" default="all" basedir=".">
<tstamp>
<format property="time" pattern="yyyyMMddhhmm" />
</tstamp>
<!-- 需要改成自己本地的 Jmeter 目录-->
<property name="jmeter.home" value="/data/jmeter/apache-jmeter-3.3" />
<!-- jmeter生成jtl格式的结果报告的路径-->
<property name="jmeter.result.jtl.dir" value="/data/jmeter/apache-jmeter-3.3/report/jtl" />
<!-- jmeter生成html格式的结果报告的路径-->
<property name="jmeter.result.html.dir" value="/data/jmeter/apache-jmeter-3.3/report/html" />
<!-- 生成的报告的前缀 -->
<property name="ReportName" value="TestReport" />
<property name="jmeter.result.jtlName" value="${jmeter.result.jtl.dir}/${ReportName}${time}.jtl" />
<property name="jmeter.result.htmlName" value="${jmeter.result.html.dir}/${ReportName}${time}.html" />
<!-- 接收测试报告的邮箱 -->
<property name="mail_to" value="jiangyf@wondershare.cn" />
<!-- 电脑地址 -->
<property name="ComputerName" value="Yyj" />
<target name="all">
<antcall target="test" />
<antcall target="report" />
<antcall target="sendmail" />
</target>
<target name="test">
<taskdef name="jmeter" classname="org.programmerplanet.ant.taskdefs.jmeter.JMeterTask" />
<jmeter jmeterhome="${jmeter.home}" resultlog="${jmeter.result.jtlName}">
<!-- 声明要运行的脚本。"*.jmx"指包含此目录下的所有jmeter脚本 -->
<testplans dir="/data/jmeter/apache-jmeter-3.3/script" includes="*.jmx" />
<property name="jmeter.save.saveservice.output_format" value="xml"/>
</jmeter>
</target>
<target name="report">
<xslt
in="${jmeter.result.jtlName}"
out="${jmeter.result.htmlName}"
style="${jmeter.home}/extras/jmeter-results-detail-report_21.xsl" />
<!-- 因为上面生成报告的时候,不会将相关的图片也一起拷贝至目标目录,所以,需要手动拷贝 -->
<copy todir="${jmeter.result.html.dir}">
<fileset dir="${jmeter.home}/extras">
<include name="collapse.png" />
<include name="expand.png" />
</fileset>
</copy>
</target>
<!-- 发送邮件 -->
<target name="sendmail" >
<mail mailhost="smtp.wondershare.cn"
mailport="993"
ssl="true"
user="jiangyf@wondershare.cn"
password="wondershare123456"
subject="接口测试报告"
from="jiangyf@wondershare.cn"
>
<to address="jiangyf@wondershare.cn"/>
<message>详细报告请查看附件</message>
<attachments>
<fileset dir="${jmeter.result.html.dir}">
<include name="${ReportName}${time}.html"/>
</fileset>
</attachments>
</mail>
</target>
</project>
g、配置jenkins的Global Tool Configuration


h、配置jenkins的构建任务:

linux+jenkins+jmeter+ant持续集成的更多相关文章
- jenkins,jmeter,ant持续集成
1.安装 jenkins, jmeter, ant 2.将 jmeter下extras中的 ant-jmeter-1.1.1.jar拷贝到ant的lib下面 3.将 jmeter下collapse ...
- 我的套路(windows):Jenkins+Jmeter+Ant持续集成
前期准备: 1.Jdk1.6或以上:http://www.oracle.com/technetwork/java/javase/downloads/index.html 命令行输入:java -ver ...
- Jenkins+Jmeter+Ant自动化集成及邮件正文以html输出
一.工具的安装与环境变量配置 1.依次安装Jenkins+Jmeter+Ant,具体安装步骤,此文不再详述 2.配置Jmeter&ant环境变量 Jmeter变量: 验证是否配置成功:cmd窗 ...
- Jenkins + Jmeter +Ant自动化集成环境搭建(一)
所需工具 一.jmeter 工具下载 https://jmeter.apache.org/ 配置环境JDK等及各种插件可以看小七之前的教程 二.Ant安装(http://ant.apache.org ...
- Jenkins+Jmeter+Ant自动化集成环境搭建
1.搭建环境,安装以下工具 JDK:jdk1.7.0_79 Ant:apache-ant-1.9.7 Jmeter: apache-jmeter-3.0 Jenkins: jenkins-1.651. ...
- linux+jenkins+github+python持续集成
1.服务器上事先安装jenkins 参见:linux上war包方式安装Jenkins 2.新建一个自由风格的job,名字随意起 3.配置git(拉取github代码) 从github复制pytho ...
- jmeter --- 搭建持续集成接口测试平台(Jenkins+Ant+Jmeter)
jmeter --- 搭建持续集成接口测试平台(Jenkins+Ant+Jmeter) 一.环境准备: 1.JDK:http://www.oracle.com/technetwork/java/jav ...
- Jenkins+Ant+Git+Jmeter实现持续集成
个人记录: 基本的配置与Jenkins+Ant+SVN+Jmeter实现持续集成的配置一样,主要在Jenkins的配置上的区别会有所不同 安装的插件: enkins安装好之后,需要为其安装gitlab ...
- jmeter+ant+jenkins 接口自动化测试持续集成(送源码)
9.1 安装和介绍 JMeter 安装文件路径:https://pan.baidu.com/s/1kVJdnuv. JMeter 是轻量级的开源且稳定的自动化测试工具. 思路:在接口说明文档中整理 ...
随机推荐
- mongodb 案例 ~ 经典故障案例
一 简介:此文汇总遇到过和搜集过的故障案例 二 场景案例 1 问题描述: mongo集群在无任何业务情况下,mongos所在服务器cpu突然被打满,内核日志报错 mongos被hung住,非常奇怪的问 ...
- win10家庭版多用户
1.Windows 找不到gpedit.msc https://jingyan.baidu.com/article/54b6b9c08b08382d593b4747.html 2.win10家庭版 创 ...
- 论文笔记:Selective Search for Object Recognition
与 Selective Search 初次见面是在著名的物体检测论文 「Rich feature hierarchies for accurate object detection and seman ...
- RocketMQ 简单梳理 及 集群部署笔记【转】
一.RocketMQ 基础知识介绍Apache RocketMQ是阿里开源的一款高性能.高吞吐量.队列模型的消息中间件的分布式消息中间件. 上图是一个典型的消息中间件收发消息的模型,RocketMQ也 ...
- vc++基础班[26]---进程的相关操作
①.ShellExecute 进行进程的创建,属于 shell api: //int iRet = (int)ShellExecute(m_hWnd, _T("open"), ...
- 题解-CTSC2012 熟悉的文章
Problem bzoj 题目大意:给定多个标准串和一个文本串,全部为01串,如果一个串长度不少于\(L\)且是任意一个标准串的子串,那么它是"熟悉"的.对于文本串\(A\),把\ ...
- 通过flask实现web页面简单的增删改查
通过flask实现web页面简单的增删改查 # 1.后台程序falsk_web01.py #coding:utf-8 from flask import Flask,render_template,r ...
- elasticsearch5.0.1集群排错的几个思路总结
1.首先查看集群整体健康状态 # curl -XGET http://10.27.35.94:9200/_cluster/health?pretty { "cluster_name" ...
- 【算法】二分查找法&大O表示法
二分查找 基本概念 二分查找是一种算法,其输入是一个有序的元素列表.如果要查找的元素包含在列表中,二分查找返回其位置:否则返回null. 使用二分查找时,每次都排除一半的数字 对于包含n个元素的列表, ...
- Spring Cloud Sleuth超详细实战
为什么需要Spring Cloud Sleuth 微服务架构是一个分布式架构,它按业务划分服务单元,一个分布式系统往往有很多个服务单元.由于服务单元数量众多,业务的复杂性,如果出现了错误和异常,很难去 ...