<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Posts on Jimmy's Blog</title><link>https://blog.jimersylee.com/posts/</link><description>Recent content in Posts on Jimmy's Blog</description><generator>Hugo</generator><language>zh-cn</language><lastBuildDate>Wed, 28 Jan 2026 12:01:00 +0800</lastBuildDate><atom:link href="https://blog.jimersylee.com/posts/index.xml" rel="self" type="application/rss+xml"/><item><title>卡片工作法在notion中的实践</title><link>https://blog.jimersylee.com/posts/%E5%8D%A1%E7%89%87%E5%B7%A5%E4%BD%9C%E6%B3%95%E5%9C%A8notion%E4%B8%AD%E7%9A%84%E5%AE%9E%E8%B7%B5/</link><pubDate>Wed, 28 Jan 2026 12:01:00 +0800</pubDate><guid>https://blog.jimersylee.com/posts/%E5%8D%A1%E7%89%87%E5%B7%A5%E4%BD%9C%E6%B3%95%E5%9C%A8notion%E4%B8%AD%E7%9A%84%E5%AE%9E%E8%B7%B5/</guid><description>&lt;h2 id="概念"&gt;概念&lt;/h2&gt;
&lt;h3 id="什么是卡片工作法"&gt;什么是卡片工作法&lt;/h3&gt;
&lt;p&gt;&lt;img alt="Untitled" loading="lazy" src="%E5%8D%A1%E7%89%87%E5%B7%A5%E4%BD%9C%E6%B3%95%E5%9C%A8notion%E4%B8%AD%E7%9A%84%E5%AE%9E%E8%B7%B5/Untitled.png"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="Untitled" loading="lazy" src="%E5%8D%A1%E7%89%87%E5%B7%A5%E4%BD%9C%E6%B3%95%E5%9C%A8notion%E4%B8%AD%E7%9A%84%E5%AE%9E%E8%B7%B5/Untitled%201.png"&gt;&lt;/p&gt;
&lt;h2 id="实践"&gt;实践&lt;/h2&gt;
&lt;h3 id="选用工具-以notion为例"&gt;选用工具-以notion为例&lt;/h3&gt;
&lt;h3 id="notion-synced-block支持的功能"&gt;notion synced block支持的功能&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;写在一个地方,可以同步到任何地方&lt;/li&gt;
&lt;li&gt;在使用同步块的任何页面,随时编辑,可以实时同步,不用找到最原始的出处,方便修改&lt;/li&gt;
&lt;li&gt;任意block可以随意转换成同步块&lt;/li&gt;
&lt;li&gt;在某些场景下,一个同步块的内容在不同的使用场景下,需要进行些许的修改,但是又不想影响到原始的内容,则可以在使用的地方对这个同步块进行unsync操作&lt;/li&gt;
&lt;li&gt;支持源同步块一键取消所有同步→unsync&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="notion中如何实践卡片笔记"&gt;Notion中如何实践卡片笔记&lt;/h2&gt;
&lt;p&gt;参考 &lt;a href="https://www.bilibili.com/video/BV1mG411g7Wz"&gt;https://www.bilibili.com/video/BV1mG411g7Wz&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="让ai助力资讯收集"&gt;让AI助力资讯收集&lt;/h2&gt;
&lt;p&gt;参考 &lt;a href="https://www.bilibili.com/video/BV1524y1M73Y"&gt;https://www.bilibili.com/video/BV1524y1M73Y&lt;/a&gt;， 新建一个带有AI block的模板, 让AI来帮助我们将文章分类, 以及做摘要, 方便分类&lt;/p&gt;
&lt;h2 id="思考"&gt;思考&lt;/h2&gt;
&lt;h2 id="参考"&gt;参考&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://www.notion.so/help/synced-blocks"&gt;Synced blocks - Notion Help Center&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://www.bilibili.com/video/BV1Vb411k7wE"&gt;【社会学】 访谈卢曼：1973年与1989年 （双语）_哔哩哔哩_bilibili&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://www.notion.so/Forte-Labs-76092829a9fa4bbfb5a177429a824f17?pvs=21"&gt;创意笔记大师：卢曼和达芬奇 - Forte Labs&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://www.notion.so/d6ec09b1dce84bbba7d8fa15853ad42b?pvs=21"&gt;卢曼纪录片卡片盒分析笔记&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://www.notion.so/Notion-f95d16236b07412b99fba607ba163933?pvs=21"&gt;关联起发散的思维成果，我用 Notion 实践卡片盒笔记法&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://www.bilibili.com/video/BV1524y1M73Y"&gt;https://www.bilibili.com/video/BV1524y1M73Y&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>20200822-杭州永辉菜价</title><link>https://blog.jimersylee.com/posts/20200822-%E6%9D%AD%E5%B7%9E%E6%B0%B8%E8%BE%89%E8%8F%9C%E4%BB%B7/</link><pubDate>Mon, 22 Aug 2022 10:00:00 +0800</pubDate><guid>https://blog.jimersylee.com/posts/20200822-%E6%9D%AD%E5%B7%9E%E6%B0%B8%E8%BE%89%E8%8F%9C%E4%BB%B7/</guid><description>记录一下物价水平</description></item><item><title>机器学习实战-学习笔记之Decision Trees</title><link>https://blog.jimersylee.com/posts/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0%E5%AE%9E%E6%88%98-%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%E4%B9%8Bdecision-trees/</link><pubDate>Thu, 21 Jul 2022 10:35:00 +0800</pubDate><guid>https://blog.jimersylee.com/posts/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0%E5%AE%9E%E6%88%98-%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%E4%B9%8Bdecision-trees/</guid><description>&lt;p&gt;项目地址:&lt;a href="http://github.com/jimersylee/MachineLearningAction"&gt;http://github.com/jimersylee/MachineLearningAction&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="决策树decision-trees"&gt;&lt;strong&gt;决策树(Decision Trees)&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;类似20个问题的游戏 参与游戏的一方在脑海里想某个事物,其他参与者向他提问题,只允许提20个问题,问题的答案只能用对或错回答,问问题的人通过推断分解,逐步缩小带猜测事物的范围.决策树的工作原理与20个问题类似,用户输入一系列数据,然后给出游戏的答案&lt;/p&gt;
&lt;p&gt;决策树 优点:计算复杂度不高,输入结果易于理解,对中间值的缺失不敏感,可以处理不相关特征数据 缺点:可能产生过度匹配问题 适用数据类型:数值型与标称型&lt;/p&gt;
&lt;p&gt;决策树的一般流程&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;收集数据:可以适用任何方法&lt;/li&gt;
&lt;li&gt;准备数据:树构造算法只适用于标称型数据,因此数值型数据必须离散化&lt;/li&gt;
&lt;li&gt;分析数据:可以适用任何方法,构造书完成之后,我们应该检查图形是否符合预期&lt;/li&gt;
&lt;li&gt;训练算法:构造树的数据结构&lt;/li&gt;
&lt;li&gt;测试算法:适用经验树计算错误率&lt;/li&gt;
&lt;li&gt;适用算法:此步骤可以适用于任何监督学习算法,而适用决策树可以更好地理解数据的内在含义&lt;/li&gt;
&lt;/ol&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;# coding:utf-8from mathimport log
import operator
import matplotlib.pyplotas plt
defcalcShannonEnt(dataSet):
&amp;#34;&amp;#34;&amp;#34;
计算给定数据集的香农熵,香农熵代表数据的无序程度,香农熵越大,数据集越无序
:param dataSet: 数据集
:return:香农熵的值
&amp;#34;&amp;#34;&amp;#34;
numEntries = len(dataSet)# 获得数据中实例的总数
labelCounts = {}# 声明一个字典# 为所有可能分类创建字典,它的键值是最后一列的数值for featVecin dataSet:
currentLabel = featVec[-1]# 目前的标签=数据集的每行的最后一个元素if currentLabelnotin labelCounts.keys():# 如果键值不存在,则扩展字典并将当前键值加入字典
labelCounts[currentLabel] = 0# 初始化为0
labelCounts[currentLabel] = labelCounts[currentLabel] + 1# 每个键值都记录了当前类别出现的次数,出现一次加1
shannonEnt = 0.0
for keyin labelCounts:
prob = float(labelCounts[key]) / numEntries# 使用所有类标签的发生频率计算类别出现的概率
shannonEnt = shannonEnt - prob * log(prob, 2)# 使用这个概率计算香农熵 以2为底求对数return shannonEnt
defcreateDataSet():
&amp;#34;&amp;#34;&amp;#34;
创建简单鱼类鉴定数据集
:return:dataSet(数据集),labels(标签)
&amp;#34;&amp;#34;&amp;#34;
_dataSet = [
[1, 1, &amp;#39;yes&amp;#39;],
[1, 1, &amp;#39;yes&amp;#39;],
[1, 0, &amp;#39;no&amp;#39;],
[0, 1, &amp;#39;no&amp;#39;],
[0, 1, &amp;#39;no&amp;#39;]
]
_labels = [&amp;#39;no surfacing&amp;#39;, &amp;#39;flippers&amp;#39;]
return _dataSet, _labels
myData, labels = createDataSet()
print myData
print calcShannonEnt(myData)
&amp;#34;&amp;#34;&amp;#34;
result
[[1, 1, &amp;#39;yes&amp;#39;], [1, 1, &amp;#39;yes&amp;#39;], [1, 0, &amp;#39;no&amp;#39;], [0, 1, &amp;#39;no&amp;#39;], [0, 1, &amp;#39;no&amp;#39;]]
0.970950594455
&amp;#34;&amp;#34;&amp;#34;
# 熵越高,则混合的数据也越多,我们可以在数据集中添加更多的分类,观察熵是如何变化的,这里我们增加第三个名为maybe的分类,测试熵的变化
myData[0][-1] = &amp;#39;maybe&amp;#39;# 第0行的最后一个元素置为maybeprint myData
print calcShannonEnt(myData)
&amp;#34;&amp;#34;&amp;#34;
[[1, 1, &amp;#39;maybe&amp;#39;], [1, 1, &amp;#39;yes&amp;#39;], [1, 0, &amp;#39;no&amp;#39;], [0, 1, &amp;#39;no&amp;#39;], [0, 1, &amp;#39;no&amp;#39;]]
1.37095059445
&amp;#34;&amp;#34;&amp;#34;
# 得到熵以后,我们就可以按照获取最大信息增益的方法划分数据集# 另一个度量集合无需程度的方法是`基尼不纯度`(Gini impurity),简单地说就是从一个数据集中随机选取子项,度量其被错误分类到其他分组里的概率&amp;#34;&amp;#34;&amp;#34;
分类算法除了要测量信息熵,还需要划分数据集,度量花费数据集的熵,以便判断当前是否正确划分了数据集,我们将对每个特征划分数据集的结果计算一次信息熵,然后判断按照那个特征划分数据集是最好的划分方式
&amp;#34;&amp;#34;&amp;#34;
defsplitDataSet(dataSet, axis, value):
&amp;#34;&amp;#34;&amp;#34;
按照给定特征划分数据集
:param dataSet: 待划分的数据集
:param axis:划分数据集的特征位
:param value:预设特征值
:return:
&amp;#34;&amp;#34;&amp;#34;
retDataSet = []# 创建新的list对象,因为函数中传递的是列表的引用,在函数内部对列表对象的修改,将会影响该列表对象的整个生存周期,因此需要创建一个新的列表for featVecin dataSet:
if featVec[axis] == value:# 如果axis位的值等于预设的特征值
reducedFeatVec = featVec[:axis]# 取行数据的前axis位
reducedFeatVec.extend(featVec[axis + 1:])# 加上axis位后的元素
retDataSet.append(reducedFeatVec)# 就是将除了axis特征位的元素抽取出来return retDataSet
# 测试splitDataSetprint &amp;#34;测试splitDataSet&amp;#34;
myData, labels = createDataSet()
print myData
newData = splitDataSet(myData, 0, 1)# 将待测试数据的第0位为1的数据的其他特征和标签筛选出来print newData
defchooseBestFeatureToSplit(dataSet):
&amp;#34;&amp;#34;&amp;#34;
选择最好的数据集划分方式
:param dataSet: 数据集
:return:
&amp;#34;&amp;#34;&amp;#34;
numFeatures = len(dataSet[0]) - 1
# 计算整个数据的原始香农熵
baseEntropy = calcShannonEnt(dataSet)
bestInfoGain = 0.0
bestFeature = -1
# 遍历数据集中的所有特征for iin range(numFeatures):
# 创建唯一的分类标签列表
featList = [example[i]for examplein dataSet]
uniqueVals = set(featList)# 将list转换为set,集合类型中每个值不同,从列表中创建集合是Python语言中得到列表中唯一元素值的最快方法
newEntropy = 0.0
# 计算每种划分方式的信息熵for valuein uniqueVals:# 遍历当前特征中的所以唯一属性值,对每个特征划分一次数据集
subDataSet = splitDataSet(dataSet, i, value)
prob = len(subDataSet) / float(len(dataSet))
newEntropy += prob * calcShannonEnt(subDataSet)# 并对所有唯一特征值得到的熵求和
infoGian = baseEntropy - newEntropy# 信息增益=熵的减少值或者数据无序度的减少# 计算最好的信息增益if infoGian &amp;gt; bestInfoGain:
bestInfoGain = infoGian
bestFeature = i
return bestFeature# 返回最好特征划分的索引值# 获取最好特征划分索引值print &amp;#34;获取最好特征划分索引值&amp;#34;
myData, labels = createDataSet()
print &amp;#34;dataSet:&amp;#34; + str(myData)
print &amp;#34;best index:&amp;#34; + str(chooseBestFeatureToSplit(myData))
&amp;#34;&amp;#34;&amp;#34;
代码表示,第0个特征是最好的用户划分数据集的特征
&amp;#34;&amp;#34;&amp;#34;
&amp;#34;&amp;#34;&amp;#34;
递归构建决策树
&amp;#34;&amp;#34;&amp;#34;
defmajorityCnt(classList):
&amp;#34;&amp;#34;&amp;#34;
类似classify0部分的投票表决
创建键值为classList中唯一值的数据字典,字典对象存储了classList中每个类标签出现的频率,最后利用operator操作键值排序字典,返回出现次数最多的分类名称
:rtype: str
:param classList: 分类名称的列表
:return: 返回出现次数最多的分类名称
&amp;#34;&amp;#34;&amp;#34;
classCount = {}
for votein classList:
if votenotin classCount.keys():# 如果投票的类别不在classCount字典的key中,
classCount[vote] = 0# 则新建此key,value设置为0
classCount[vote] += 1
sortedClassCount = sorted(classCount.iteritems(), key=operator.itemgetter(1), reverse=True)
return sortedClassCount[0][0]
defcreateTree(dataSet, labels):
&amp;#34;&amp;#34;&amp;#34;
创建树,使用了递归
:param dataSet:数据集
:param labels: 分类标签
:return: 树结构
&amp;#34;&amp;#34;&amp;#34;
classList = [example[-1]for examplein dataSet]# 将数据集中的每一行的最后一个元素的值取出生成类别列表classListif classList.count(classList[0]) == len(classList):# 递归停止条件1return classList[0]# 类别完全相同时停止继续划分if len(dataSet[0]) == 1:# 递归停止条件2return majorityCnt(classList)# 遍历完所有特征时返回出现次数最多的
bestFeat = chooseBestFeatureToSplit(dataSet)# 选择最好的划分特征位
bestFeatLabel = labels[bestFeat]# 取出最好的标签
myTree = {bestFeatLabel: {}}# 初始化一个tree字典del (labels[bestFeat])# 删除最好的标签,防止树的下一个节点还使用此标签
featValues = [example[bestFeat]for examplein dataSet]# 创建最好的特征位的值所构建的list
uniqueVals = set(featValues)# 生成唯一的特征位的值构成的集合setfor valuein uniqueVals:
subLabels = labels[:]# 复制所有标签,且树不会和已经存在的标签搞混
myTree[bestFeatLabel][value] = createTree(splitDataSet(dataSet, bestFeat, value), subLabels)# 递归创建树return myTree
# 构建树测试print &amp;#34;构建树测试&amp;#34;
myData, labels = createDataSet()
myTree = createTree(myData, labels)
print myTree
&lt;/code&gt;&lt;/pre&gt;&lt;pre tabindex="0"&gt;&lt;code&gt;# coding:utf-8import matplotlib.pyplotas plt# 导入绘制图库&amp;#34;&amp;#34;&amp;#34;
绘制树图
&amp;#34;&amp;#34;&amp;#34;
decisionNode = dict(boxstyle=&amp;#34;sawtooth&amp;#34;, fc=&amp;#34;0.8&amp;#34;)
leafNode = dict(boxstyle=&amp;#34;round4&amp;#34;, fc=&amp;#34;0.8&amp;#34;)
arrow_args = dict(arrowstyle=&amp;#34;&amp;lt;-&amp;#34;)
defgetNumLeafs(myTree):
&amp;#34;&amp;#34;&amp;#34;
获取叶节点的数目
:param myTree:树结构
:return: 叶节点的数目
&amp;#34;&amp;#34;&amp;#34;
numLeafs = 0
firstStr = myTree.keys()[0]
secondDict = myTree[firstStr]
for keyin secondDict.keys():
if type(secondDict[
key]).__name__ == &amp;#39;dict&amp;#39;:# test to see if the nodes are dictonaires, if not they are leaf nodes
numLeafs += getNumLeafs(secondDict[key])
else:
numLeafs += 1
return numLeafs
defgetTreeDepth(myTree):
&amp;#34;&amp;#34;&amp;#34;
获取树的层数(深度)
:param myTree:
:return: 树的层数(深度)
&amp;#34;&amp;#34;&amp;#34;
maxDepth = 0
firstStr = myTree.keys()[0]
secondDict = myTree[firstStr]
for keyin secondDict.keys():
if type(secondDict[
key]).__name__ == &amp;#39;dict&amp;#39;:# 判断此节点是否是字典,如果不是就是叶节点
thisDepth = 1 + getTreeDepth(secondDict[key])# 是字典,层数+1else:
thisDepth = 1# 叶节点,层数为1if thisDepth &amp;gt; maxDepth:
maxDepth = thisDepth
return maxDepth
defplotNode(nodeTxt, centerPt, parentPt, nodeType):
&amp;#34;&amp;#34;&amp;#34;
绘制节点
:param nodeTxt:节点名称
:param centerPt: 目前的位置
:param parentPt: 父节点的位置
:param nodeType: 节点类型
:return:
&amp;#34;&amp;#34;&amp;#34;
createPlot.ax1.annotate(nodeTxt, xy=parentPt, xycoords=&amp;#39;axes fraction&amp;#39;,
xytext=centerPt, textcoords=&amp;#39;axes fraction&amp;#39;,
va=&amp;#34;center&amp;#34;, ha=&amp;#34;center&amp;#34;, bbox=nodeType, arrowprops=arrow_args)
defplotMidText(currentPt, parentPt, txtString):
&amp;#34;&amp;#34;&amp;#34;
绘制中间的文本
:param currentPt:目前的位置
:param parentPt: 父节点的位置
:param txtString: 想绘制的文本
:return:
&amp;#34;&amp;#34;&amp;#34;
xMid = (parentPt[0] - currentPt[0]) / 2.0 + currentPt[0]
yMid = (parentPt[1] - currentPt[1]) / 2.0 + currentPt[1]
createPlot.ax1.text(xMid, yMid, txtString, va=&amp;#34;center&amp;#34;, ha=&amp;#34;center&amp;#34;, rotation=30)
defplotTree(myTree, parentPt, nodeTxt):# if the first key tells you what feat was split on
numLeafs = getNumLeafs(myTree)# this determines the x width of this tree
depth = getTreeDepth(myTree)
firstStr = myTree.keys()[0]# the text label for this node should be this
cntrPt = (plotTree.xOff + (1.0 + float(numLeafs)) / 2.0 / plotTree.totalW, plotTree.yOff)
plotMidText(cntrPt, parentPt, nodeTxt)
plotNode(firstStr, cntrPt, parentPt, decisionNode)
secondDict = myTree[firstStr]
plotTree.yOff = plotTree.yOff - 1.0 / plotTree.totalD
for keyin secondDict.keys():
if type(secondDict[
key]).__name__ == &amp;#39;dict&amp;#39;:# test to see if the nodes are dictonaires, if not they are leaf nodes
plotTree(secondDict[key], cntrPt, str(key))# recursionelse:# it&amp;#39;s a leaf node print the leaf node
plotTree.xOff = plotTree.xOff + 1.0 / plotTree.totalW
plotNode(secondDict[key], (plotTree.xOff, plotTree.yOff), cntrPt, leafNode)
plotMidText((plotTree.xOff, plotTree.yOff), cntrPt, str(key))
plotTree.yOff = plotTree.yOff + 1.0 / plotTree.totalD
# if you do get a dictionary you know it&amp;#39;s a tree, and the first element will be another dictdefcreatePlot(inTree):
fig = plt.figure(1, facecolor=&amp;#39;white&amp;#39;)
fig.clf()
axprops = dict(xticks=[], yticks=[])
createPlot.ax1 = plt.subplot(111, frameon=False, **axprops)# no ticks# createPlot.ax1 = plt.subplot(111, frameon=False) #ticks for demo puropses
plotTree.totalW = float(getNumLeafs(inTree))
plotTree.totalD = float(getTreeDepth(inTree))
plotTree.xOff = -0.5 / plotTree.totalW
plotTree.yOff = 1.0
plotTree(inTree, (0.5, 1.0), &amp;#39;&amp;#39;)
plt.show()
# def createPlot():# fig = plt.figure(1, facecolor=&amp;#39;white&amp;#39;)# fig.clf()# createPlot.ax1 = plt.subplot(111, frameon=False) #ticks for demo puropses# plotNode(&amp;#39;a decision node&amp;#39;, (0.5, 0.1), (0.1, 0.5), decisionNode)# plotNode(&amp;#39;a leaf node&amp;#39;, (0.8, 0.1), (0.3, 0.8), leafNode)# plt.show()defretrieveTree(i):
listOfTrees = [{&amp;#39;no surfacing&amp;#39;: {0: &amp;#39;no&amp;#39;, 1: {&amp;#39;flippers&amp;#39;: {0: &amp;#39;no&amp;#39;, 1: &amp;#39;yes&amp;#39;}}}},
{&amp;#39;no surfacing&amp;#39;: {0: &amp;#39;no&amp;#39;, 1: {&amp;#39;flippers&amp;#39;: {0: {&amp;#39;head&amp;#39;: {0: &amp;#39;no&amp;#39;, 1: &amp;#39;yes&amp;#39;}}, 1: &amp;#39;no&amp;#39;}}}}
]
return listOfTrees[i]
# createPlot(thisTree)
myTree = retrieveTree(0)
createPlot(myTree)
&lt;/code&gt;&lt;/pre&gt;</description></item><item><title>Yii1.x的管理后台分页导致的性能问题</title><link>https://blog.jimersylee.com/posts/yii1.x%E7%9A%84%E7%AE%A1%E7%90%86%E5%90%8E%E5%8F%B0%E5%88%86%E9%A1%B5%E5%AF%BC%E8%87%B4%E7%9A%84%E6%80%A7%E8%83%BD%E9%97%AE%E9%A2%98/</link><pubDate>Fri, 10 Sep 2021 22:37:00 +0000</pubDate><guid>https://blog.jimersylee.com/posts/yii1.x%E7%9A%84%E7%AE%A1%E7%90%86%E5%90%8E%E5%8F%B0%E5%88%86%E9%A1%B5%E5%AF%BC%E8%87%B4%E7%9A%84%E6%80%A7%E8%83%BD%E9%97%AE%E9%A2%98/</guid><description>&lt;h1 id="yii-1x的管理后台分页导致的性能问题"&gt;Yii 1.x的管理后台分页导致的性能问题&lt;/h1&gt;
&lt;p&gt;上午客服反应管理后台在售管理和求购管理打开缓慢,我跟踪了下原因 我猜想原因如下:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;交易相关的,走了交易服务的接口,接口比较缓慢&lt;/li&gt;
&lt;li&gt;没加limit或者查询条件比较复杂没走索引&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;查看代码,发现是php代码直接查询数据库的,排除第一个原因,接下来往直接查数据的方向查,可能原因有&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;del&gt;交易数据负载比较高,查询响应慢&lt;/del&gt;&lt;/li&gt;
&lt;li&gt;&lt;del&gt;管理后台使用了外网地址连接数据库&lt;/del&gt;&lt;/li&gt;
&lt;li&gt;查看交易数据的近期慢SQL,是否有管理后台请求的慢SQL,发现端倪&lt;/li&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code&gt;![page1.png](2-Areas/blog/public-blog/hugo/content/posts/Yii%201%20x的管理后台分页导致的性能问题/page1.png)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;本地开启浏览器显示sql调试信息&lt;/p&gt;
&lt;p&gt;&lt;img alt="page2.png" loading="lazy" src="2-Areas/blog/public-blog/hugo/content/posts/Yii%201%20x%E7%9A%84%E7%AE%A1%E7%90%86%E5%90%8E%E5%8F%B0%E5%88%86%E9%A1%B5%E5%AF%BC%E8%87%B4%E7%9A%84%E6%80%A7%E8%83%BD%E9%97%AE%E9%A2%98/page2.png"&gt;&lt;/p&gt;
&lt;p&gt;发现会select count(*) from trade_product_sell,这个应该是为了分页,但是线上表数据已经5600万了,这个sql得执行9秒,能不慢吗 管理后台的分页插件都会执行这个count操作&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;public function getTotalItemCount($refresh=false)
  {
       if($this-&amp;gt;_totalItemCount===null || $refresh)
           $this-&amp;gt;_totalItemCount=$this-&amp;gt;calculateTotalItemCount();
       return $this-&amp;gt;_totalItemCount;
  }
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;找到问题后,怎么处理,现状如下&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;此处代码为yii1.x的分页逻辑,查询总条数,然后计算分页,此代码在管理后台使用的非常多&lt;/li&gt;
&lt;li&gt;此分页逻辑在针对小表查询的时候一点问题也没有,且使用比较方便&lt;/li&gt;
&lt;li&gt;原则是不能改框架,且一定要获取到总条数,前端页面才能正常显示分页&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;解决方案&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;既然总条数的获取不可避免,那就优化count(*)的性能&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;del&gt;根治的方法:针对大表进行归档处理,这个是交易系统的表,处理起来需要时间,可能要排到下季度了&lt;/del&gt;&lt;/li&gt;
&lt;li&gt;&lt;del&gt;治标的方法: 赋值一个假的总条数,这个的问题是体验不好,有的表只有几行,却显示一堆分页&lt;/del&gt;&lt;/li&gt;
&lt;li&gt;治标的方法: 将查询总数缓存起来,虽然第一次会慢,但是之后都挺快的&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;代码实现&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;不能修改框架代码,防止之后升级框架版本的时候覆盖了&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;可以选择修改基础的模型类,增加一个方法,进行总数缓存,且可以按需使用,针对大表及对总数精确度不敏感的场景&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;BasicAcitveRecord类中增加方法/** * 缓存一下分页组件使用的数据总条数 * 适用场景: * 对count不要求精确的,表比较大的,select count(*) 比较慢的那种,如果不缓存,每次都得查count(*)比较慢 * 不适用场景: * 对总数要求精确的 * 实现原理,使用表名+查询条件的md5作为key,缓存此条件下的查询总条数 * @param CActiveDataProvider $dataProvider :分页使用的dataProvider */ public function cacheTotalCount(CActiveDataProvider $dataProvider) { /** * @var $redis ARedisCache */ $redis = Yii::app()-&amp;gt;cache; $md5 = md5(json_encode($dataProvider-&amp;gt;getCountCriteria()) . $dataProvider-&amp;gt;model-&amp;gt;tableName()); $count = $redis-&amp;gt;get(RedisKeyService::getCachedTabelCountKey($md5)); if ($count != null) { $dataProvider-&amp;gt;setTotalItemCount($count); } else { $redis-&amp;gt;set(RedisKeyService::getCachedTabelCountKey($md5), $dataProvider-&amp;gt;getTotalItemCount(), 3600); } }&lt;/code&gt;&lt;/p&gt;</description></item><item><title>服务重新发布导致的mysql会话飙升以及网站访问延迟的问题排查处理</title><link>https://blog.jimersylee.com/posts/%E6%9C%8D%E5%8A%A1%E9%87%8D%E6%96%B0%E5%8F%91%E5%B8%83%E5%AF%BC%E8%87%B4%E7%9A%84mysql%E4%BC%9A%E8%AF%9D%E9%A3%99%E5%8D%87%E4%BB%A5%E5%8F%8A%E7%BD%91%E7%AB%99%E8%AE%BF%E9%97%AE%E5%BB%B6%E8%BF%9F%E7%9A%84%E9%97%AE%E9%A2%98%E6%8E%92%E6%9F%A5%E5%A4%84%E7%90%86/</link><pubDate>Sat, 24 Jul 2021 16:13:00 +0000</pubDate><guid>https://blog.jimersylee.com/posts/%E6%9C%8D%E5%8A%A1%E9%87%8D%E6%96%B0%E5%8F%91%E5%B8%83%E5%AF%BC%E8%87%B4%E7%9A%84mysql%E4%BC%9A%E8%AF%9D%E9%A3%99%E5%8D%87%E4%BB%A5%E5%8F%8A%E7%BD%91%E7%AB%99%E8%AE%BF%E9%97%AE%E5%BB%B6%E8%BF%9F%E7%9A%84%E9%97%AE%E9%A2%98%E6%8E%92%E6%9F%A5%E5%A4%84%E7%90%86/</guid><description>&lt;h2 id="故障表现"&gt;故障表现&lt;/h2&gt;
&lt;p&gt;在重新发布交易服务的时候,网站出现访问延迟增长的情况&lt;/p&gt;
&lt;h2 id="故障分析"&gt;故障分析&lt;/h2&gt;
&lt;h3 id="排查清单"&gt;&lt;strong&gt;排查清单&lt;/strong&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;input checked="" disabled="" type="checkbox"&gt; RDS数据库指标是否正常,CPU,内存正常,会话数激增&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://img.c5game.com/docimg/%E8%BF%9E%E6%8E%A5%E6%B1%A0%E8%B0%83%E6%95%B4%E4%B9%8B%E5%89%8Drds%E4%BC%9A%E8%AF%9D%E6%95%B0.png"&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;input checked="" disabled="" type="checkbox"&gt; ES搜索服务是否正常,正常&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;input checked="" disabled="" type="checkbox"&gt; REDIS服务是否正常,正常&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;确认基本方向,可能数据库连接配置存在问题&lt;/p&gt;
&lt;h3 id="排查druid依赖版本问题"&gt;&lt;strong&gt;排查druid依赖版本问题&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;查看pom依赖,发现版本太老了,1.0.16的版本发布于2015年10月&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;lt;dependency&amp;gt;
&amp;lt;groupId&amp;gt;com.alibaba&amp;lt;/groupId&amp;gt;
&amp;lt;artifactId&amp;gt;druid-spring-boot-starter&amp;lt;/artifactId&amp;gt;
&amp;lt;version&amp;gt;1.1.0&amp;lt;/version&amp;gt;
&amp;lt;/dependency&amp;gt;
&amp;lt;dependency&amp;gt;
&amp;lt;groupId&amp;gt;com.alibaba&amp;lt;/groupId&amp;gt;
&amp;lt;artifactId&amp;gt;druid&amp;lt;/artifactId&amp;gt;
&amp;lt;version&amp;gt;1.0.16&amp;lt;/version&amp;gt;
&amp;lt;/dependency&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;进行升级测试,保险起见,升级到1.1.x系列的最新版本,发布于2020.9月,还有最新的1.2.x版本可能存在较大更新,没有尝试&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt; &amp;lt;dependency&amp;gt;
&amp;lt;groupId&amp;gt;com.alibaba&amp;lt;/groupId&amp;gt;
&amp;lt;artifactId&amp;gt;druid-spring-boot-starter&amp;lt;/artifactId&amp;gt;
&amp;lt;version&amp;gt;1.1.24&amp;lt;/version&amp;gt;
&amp;lt;/dependency&amp;gt;
&amp;lt;dependency&amp;gt;
&amp;lt;groupId&amp;gt;com.alibaba&amp;lt;/groupId&amp;gt;
&amp;lt;artifactId&amp;gt;druid&amp;lt;/artifactId&amp;gt;
&amp;lt;version&amp;gt;1.1.24&amp;lt;/version&amp;gt;
&amp;lt;/dependency&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;本地测试正常,无兼容性修改&lt;/p&gt;
&lt;h3 id="排查druid配置问题"&gt;&lt;strong&gt;排查druid配置问题&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;生产环境配置如下&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;trade:
datasource:
#druid相关配置
druid:
#监控统计拦截的filters
filters: stat
driverClassName: com.mysql.jdbc.Driver
#配置基本属性
url: ****
username: ***
password: ****
#配置初始化大小/最小/最大
initialSize: 50
minIdle: 10
maxActive: 300
#获取连接等待超时时间
maxWait: 60000
#间隔多久进行一次检测，检测需要关闭的空闲连接
timeBetweenEvictionRunsMillis: 60000
#一个连接在池中最小生存的时间
minEvictableIdleTimeMillis: 300000
validationQuery: SELECT &amp;#39;x&amp;#39;
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
#打开PSCache，并指定每个连接上PSCache的大小。oracle设为true，mysql设为false。分库分表较多推荐设置为false
poolPreparedStatements: false
maxPoolPreparedStatementPerConnectionSize: 20
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="查询druid配置最佳实践相关资料"&gt;&lt;strong&gt;查询druid配置最佳实践相关资料&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://www.infoq.cn/article/njxtjbzpnlnfp6d56adr"&gt;有赞DB连接池性能优化-InfoQ&lt;/a&gt;&lt;/p&gt;</description></item><item><title>使用nvm管理node环境</title><link>https://blog.jimersylee.com/posts/%E4%BD%BF%E7%94%A8nvm%E7%AE%A1%E7%90%86node%E7%8E%AF%E5%A2%83/</link><pubDate>Wed, 23 Jun 2021 18:00:00 +0000</pubDate><guid>https://blog.jimersylee.com/posts/%E4%BD%BF%E7%94%A8nvm%E7%AE%A1%E7%90%86node%E7%8E%AF%E5%A2%83/</guid><description>&lt;p&gt;archlinux,manjaro 使用nvm安装管理node&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 安装nvm&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo pacman -S nvm
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#配置nvm&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;echo &lt;span style="color:#e6db74"&gt;&amp;#34;source /usr/share/nvm/init-nvm.sh&amp;#34;&lt;/span&gt;&amp;gt;&amp;gt;~/.profile
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#立即生效&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;source /usr/share/nvm/init-nvm.sh
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 安装稳定版&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;nvm install stable
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 或者安装指定版本&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;nvm install 10.15.0
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 指定使用某个版本&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;nvm use 10.15.0
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 检查版本是否正确&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;node -v
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://github.com/creationix/nvm"&gt;https://github.com/creationix/nvm&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;</description></item><item><title>分布式ID重复问题</title><link>https://blog.jimersylee.com/posts/%E5%88%86%E5%B8%83%E5%BC%8Fid%E9%87%8D%E5%A4%8D%E9%97%AE%E9%A2%98/</link><pubDate>Fri, 16 Apr 2021 22:59:00 +0000</pubDate><guid>https://blog.jimersylee.com/posts/%E5%88%86%E5%B8%83%E5%BC%8Fid%E9%87%8D%E5%A4%8D%E9%97%AE%E9%A2%98/</guid><description>&lt;h2 id="背景"&gt;背景&lt;/h2&gt;
&lt;p&gt;线上存在数据表主键重复的错误&lt;/p&gt;
&lt;p&gt;通过&lt;a href="https://sls.console.aliyun.com/lognext/project/trade-api/logsearch/steam-trade-boot"&gt;阿里云日志&lt;/a&gt;搜索以下关键词可以查询到&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;Duplicate&amp;rdquo; and &amp;ldquo;primary&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;日志例子&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;log:2021-04-22 13:19:31,896 ERROR [http-nio2-8088-exec-100] [ac140db2-knscphtx-437669] [steam-trade-boot] c.x.s.t.s.b.i.TradeOrderLogServiceImpl - 插入日志冲突
org.springframework.dao.DuplicateKeyException:
### Error updating database. Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry &amp;#39;859225024379092992&amp;#39; for key &amp;#39;PRIMARY&amp;#39;
### The error may exist in com/xingchao/steam/trade/dal/mapper/TradeOrderLogMapper.java (best guess)
### The error may involve com.xingchao.steam.trade.dal.mapper.TradeOrderLogMapper.insertSelective-Inline
### The error occurred while setting parameters
### SQL: INSERT INTO trade_order_log ( id,order_asset_id,type,before_status,after_status,event,content,create_time,update_time ) VALUES( ?,?,?,?,?,?,?,?,? )
### Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry &amp;#39;859225024379092992&amp;#39; for key &amp;#39;PRIMARY&amp;#39;
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="代码例子"&gt;代码例子&lt;/h2&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;//项目中所有主键使用的SnowFlakeUtil这个组件生成id
logDO.setId(SnowFlakeUtil.getId());
tradeOrderLogMapper.insertSelective(logDO);
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="表现"&gt;表现&lt;/h2&gt;
&lt;p&gt;针对这种频繁插入的情况,容易出现id重复的问题,与当初预想的不一样&lt;/p&gt;</description></item><item><title>跨数据库实例以及复杂聚合查询数据分析方案调研</title><link>https://blog.jimersylee.com/posts/%E8%B7%A8%E6%95%B0%E6%8D%AE%E5%BA%93%E5%AE%9E%E4%BE%8B%E4%BB%A5%E5%8F%8A%E5%A4%8D%E6%9D%82%E8%81%9A%E5%90%88%E6%9F%A5%E8%AF%A2%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90%E6%96%B9%E6%A1%88%E8%B0%83%E7%A0%94/</link><pubDate>Tue, 16 Mar 2021 20:59:00 +0000</pubDate><guid>https://blog.jimersylee.com/posts/%E8%B7%A8%E6%95%B0%E6%8D%AE%E5%BA%93%E5%AE%9E%E4%BE%8B%E4%BB%A5%E5%8F%8A%E5%A4%8D%E6%9D%82%E8%81%9A%E5%90%88%E6%9F%A5%E8%AF%A2%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90%E6%96%B9%E6%A1%88%E8%B0%83%E7%A0%94/</guid><description>&lt;h2 id="背景"&gt;背景&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;目前BI需求繁多,且都是些复杂联表查询,很容易产生数据库性能问题,影响线上用户, 目前架构如下,虽然能够满足现在的需求,但面对未来更大的数据量,更加复杂的统计需求,将只能通过添加只读实例和升级配置解决&lt;/li&gt;
&lt;li&gt;用户基础信息与交易信息不在同一个实例,数据分析需要联合表查询得到数据,目前先查用户id再去用户信息表取存在诸多不便,需要寻求更方便的形式&lt;/li&gt;
&lt;li&gt;针对用户行为漏斗分析等场景,MySQL的支持很差,基本查不动,需要更合适的数据库&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="需求"&gt;需求&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;支持更复杂的聚合查询,更快的查询速度&lt;/li&gt;
&lt;li&gt;不影响用户体验&lt;/li&gt;
&lt;li&gt;更少的成本&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="方案"&gt;方案&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;方案A:metabase,使用matebase构建目前的bi.xxx.com,数据源自RDS,当进行复杂查询的时候存在性能问题,会影响生产环境&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;初代版本&lt;/p&gt;
&lt;p&gt;&lt;img alt="mysql-architect.svg" loading="lazy" src="2-Areas/blog/public-blog/hugo/content/posts/%E8%B7%A8%E6%95%B0%E6%8D%AE%E5%BA%93%E5%AE%9E%E4%BE%8B%E4%BB%A5%E5%8F%8A%E5%A4%8D%E6%9D%82%E8%81%9A%E5%90%88%E6%9F%A5%E8%AF%A2%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90%E6%96%B9%E6%A1%88%E8%B0%83%E7%A0%94/mysql-architect.svg"&gt;&lt;/p&gt;
&lt;p&gt;演进版本&lt;/p&gt;
&lt;p&gt;&lt;img alt="mysql-architect.png" loading="lazy" src="2-Areas/blog/public-blog/hugo/content/posts/%E8%B7%A8%E6%95%B0%E6%8D%AE%E5%BA%93%E5%AE%9E%E4%BE%8B%E4%BB%A5%E5%8F%8A%E5%A4%8D%E6%9D%82%E8%81%9A%E5%90%88%E6%9F%A5%E8%AF%A2%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90%E6%96%B9%E6%A1%88%E8%B0%83%E7%A0%94/mysql-architect.png"&gt;&lt;/p&gt;
&lt;h2 id="备选方案"&gt;备选方案&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;B:使用阿里云DLA服务&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;阿里云DLA ,介绍 &lt;a href="https://help.aliyun.com/document_detail/70378.html"&gt;https://help.aliyun.com/document_detail/70378.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;跨库查询支持 &lt;a href="https://help.aliyun.com/document_detail/107698.html"&gt;https://help.aliyun.com/document_detail/107698.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;知乎专栏:&lt;a href="https://www.zhihu.com/column/data-lake-analytics"&gt;https://www.zhihu.com/column/data-lake-analytics&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;测试过程&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;1：尝试云原生数据湖的联合查询多个MySql实例，通过&lt;a href="https://help.aliyun.com/document_detail/107698.html?spm=a2c4g.11186623.6.837.4d7974f4GsP1S0"&gt;https://help.aliyun.com/document_detail/107698.html?spm=a2c4g.11186623.6.837.4d7974f4GsP1S0&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;可以实现不同数据库的多表联合查询，但是咨询工单反馈，查询过程仍再原数据库中执行，在小数量的数据库查询中影响不大，但是在查询量较大较频繁时，无法&lt;/p&gt;
&lt;p&gt;保证原数据库的性能。于是尝试其他方法。&lt;/p&gt;
&lt;p&gt;2：尝试创建云原生数据湖分析中的T+1多库合并建仓，将数据库导入到DLA数据湖中，通过自己新创建的数据量很小的数据库导入，可以实现，并且不会占用大量性能。&lt;/p&gt;
&lt;p&gt;但针对test库的多库合并建仓时，因为性能原因造成较大的影响。并且询问阿里云工单之后反馈，多库合并建仓再第一次入湖之后，再每一次的更新数据时是全量重新同步，意味着&lt;/p&gt;
&lt;p&gt;每天进行同步都会遭遇很大的性能影响，并且数据存在一天延迟于是尝试其他方法。&lt;/p&gt;
&lt;p&gt;优点&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;如果使用数据库联合查询方案,可以直接跨库查询&lt;/li&gt;
&lt;li&gt;支持OSS直接上传离线数据文件进行分析&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;缺点&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;虽然可以实现跨库查询,但是占用的还是生产库的计算资源,当需要复杂查询的时候可能影响用户体验&lt;/li&gt;
&lt;li&gt;T+1方案存在数据延迟,且每天都是全量同步,在同步时对生产库有性能影响&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;C:使用clickhouse订阅多个mysql,实现数据聚合&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="page1.png" loading="lazy" src="2-Areas/blog/public-blog/hugo/content/posts/%E8%B7%A8%E6%95%B0%E6%8D%AE%E5%BA%93%E5%AE%9E%E4%BE%8B%E4%BB%A5%E5%8F%8A%E5%A4%8D%E6%9D%82%E8%81%9A%E5%90%88%E6%9F%A5%E8%AF%A2%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90%E6%96%B9%E6%A1%88%E8%B0%83%E7%A0%94/page1.png"&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;方案优势&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;clickhouse在推出了支持MySQL实时复制后,可以很方便的订阅binlog实现clickhouse的数据库更新同步,实现准实时的数据分析&lt;/li&gt;
&lt;li&gt;clickhouse数据库和用户使用的mysql数据库是完全隔离的,不会互相影响&lt;/li&gt;
&lt;li&gt;无论是直接购买还是自建,相对其他大数据方案,成本较低&lt;/li&gt;
&lt;li&gt;其他公司应用较多,携程,有赞等公司有在线上环境使用,参考资料较多&lt;/li&gt;
&lt;li&gt;针对用户行为漏斗,留存等场景,有专有函数支持计算&lt;/li&gt;
&lt;li&gt;metabase支持clickhouse数据库,原来的使用习惯不用改变,还是可以通过bi.xxx.com看数据&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;测试过程&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;ClickHouse，通过购买建立ClickHouse集群，通过购买DTS数据同步，将RDS数据库中的数据导入到ClickHouse集群中，可以实现不同数据的不同表导入到同一个数据库中，实现快速查询。&lt;/p&gt;
&lt;p&gt;ClickHouse ，并且可以实时更新数据。 现ClickHouse配置为4核8G配置 1000G 属于按量付费，约1.5RMB/小时，30RMB/天，如需长期使用建议转为按月付费约600RMB/月， DTS数据同步&lt;/p&gt;
&lt;p&gt;现购买两个每个约0.5RMB/小时，两个共计20RMB/天，如需长期使用建议按月付费每个400RMB/月&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;初始成本1400/月,后续可以视业务规模扩容升配置&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;线上业务性能对比&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;实例配置对比  mysql5.7 16核64G内存      clickhouse 20.3  4核8G&lt;/p&gt;
&lt;p&gt;查询速度对比:&lt;/p&gt;
&lt;p&gt;&lt;a href="%E8%B7%A8%E6%95%B0%E6%8D%AE%E5%BA%93%E5%AE%9E%E4%BE%8B%E4%BB%A5%E5%8F%8A%E5%A4%8D%E6%9D%82%E8%81%9A%E5%90%88%E6%9F%A5%E8%AF%A2%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90%E6%96%B9%E6%A1%88%E8%B0%83%E7%A0%94/Untitled%20ddf9682b130c44e39aa76f60bf371cd8.csv"&gt;Untitled&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="调研过程"&gt;调研过程&lt;/h2&gt;
&lt;p&gt;1：尝试云原生数据湖的联合查询多个MySql实例，通过&lt;a href="https://help.aliyun.com/document_detail/107698.html?spm=a2c4g.11186623.6.837.4d7974f4GsP1S0"&gt;https://help.aliyun.com/document_detail/107698.html?spm=a2c4g.11186623.6.837.4d7974f4GsP1S0&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;可以实现不同数据库的多表联合查询，但是咨询工单反馈，查询过程仍再原数据库中执行，在小数量的数据库查询中影响不大，但是在查询量较大较频繁时，无法&lt;/p&gt;
&lt;p&gt;保证原数据库的性能。于是尝试其他方法。&lt;/p&gt;
&lt;p&gt;2：尝试创建云原生数据湖分析中的T+1多库合并建仓，将数据库导入到DLA数据湖中，通过自己新创建的数据量很小的数据库导入，可以实现，并且不会占用大量性能。&lt;/p&gt;
&lt;p&gt;但针对test库的多库合并建仓时，因为性能原因造成较大的影响。并且询问阿里云工单之后反馈，多库合并建仓再第一次入湖之后，再每一次的更新数据时是全量重新同步，意味着&lt;/p&gt;
&lt;p&gt;每天进行同步都会遭遇很大的性能影响，并且数据存在一天延迟于是尝试其他方法。&lt;/p&gt;
&lt;p&gt;3：ClickHouse，通过购买建立ClickHouse集群，通过购买DTS数据同步，将RDS数据库中的数据导入到ClickHouse集群中，可以实现不同数据的不同表导入到同一个数据库中，实现&lt;/p&gt;</description></item><item><title>真不是我甩锅,细数我遇到过的阿里云的故障</title><link>https://blog.jimersylee.com/posts/%E7%9C%9F%E4%B8%8D%E6%98%AF%E6%88%91%E7%94%A9%E9%94%85%E7%BB%86%E6%95%B0%E6%88%91%E9%81%87%E5%88%B0%E8%BF%87%E7%9A%84%E9%98%BF%E9%87%8C%E4%BA%91%E7%9A%84%E6%95%85%E9%9A%9C/</link><pubDate>Wed, 10 Feb 2021 08:07:00 +0000</pubDate><guid>https://blog.jimersylee.com/posts/%E7%9C%9F%E4%B8%8D%E6%98%AF%E6%88%91%E7%94%A9%E9%94%85%E7%BB%86%E6%95%B0%E6%88%91%E9%81%87%E5%88%B0%E8%BF%87%E7%9A%84%E9%98%BF%E9%87%8C%E4%BA%91%E7%9A%84%E6%95%85%E9%9A%9C/</guid><description>&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://workorder.console.aliyun.com/#/ticket/detail/?ticketId=9LCGD1D"&gt;网站时不时卡顿几分钟,自动恢复,搜索服务响应缓慢&lt;/a&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;影响范围:web,app都出现502&lt;/li&gt;
&lt;li&gt;原因: 阿里云低版本ES存在稳定性问题&lt;/li&gt;
&lt;li&gt;解决方案:升级ES内核,阿里云并不会自动升级&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://workorder.console.aliyun.com/#/ticket/detail/?ticketId=CACMXPA"&gt;香港的serverless 容器 访问国内的网络有connect time out的问题，每天的晚上8点开始会突然多起来&lt;/a&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;影响范围:香港报价服务和国内交易服务的通讯&lt;/li&gt;
&lt;li&gt;原因:运营商反馈：是运营商海缆故障，请您知悉。&lt;/li&gt;
&lt;li&gt;解决方案:等待恢复&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://workorder.console.aliyun.com/#/ticket/detail/?ticketId=DGCHHT9"&gt;服务内调用服务出现超时&lt;/a&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;影响范围:一些服务异常,包括库存,短信等&lt;/li&gt;
&lt;li&gt;原因:阿里云k8s集群自己改变了策略,导致我们之前的正常的流量策略不可用&lt;/li&gt;
&lt;li&gt;解决方案:设置成新的策略&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://workorder.console.aliyun.com/#/ticket/detail/?ticketId=ACCF4A2"&gt;证书出现问题,无法访问&lt;/a&gt;   &lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;影响范围:人工发货功能不可用,用户无法使用我们的代理地址&lt;/li&gt;
&lt;li&gt;原因:阿里云升级了k8s的配置,没有通知我们&lt;/li&gt;
&lt;li&gt;解决方案:按新的方式配置证书&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://workorder.console.aliyun.com/#/ticket/detail/?ticketId=G2CD82G"&gt;阿里云的RDS数据库读写分离地址突然失效&lt;/a&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;影响范围:半夜的时候造成网站完全无法访问&lt;/li&gt;
&lt;li&gt;原因:阿里云故障&lt;/li&gt;
&lt;li&gt;解决方案:我们当时立马申请了新的地址,才恢复访问&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://workorder.console.aliyun.com/#/ticket/detail/?ticketId=BSBUTSW"&gt;香港的serverless集群突然全部实例异常,流量无法进入&lt;/a&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;影响范围:部署在香港的服务全部无法问题&lt;/li&gt;
&lt;li&gt;原因:阿里云故障&lt;/li&gt;
&lt;li&gt;解决方案:等待阿里云修复之后才恢复正常,已经要求阿里云赔偿&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://workorder.console.aliyun.com/#/ticket/detail/?ticketId=3EC8CU7"&gt;香港的serverless集群绑定的弹性公网IP自动消失&lt;/a&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;影响范围:报价服务异常&lt;/li&gt;
&lt;li&gt;原因:阿里云故障&lt;/li&gt;
&lt;li&gt;解决方案:等阿里云修复&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="../../20210223-RocketMQ%E6%B6%88%E8%B4%B9%E8%80%85%E5%85%A8%E9%83%A8%E7%A6%BB%E7%BA%BF%E6%95%85%E9%9A%9C%2520x.md#"&gt;&lt;strong&gt;RocketMQ消费者全部离线故障&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;影响范围: 公司全部报价无法处理&lt;/li&gt;
&lt;li&gt;原因: 阿里云旧的SDK存在断线重连重试BUG&lt;/li&gt;
&lt;li&gt;解决方案: 升级新的SDK&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;</description></item><item><title>nginx https 配置</title><link>https://blog.jimersylee.com/posts/nginx-https-%E9%85%8D%E7%BD%AE/</link><pubDate>Wed, 03 Feb 2021 18:04:00 +0000</pubDate><guid>https://blog.jimersylee.com/posts/nginx-https-%E9%85%8D%E7%BD%AE/</guid><description>&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-nix" data-lang="nix"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;server {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; listen &lt;span style="color:#ae81ff"&gt;80&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; listen &lt;span style="color:#ae81ff"&gt;443&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ssl on;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ssl_certificate &lt;span style="color:#e6db74"&gt;conf.d/jimersylee.com.crt&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ssl_certificate_key &lt;span style="color:#e6db74"&gt;conf.d/jimersylee.com.key.pem&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ssl_session_timeout &lt;span style="color:#960050;background-color:#1e0010"&gt;5&lt;/span&gt;m;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ssl_protocols SSLv2 SSLv3 TLSv1;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ssl_ciphers &lt;span style="color:#e6db74"&gt;ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ssl_prefer_server_ciphers on;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; root &lt;span style="color:#e6db74"&gt;/etc/nginx/conf.d&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# Add index.php to the list if you are using PHP&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; index index&lt;span style="color:#f92672"&gt;.&lt;/span&gt;html index&lt;span style="color:#f92672"&gt;.&lt;/span&gt;htm index&lt;span style="color:#f92672"&gt;.&lt;/span&gt;nginx-debian&lt;span style="color:#f92672"&gt;.&lt;/span&gt;html;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; server_name &lt;span style="color:#f92672"&gt;*.&lt;/span&gt;jimersylee&lt;span style="color:#f92672"&gt;.&lt;/span&gt;com;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; location&lt;span style="color:#f92672"&gt; / &lt;/span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# First attempt to serve request as file, then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# as directory, then fall back to displaying a 404.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; try_files &lt;span style="color:#960050;background-color:#1e0010"&gt;$&lt;/span&gt;uri &lt;span style="color:#960050;background-color:#1e0010"&gt;$&lt;/span&gt;uri&lt;span style="color:#960050;background-color:#1e0010"&gt;/&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;404&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;另外推荐，一个工具 &lt;a href="https://www.digitalocean.com/community/tools/nginx"&gt;https://www.digitalocean.com/community/tools/nginx&lt;/a&gt; 可视化配置nginx，方便新手了解nginx&lt;/p&gt;</description></item><item><title>Yii2项目整合阿里云日志服务</title><link>https://blog.jimersylee.com/posts/yii2%E9%A1%B9%E7%9B%AE%E6%95%B4%E5%90%88%E9%98%BF%E9%87%8C%E4%BA%91%E6%97%A5%E5%BF%97%E6%9C%8D%E5%8A%A1/</link><pubDate>Tue, 29 Sep 2020 23:05:00 +0000</pubDate><guid>https://blog.jimersylee.com/posts/yii2%E9%A1%B9%E7%9B%AE%E6%95%B4%E5%90%88%E9%98%BF%E9%87%8C%E4%BA%91%E6%97%A5%E5%BF%97%E6%9C%8D%E5%8A%A1/</guid><description>&lt;h1 id="原因"&gt;原因&lt;/h1&gt;
&lt;p&gt;公司的php项目之前的日志基本是存数据库,存服务器文件,存在占用数据库大量空间,日志查看存在难以看到完整上下文,服务器上查找日志困难等问题,急需解决方案&lt;/p&gt;
&lt;h1 id="方案"&gt;方案&lt;/h1&gt;
&lt;p&gt;1.购买阿里云ELK:缺点贵&lt;/p&gt;
&lt;p&gt;2.购买阿里云服务器自己搭ELK:虽然便宜些,但是增加运维成本&lt;/p&gt;
&lt;p&gt;3.使用&lt;a href="https://help.aliyun.com/learn/learningpath/log.html?spm=5176.2020520112.104.7.122834c07Lpxpa"&gt;阿里云的日志服务&lt;/a&gt;,&lt;a href="https://github.com/aliyun/aliyun-log-logback-appender"&gt;官方示例项目&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;优点:1.便宜 2:方便接入 3:机器人日志已有使用经验 4:在app即将上线的时候能够快速接入&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="示例项目"&gt;示例项目&lt;/h1&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;依赖引入&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;进入项目根目录,执行&lt;/p&gt;
&lt;p&gt;composer require &amp;ndash;prefer-dist ranvk/yii2-aliyun-logtarget -vvv&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;composer.json文件中会增加&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;#34;ranvk/yii2-aliyun-logtarget&amp;#34;: &amp;#34;^18.3&amp;#34;
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;修改配置,dev和local环境配置阿里云的外网地址,才可以上传日志,在线上的test和prod环境,使用内网地址,加快日志上传速度&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;api/config/dev/main.php&lt;/li&gt;
&lt;li&gt;修改log的组件&lt;/li&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code&gt;```php
'components' =&amp;gt; [
'log' =&amp;gt; [
'targets' =&amp;gt; [
[
'class' =&amp;gt; 'yii\log\FileTarget',
'levels' =&amp;gt; ['error', 'warning', 'trace', 'info'],
],
[
'levels' =&amp;gt; ['error', 'warning', 'info'],
'class' =&amp;gt; 'Ranvk\Yii2AliyunLogtarget\AliyunLogTarget',
'logstore' =&amp;gt; 'www-xxx-com',
'topic' =&amp;gt; YII_ENV,
'project' =&amp;gt; 'c5game-webserver',
'accessKeyId' =&amp;gt; 'xxx',
'accessKeySecret' =&amp;gt; 'xxx',
'endpoint' =&amp;gt; 'cn-shanghai.log.aliyuncs.com', //外网地址,内网地址为cn-shanghai-intranet.log.aliyuncs.com
],
],
],
```
1. 其他环境的配置文件类似,别忘了修改
2. 具体代码 [http://xxxx/-/merge_requests/49/diffs](http://git.c5game.com/zbt/www.zbt.com/-/merge_requests/49/diffs)
&lt;/code&gt;&lt;/pre&gt;
&lt;h1 id="查询示例"&gt;查询示例&lt;/h1&gt;
&lt;p&gt;网址:https://sls.console.aliyun.com/lognext/project/xxx&lt;/p&gt;</description></item><item><title>关于k8s集群中的容器资源限制以及JAVA应用运行参数设置</title><link>https://blog.jimersylee.com/posts/%E5%85%B3%E4%BA%8Ek8s%E9%9B%86%E7%BE%A4%E4%B8%AD%E7%9A%84%E5%AE%B9%E5%99%A8%E8%B5%84%E6%BA%90%E9%99%90%E5%88%B6%E4%BB%A5%E5%8F%8Ajava%E5%BA%94%E7%94%A8%E8%BF%90%E8%A1%8C%E5%8F%82%E6%95%B0%E8%AE%BE%E7%BD%AE/</link><pubDate>Fri, 28 Aug 2020 22:00:00 +0000</pubDate><guid>https://blog.jimersylee.com/posts/%E5%85%B3%E4%BA%8Ek8s%E9%9B%86%E7%BE%A4%E4%B8%AD%E7%9A%84%E5%AE%B9%E5%99%A8%E8%B5%84%E6%BA%90%E9%99%90%E5%88%B6%E4%BB%A5%E5%8F%8Ajava%E5%BA%94%E7%94%A8%E8%BF%90%E8%A1%8C%E5%8F%82%E6%95%B0%E8%AE%BE%E7%BD%AE/</guid><description>&lt;h1 id="背景"&gt;背景&lt;/h1&gt;
&lt;p&gt;目前存在一些应用频繁重启的问题,查看日志,有的显示容器被驱逐(evic),这种情况一般为资源使用超过配置的限制,k8s为了整体稳定性进行服务的重启,防止一些应用层的内存泄漏问题导致整体服务稳定性下降&lt;/p&gt;
&lt;p&gt;针对此问题,需要调研k8s集群中,容器的内存分配,以及应用是否能正确识别到分配的容器内存限制&lt;/p&gt;
&lt;h1 id="现状"&gt;现状&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;目前线上的java应用使用的基础镜像为:library/openjdk8-skywalking:latest&lt;/li&gt;
&lt;li&gt;此镜像的项目地址为 :middleware/docker-image-openjdk8-skywalking&lt;/li&gt;
&lt;li&gt;此基础镜像包含的软件为:
&lt;ul&gt;
&lt;li&gt;openjdk-8u212&lt;/li&gt;
&lt;li&gt;nginx&lt;/li&gt;
&lt;li&gt;curl&lt;/li&gt;
&lt;li&gt;vim&lt;/li&gt;
&lt;li&gt;php7&lt;/li&gt;
&lt;li&gt;php7-pecl-mongodb&lt;/li&gt;
&lt;li&gt;skywalking&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;线上使用配置
&lt;ul&gt;
&lt;li&gt;通过设置环境变量,运行脚本使用环境变量配置jvm参数实现&lt;/li&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt; ![](https://i.loli.net/2021/04/29/nQJ4sRZp791HAhi.png)
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id="本地测试结果"&gt;本地测试结果&lt;/h2&gt;
&lt;h2 id="自动方案"&gt;自动方案&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;不带jvm参数运行,看默认配置为多少内存,给容器设置最大内存限制为2GB,jvm设置的最大堆内存为455.50M,约为1/4最大内存,符合预期&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;docker run -m 2GB &amp;ndash;rm &lt;a href="http://reg.xxxx.cn/library/openjdk8-skywalking:latest"&gt;reg.xxxx.cn/library/openjdk8-skywalking:latest&lt;/a&gt; java -XshowSettings:vm -version VM settings: Max. Heap Size (Estimated): 455.50M Ergonomics Machine Class: server Using VM: OpenJDK 64-Bit Server VM&lt;/p&gt;
&lt;p&gt;openjdk version &amp;ldquo;1.8.0_212&amp;rdquo; OpenJDK Runtime Environment (IcedTea 3.12.0) (Alpine 8.212.04-r0) OpenJDK 64-Bit Server VM (build 25.212-b04, mixed mode)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;OpenJdk&lt;/p&gt;
&lt;p&gt;自动识别到容器限制后，OpenJdk把最大堆设置为了大概容器内存的1/4，对内存的浪费不可谓不大。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;我们尝试将MaxRAMFraction设置手动设置为1,可以看到最大堆内存将被设置为1.78G,我觉得这样的资源利用率比较高&lt;/p&gt;</description></item><item><title>杭州永辉菜价</title><link>https://blog.jimersylee.com/posts/%E6%9D%AD%E5%B7%9E%E6%B0%B8%E8%BE%89%E8%8F%9C%E4%BB%B7/</link><pubDate>Sat, 22 Aug 2020 00:00:00 +0800</pubDate><guid>https://blog.jimersylee.com/posts/%E6%9D%AD%E5%B7%9E%E6%B0%B8%E8%BE%89%E8%8F%9C%E4%BB%B7/</guid><description>&lt;ul&gt;
&lt;li&gt;&lt;input checked="" disabled="" type="checkbox"&gt; 西蓝花一小颗 1.5/斤 1元&lt;/li&gt;
&lt;li&gt;&lt;input checked="" disabled="" type="checkbox"&gt; 南瓜一小片 0.8/斤 4元&lt;/li&gt;
&lt;li&gt;&lt;input checked="" disabled="" type="checkbox"&gt; 芹菜少点 6/斤 6.9&lt;/li&gt;
&lt;li&gt;&lt;input checked="" disabled="" type="checkbox"&gt; 姜两块 5.5/斤 5.7&lt;/li&gt;
&lt;li&gt;&lt;input checked="" disabled="" type="checkbox"&gt; 黄瓜 1.5/斤 元&lt;/li&gt;
&lt;li&gt;&lt;input checked="" disabled="" type="checkbox"&gt; 茄子 2/斤 3.5&lt;/li&gt;
&lt;li&gt;&lt;input checked="" disabled="" type="checkbox"&gt; 菠菜 4元/斤&lt;/li&gt;
&lt;li&gt;&lt;input checked="" disabled="" type="checkbox"&gt; 香菜 8.5斤&lt;/li&gt;
&lt;li&gt;&lt;input checked="" disabled="" type="checkbox"&gt; 小油菜 3/斤3元&lt;/li&gt;
&lt;li&gt;&lt;input checked="" disabled="" type="checkbox"&gt; 生菜 3/斤 3 元&lt;/li&gt;
&lt;li&gt;&lt;input checked="" disabled="" type="checkbox"&gt; 香菇 7.5/斤+10/斤*0.5=12&lt;/li&gt;
&lt;li&gt;&lt;input checked="" disabled="" type="checkbox"&gt; 西红柿 2.5/斤 4.9元&lt;/li&gt;
&lt;li&gt;&lt;input checked="" disabled="" type="checkbox"&gt; 大葱 2块/斤 5元&lt;/li&gt;
&lt;li&gt;&lt;input checked="" disabled="" type="checkbox"&gt; 黄豆芽两块钱的 2元&lt;/li&gt;
&lt;li&gt;&lt;input checked="" disabled="" type="checkbox"&gt; 鸡胸肉四块 7/斤 10元&lt;/li&gt;
&lt;li&gt;&lt;input checked="" disabled="" type="checkbox"&gt; 干豆腐 4元&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>spring-boot不同的启动的方式</title><link>https://blog.jimersylee.com/posts/spring-boot%E4%B8%8D%E5%90%8C%E7%9A%84%E5%90%AF%E5%8A%A8%E7%9A%84%E6%96%B9%E5%BC%8F/</link><pubDate>Wed, 18 Mar 2020 18:06:00 +0000</pubDate><guid>https://blog.jimersylee.com/posts/spring-boot%E4%B8%8D%E5%90%8C%E7%9A%84%E5%90%AF%E5%8A%A8%E7%9A%84%E6%96%B9%E5%BC%8F/</guid><description>&lt;h1 id="以mvn运行"&gt;以mvn运行&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#使用prod配置运行&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;mvn spring-boot:run -Dspring-boot.run.profiles&lt;span style="color:#f92672"&gt;=&lt;/span&gt;prod
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#后台运行无额外日志文件&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;nohup mvn spring-boot:run -Dspring-boot.run.profiles&lt;span style="color:#f92672"&gt;=&lt;/span&gt;prod &amp;gt;/dev/null 2&amp;gt;&amp;amp;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &amp;amp;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id="以包运行"&gt;以包运行&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#默认配置&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;java -jar xxxx.jar
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#指定配置文件或者参数&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;java -Xms128m -Xmx256m -jar xxxx.jar --spring.profiles.active&lt;span style="color:#f92672"&gt;=&lt;/span&gt;prod
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#后台运行无额外日志文件&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;nohup java -Xms128m -Xmx256m -jar xxxx.jar --spring.profiles.active&lt;span style="color:#f92672"&gt;=&lt;/span&gt;prod &amp;gt;/dev/null 2&amp;gt;&amp;amp;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &amp;amp;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>美团2019年货分享</title><link>https://blog.jimersylee.com/posts/%E7%BE%8E%E5%9B%A22019%E5%B9%B4%E8%B4%A7%E5%88%86%E4%BA%AB/</link><pubDate>Tue, 05 Mar 2019 17:58:00 +0000</pubDate><guid>https://blog.jimersylee.com/posts/%E7%BE%8E%E5%9B%A22019%E5%B9%B4%E8%B4%A7%E5%88%86%E4%BA%AB/</guid><description>&lt;h1 id="美团年货分享"&gt;📝美团年货分享&lt;/h1&gt;
&lt;p&gt;感谢关注美团技术团队。我们每周会推送来自一线的实践技术文章，涵盖前端（Web、iOS和Android）、后台、大数据、AI/算法、测试、运维等技术领域。在2019年春节到来之际，我们精选了114篇技术干货，制作成一本厚达1200多页的电子书呈送给大家。温馨提醒：文件有点大（全部下载约350M），请耐心等候下载。建议通过WIFI下载，或将地址复制到PC端，使用浏览器下载。【前端系列】下载链接：&lt;a href="http://dpurl.cn/DWVhPpS%E3%80%90%E5%90%8E%E5%8F%B0%E7%B3%BB%E5%88%97%E3%80%91%E4%B8%8B%E8%BD%BD%E9%93%BE%E6%8E%A5%EF%BC%9Ahttp://dpurl.cn/obtIVn%E3%80%90%E7%B3%BB%E7%BB%9F%E7%B3%BB%E5%88%97%E3%80%91%E4%B8%8B%E8%BD%BD%E9%93%BE%E6%8E%A5%EF%BC%9Ahttp://dpurl.cn/zTDWq8Q%E3%80%90%E7%AE%97%E6%B3%95%E7%B3%BB%E5%88%97%E3%80%91%E4%B8%8B%E8%BD%BD%E9%93%BE%E6%8E%A5%EF%BC%9Ahttp://dpurl.cn/ODj5qAB%E3%80%90%E8%BF%90%E7%BB%B4%E7%B3%BB%E5%88%97%E3%80%91%E4%B8%8B%E8%BD%BD%E9%93%BE%E6%8E%A5%EF%BC%9Ahttp://dpurl.cn/6zjgHFj%E3%80%90%E6%B5%8B%E8%AF%95%E7%B3%BB%E5%88%97%E3%80%91%E4%B8%8B%E8%BD%BD%E9%93%BE%E6%8E%A5%EF%BC%9Ahttp://dpurl.cn/wfKQqy%E3%80%90%E5%B7%A5%E7%A8%8B%E5%B8%88%E6%88%90%E9%95%BF%E7%B3%BB%E5%88%97%E3%80%91%E4%B8%8B%E8%BD%BD%E9%93%BE%E6%8E%A5%EF%BC%9Ahttp://dpurl.cn/p5sPoKT%E3%80%902018%E5%B9%B4%E7%BE%8E%E5%9B%A2%E7%82%B9%E8%AF%84%E6%8A%80%E6%9C%AF%E6%96%87%E7%AB%A0%E5%90%88%E8%BE%91%E3%80%91%E4%B8%8B%E8%BD%BD%E9%93%BE%E6%8E%A5%EF%BC%9Ahttp://dpurl.cn/iLGBtuS"&gt;http://dpurl.cn/DWVhPpS【后台系列】下载链接：http://dpurl.cn/obtIVn【系统系列】下载链接：http://dpurl.cn/zTDWq8Q【算法系列】下载链接：http://dpurl.cn/ODj5qAB【运维系列】下载链接：http://dpurl.cn/6zjgHFj【测试系列】下载链接：http://dpurl.cn/wfKQqy【工程师成长系列】下载链接：http://dpurl.cn/p5sPoKT【2018年美团点评技术文章合辑】下载链接：http://dpurl.cn/iLGBtuS&lt;/a&gt;&lt;/p&gt;
&lt;h1 id="总结归纳"&gt;🤗总结归纳&lt;/h1&gt;
&lt;p&gt;致谢：&lt;/p&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;!-- raw HTML omitted --&gt;</description></item><item><title>go-web程序的热更新</title><link>https://blog.jimersylee.com/posts/go-web%E7%A8%8B%E5%BA%8F%E7%9A%84%E7%83%AD%E6%9B%B4%E6%96%B0/</link><pubDate>Sun, 30 Sep 2018 11:25:00 +0000</pubDate><guid>https://blog.jimersylee.com/posts/go-web%E7%A8%8B%E5%BA%8F%E7%9A%84%E7%83%AD%E6%9B%B4%E6%96%B0/</guid><description>&lt;p&gt;当使用go开发web程序时，修改点代码就得编译，虽然编译速度很快，但是也累啊，想起java的spring-boot有热更新插件， php根本都不需要重启，go怎么可以落后。&lt;/p&gt;
&lt;p&gt;一顿搜索后，找到了&lt;a href="https://github.com/codegangsta/gin"&gt;gin&lt;/a&gt;和&lt;a href="https://github.com/pilu/fresh"&gt;fresh&lt;/a&gt;,都挺好用的&lt;/p&gt;
&lt;h1 id="gin"&gt;&lt;strong&gt;gin&lt;/strong&gt;&lt;/h1&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;cd path/to/app
gin run main.go
&lt;/code&gt;&lt;/pre&gt;&lt;h1 id="fresh"&gt;&lt;strong&gt;fresh&lt;/strong&gt;&lt;/h1&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;cd path/to/app
fresh
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;懒人有懒福～&lt;/p&gt;</description></item><item><title>Manjaro安装fusuma</title><link>https://blog.jimersylee.com/posts/manjaro%E5%AE%89%E8%A3%85fusuma/</link><pubDate>Wed, 12 Sep 2018 11:24:00 +0000</pubDate><guid>https://blog.jimersylee.com/posts/manjaro%E5%AE%89%E8%A3%85fusuma/</guid><description>&lt;h1 id="manjaro安装fusuma"&gt;Manjaro安装fusuma&lt;/h1&gt;
&lt;p&gt;环境:Manjaro&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt; ██████████████████ ████████ jimersylee@jimersylee-laptop
██████████████████ ████████ OS: Manjaro 17.1.12 Hakoila
██████████████████ ████████ Kernel: x86_64 Linux 4.14.67-1-MANJARO
██████████████████ ████████ Uptime: 3h 12m
████████ ████████ Packages: 1184
████████ ████████ ████████ Shell: zsh 5.5.1
████████ ████████ ████████ Resolution: 1920x1080
████████ ████████ ████████ DE: GNOME
████████ ████████ ████████ WM: GNOME Shell
████████ ████████ ████████ WM Theme: Adapta-Nokto-Maia
████████ ████████ ████████ GTK Theme: Adapta-Nokto-Maia [GTK2/3]
████████ ████████ ████████ Icon Theme: Papirus-Adapta-Maia
████████ ████████ ████████ Font: Noto Sans 11
████████ ████████ ████████ CPU: Intel Core i7-8550U @ 8x 4GHz [47.0°C]
GPU: Mesa DRI Intel(R) UHD Graphics 620 (Kabylake GT2)
RAM: 6157MiB / 15928MiB
&lt;/code&gt;&lt;/pre&gt;&lt;h1 id="将用户加入输入组"&gt;&lt;strong&gt;将用户加入输入组&lt;/strong&gt;&lt;/h1&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;sudo gpasswd -a $USER input
sudo reboot
&lt;/code&gt;&lt;/pre&gt;&lt;h1 id="安装ruby环境安装fusuma包"&gt;&lt;strong&gt;安装ruby环境，安装fusuma包&lt;/strong&gt;&lt;/h1&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;#安装ruby
sudo pacman -S ruby
sudo gem install fusuma
#
&lt;/code&gt;&lt;/pre&gt;&lt;h1 id="配置"&gt;&lt;strong&gt;配置&lt;/strong&gt;&lt;/h1&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;#将ruby程序目录加入路径
echo &amp;#34;export PATH=$PATH:/home/jimersylee/.gem/ruby/2.5.0/bin&amp;#34; &amp;gt;&amp;gt; ~/.profile
source ~/.profile
#人工启动
fusuma -d
#加入开机启动
/usr/share/applications 新建一个.desktop快捷方式，配置好
使用tweaks 添加 startup application
&lt;/code&gt;&lt;/pre&gt;</description></item><item><title>Manjaro安装Mariadb</title><link>https://blog.jimersylee.com/posts/manjaro%E5%AE%89%E8%A3%85mariadb/</link><pubDate>Sun, 09 Sep 2018 11:23:00 +0000</pubDate><guid>https://blog.jimersylee.com/posts/manjaro%E5%AE%89%E8%A3%85mariadb/</guid><description>&lt;h1 id="manjaro安装mariadb"&gt;Manjaro安装Mariadb&lt;/h1&gt;
&lt;p&gt;环境:Manjaro&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt; ██████████████████ ████████ jimersylee@jimersylee-laptop
██████████████████ ████████ OS: Manjaro 17.1.12 Hakoila
██████████████████ ████████ Kernel: x86_64 Linux 4.14.67-1-MANJARO
██████████████████ ████████ Uptime: 3h 12m
████████ ████████ Packages: 1184
████████ ████████ ████████ Shell: zsh 5.5.1
████████ ████████ ████████ Resolution: 1920x1080
████████ ████████ ████████ DE: GNOME
████████ ████████ ████████ WM: GNOME Shell
████████ ████████ ████████ WM Theme: Adapta-Nokto-Maia
████████ ████████ ████████ GTK Theme: Adapta-Nokto-Maia [GTK2/3]
████████ ████████ ████████ Icon Theme: Papirus-Adapta-Maia
████████ ████████ ████████ Font: Noto Sans 11
████████ ████████ ████████ CPU: Intel Core i7-8550U @ 8x 4GHz [47.0°C]
GPU: Mesa DRI Intel(R) UHD Graphics 620 (Kabylake GT2)
RAM: 6157MiB / 15928MiB
&lt;/code&gt;&lt;/pre&gt;&lt;h1 id="安装"&gt;&lt;strong&gt;安装&lt;/strong&gt;&lt;/h1&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;sudo pacman -S mariadb
&lt;/code&gt;&lt;/pre&gt;&lt;h1 id="配置"&gt;&lt;strong&gt;配置&lt;/strong&gt;&lt;/h1&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;#初始化
sudo mysql_install_db --user=mysql --basedir=/usr --datadir=/var/lib/mysql
#启动
sudo systemctl start mariadb
#设置密码
mysql_secure_installation
&lt;/code&gt;&lt;/pre&gt;</description></item><item><title>&lt;Go build web application&gt;的中文翻译版-第三章-连接数据</title><link>https://blog.jimersylee.com/posts/go-build-web-application%E7%9A%84%E4%B8%AD%E6%96%87%E7%BF%BB%E8%AF%91%E7%89%88-%E7%AC%AC%E4%B8%89%E7%AB%A0-%E8%BF%9E%E6%8E%A5%E6%95%B0%E6%8D%AE/</link><pubDate>Fri, 22 Sep 2017 13:38:00 +0000</pubDate><guid>https://blog.jimersylee.com/posts/go-build-web-application%E7%9A%84%E4%B8%AD%E6%96%87%E7%BF%BB%E8%AF%91%E7%89%88-%E7%AC%AC%E4%B8%89%E7%AB%A0-%E8%BF%9E%E6%8E%A5%E6%95%B0%E6%8D%AE/</guid><description>&lt;p&gt;在上一章中,我们探索了在web应用中如何处理URLS和指引他们转到不同的页面.同时,我们通过net/http中的handle创建了动态的链接和动态的结果.&lt;/p&gt;
&lt;p&gt;通过实现和扩展Gorilla toolkit的mux路由,我们通过正则表达式扩展了路由的能力,使其给予我们的应用更大的灵活性.&lt;/p&gt;
&lt;p&gt;其实这是一些最流行的web服务器的特性.比如说Apache和Nginx都在路由中提供了方法去解析正则表达式.&lt;/p&gt;
&lt;p&gt;但是这仅仅是构成web应用的基石.为了更加深入,我们需要去看看如何引入数据.&lt;/p&gt;
&lt;p&gt;前一章的例子中静态文件服务依赖于硬编码,这显然是过时的且难以控制的.&lt;/p&gt;
&lt;p&gt;但是幸运的是,从90年代末期开始,网站变得动态化,数据库开始统治世界.虽然APIs,微服务和NoSQL在某些领域替代了这些架构,但是这个架构在当今的Web开发中还是万金油的角色.&lt;/p&gt;
&lt;p&gt;所以,事不宜迟,让我们开始获取一些动态数据&lt;/p&gt;
&lt;p&gt;在这一章中,我们将学习以下几个主题&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;连接数据库&lt;/li&gt;
&lt;li&gt;使用GUID美化URLs&lt;/li&gt;
&lt;li&gt;处理404页面&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="连接一个数据库"&gt;&lt;strong&gt;连接一个数据库&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;为了连接数据库,Go的SQL接口提供了一个非常简单且可信赖的方式去连接拥有驱动的不同种类的数据库服务器.&lt;/p&gt;
&lt;p&gt;目前,大部分流行的数据库都支持-MySQL,Postgres,SQLite,MSSQL和相当多的实现了Go提供的database/sql接口的数据库驱动.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Note:在本书中,我们将会把MySQL和Postgres数据库使用最好的实践运用在多个例子上.安装MySQL和Postgres在Nix,Windows,OS X 系统的机器上是相当基础的工作&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h1 id="创建mysql数据库"&gt;&lt;strong&gt;创建MySQL数据库&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;你可以选择设计任何你想要的应用,但是在这些例子中,我们将着手一个非常的简单的博客.&lt;/p&gt;
&lt;p&gt;我们的目标是尽可能地在数据库中创建一些博客的入口,最好可以使用GUID在数据库中直接地获取数据和展示,如果博客的入口不存在,将展示错误页面.&lt;/p&gt;
&lt;p&gt;为了实现这个需求,我们将创建一个包含了我们的页面的MySQL数据库.这个数据库将包含一个整数型的,自动递增的ID,一个全局唯一的标识,或者GUID,还有一些博客的初始数据.&lt;/p&gt;
&lt;p&gt;简单起见,我们创建一个叫存储标题的page_title字段,存储页面内容的page_content字段,还有一个使用Unix时间戳的字段page_date.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;CREATETABLE&lt;/span&gt; &lt;span style="color:#e6db74"&gt;`pages`&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;`id`&lt;/span&gt; int(&lt;span style="color:#ae81ff"&gt;11&lt;/span&gt;) &lt;span style="color:#a6e22e"&gt;unsignedNOT&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;NULL&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;AUTO_INCREMENT&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;`page_guid`&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;varchar&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;256&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;NOT&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;NULLDEFAULT&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;&amp;#39;&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;`page_title`&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;varchar&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;256&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;DEFAULT&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;NULL&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;`page_content`&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;mediumtext&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;`page_date`&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;timestampNOT&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;NULLDEFAULTCURRENT_TIMESTAMPONUPDATECURRENT_TIMESTAMP&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;PRIMARYKEY&lt;/span&gt; (&lt;span style="color:#e6db74"&gt;`id`&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;UNIQUEKEY&lt;/span&gt; &lt;span style="color:#e6db74"&gt;`page_guid`&lt;/span&gt; (&lt;span style="color:#e6db74"&gt;`page_guid`&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)&lt;span style="color:#a6e22e"&gt;ENGINE&lt;/span&gt;=&lt;span style="color:#a6e22e"&gt;InnoDB&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;AUTO_INCREMENT&lt;/span&gt;=&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;DEFAULTCHARSET&lt;/span&gt;=&lt;span style="color:#a6e22e"&gt;utf&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;8&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;将page_guid标记为UNIQUE_KEY相当重要,如果我们允许出现重复的page_guid,在浏览某个网址的时候可能出现不准确的情况. 我们使用以下的语句插入一些blog数据&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;INSERTINTO&lt;/span&gt; &lt;span style="color:#e6db74"&gt;`pages`&lt;/span&gt; (&lt;span style="color:#e6db74"&gt;`id`&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;`page_guid`&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;`page_title`&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;`page_content`&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;`page_date`&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;VALUES&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;NULL&lt;/span&gt;, &lt;span style="color:#960050;background-color:#1e0010"&gt;&amp;#39;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;hello&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;world&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;&amp;#39;&lt;/span&gt;, &lt;span style="color:#960050;background-color:#1e0010"&gt;&amp;#39;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;Hello&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;World&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;&amp;#39;&lt;/span&gt;, &lt;span style="color:#960050;background-color:#1e0010"&gt;&amp;#39;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;I&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;\&amp;#39;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;m&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;so&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;glad&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;you&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;found&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;this&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;page&lt;/span&gt;! &lt;span style="color:#a6e22e"&gt;It&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;\&amp;#39;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;s&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;been&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;sitting&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;patiently&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;on&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;the&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Internet&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;some&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;time&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;just&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;waiting&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;a&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;visitor&lt;/span&gt;.&lt;span style="color:#960050;background-color:#1e0010"&gt;&amp;#39;&lt;/span&gt;,&lt;span style="color:#a6e22e"&gt;CURRENT_TIMESTAMP&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;执行了上面的语句之后,我们就获得了初始数据 使用下面的代码来获得连接数据库的能力&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;package&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;database/sql&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;_&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;github.com/go-sql-driver/mysql&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;log&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;我们导入MySQL驱动包来完成需求.通常,这意味着驱动是另一个包的实现.你能注意到使用 &lt;em&gt;符号来导入包.你可能已经熟悉这点,作为一种快速且脏的方式去忽略类的实例的返回值.比如说x,&lt;/em&gt; :=something() 允许你去忽略第二个返回值.这经常也被开发者用在计划去使用一个库,但是目前还没有用到的情况.通过这种方式准备包,它允许导入声明而不引起编译期报错.虽然这不是推荐的做法,但是在预载入方法中使用下划线_或者空白标识符,好处是这是很常见的做法也普遍被接受. 其实,这全部依赖于你怎样以及为何使用标识符.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;DBHost&lt;/span&gt; = &lt;span style="color:#e6db74"&gt;&amp;#34;127.0.0.1&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;DBPort&lt;/span&gt; = &lt;span style="color:#e6db74"&gt;&amp;#34;:3306&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;DBUser&lt;/span&gt; = &lt;span style="color:#e6db74"&gt;&amp;#34;root&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;DBPass&lt;/span&gt; = &lt;span style="color:#e6db74"&gt;&amp;#34;password!&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;DBDbase&lt;/span&gt; = &lt;span style="color:#e6db74"&gt;&amp;#34;cms&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;记得使用你自己的配置去替换以上值&lt;/p&gt;</description></item><item><title>&lt;Go build web application&gt;的中文翻译版本</title><link>https://blog.jimersylee.com/posts/go-build-web-application%E7%9A%84%E4%B8%AD%E6%96%87%E7%BF%BB%E8%AF%91%E7%89%88%E6%9C%AC/</link><pubDate>Wed, 20 Sep 2017 11:17:00 +0000</pubDate><guid>https://blog.jimersylee.com/posts/go-build-web-application%E7%9A%84%E4%B8%AD%E6%96%87%E7%BF%BB%E8%AF%91%E7%89%88%E6%9C%AC/</guid><description>&lt;h1 id="目录"&gt;&lt;strong&gt;目录&lt;/strong&gt;&lt;/h1&gt;
&lt;h1 id="模块1学习go的web开发"&gt;&lt;strong&gt;模块1:学习Go的Web开发&lt;/strong&gt;&lt;/h1&gt;
&lt;h3 id="第一章介绍和安装go环境"&gt;&lt;strong&gt;第一章:介绍和安装Go环境&lt;/strong&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;安装Go&lt;/li&gt;
&lt;li&gt;构建一个项目&lt;/li&gt;
&lt;li&gt;引入包&lt;/li&gt;
&lt;li&gt;介绍net包&lt;/li&gt;
&lt;li&gt;你好,Web&lt;/li&gt;
&lt;li&gt;本章总结&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="第二章服务和路由"&gt;&lt;strong&gt;第二章:服务和路由&lt;/strong&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;直接的文件服务&lt;/li&gt;
&lt;li&gt;基本路由&lt;/li&gt;
&lt;li&gt;使用Gorilla实现更复杂的路由&lt;/li&gt;
&lt;li&gt;转发请求&lt;/li&gt;
&lt;li&gt;处理基本的错误&lt;/li&gt;
&lt;li&gt;本章总结&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="第三章连接数据"&gt;&lt;strong&gt;第三章:连接数据&lt;/strong&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;连接一个数据库&lt;/li&gt;
&lt;li&gt;使用GUID美化URLs&lt;/li&gt;
&lt;li&gt;处理404错误&lt;/li&gt;
&lt;li&gt;总结&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="第四章使用模板"&gt;&lt;strong&gt;第四章:使用模板&lt;/strong&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;介绍模板,上下文和可视化&lt;/li&gt;
&lt;li&gt;HTML模板和文本模板&lt;/li&gt;
&lt;li&gt;渲染变量和安全性&lt;/li&gt;
&lt;li&gt;使用逻辑和控制结构&lt;/li&gt;
&lt;li&gt;本章总结&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="第五章使用restful-apis进行前端集成"&gt;&lt;strong&gt;第五章:使用RESTful APIs进行前端集成&lt;/strong&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;设置基本的API结构&lt;/li&gt;
&lt;li&gt;RESTful架构和最佳实践&lt;/li&gt;
&lt;li&gt;创建我们的第一个API&lt;/li&gt;
&lt;li&gt;实现安全&lt;/li&gt;
&lt;li&gt;使用POST创建数据&lt;/li&gt;
&lt;li&gt;使用PUT更改数据&lt;/li&gt;
&lt;li&gt;本章总结&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="第六章session和cookies"&gt;&lt;strong&gt;第六章:Session和Cookies&lt;/strong&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;设置cookies&lt;/li&gt;
&lt;li&gt;存储用户的信息&lt;/li&gt;
&lt;li&gt;初始化一个服务端的session&lt;/li&gt;
&lt;li&gt;本章总结&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="第七章微服务和通讯"&gt;&lt;strong&gt;第七章:微服务和通讯&lt;/strong&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;介绍引入微服务&lt;/li&gt;
&lt;li&gt;使用微服务的利弊&lt;/li&gt;
&lt;li&gt;理解微服务的内核&lt;/li&gt;
&lt;li&gt;微服务之间的通讯&lt;/li&gt;
&lt;li&gt;在线上放一个信息&lt;/li&gt;
&lt;li&gt;从其他服务读取信息&lt;/li&gt;
&lt;li&gt;本章总结&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="第八章记录日志和测试"&gt;&lt;strong&gt;第八章:记录日志和测试&lt;/strong&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;介绍Go中的日志&lt;/li&gt;
&lt;li&gt;记录日志到IO中&lt;/li&gt;
&lt;li&gt;格式化你的输出&lt;/li&gt;
&lt;li&gt;使用panics和fatal errors&lt;/li&gt;
&lt;li&gt;介绍Go中的测试&lt;/li&gt;
&lt;li&gt;本章总结&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="第九章安全"&gt;&lt;strong&gt;第九章:安全&lt;/strong&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;在任何地方使用HTTPS-实现TLS&lt;/li&gt;
&lt;li&gt;防止SQL注入&lt;/li&gt;
&lt;li&gt;防范XSS攻击&lt;/li&gt;
&lt;li&gt;防范CSRF跨站攻击&lt;/li&gt;
&lt;li&gt;加密cookies&lt;/li&gt;
&lt;li&gt;使用安全中间件&lt;/li&gt;
&lt;li&gt;本章总结&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="第十章缓存代理和提高性能"&gt;&lt;strong&gt;第十章:缓存,代理和提高性能&lt;/strong&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;确定瓶颈&lt;/li&gt;
&lt;li&gt;实现反向代理&lt;/li&gt;
&lt;li&gt;实现缓存&lt;/li&gt;
&lt;li&gt;实现HTTP/2&lt;/li&gt;
&lt;li&gt;本章总结&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="模块2go-编程蓝皮书"&gt;&lt;strong&gt;模块2:Go 编程蓝皮书&lt;/strong&gt;&lt;/h1&gt;
&lt;h3 id="第一章使用web-sockets构建的聊天应用"&gt;&lt;strong&gt;第一章:使用Web Sockets构建的聊天应用&lt;/strong&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;一个简单的Web服务器&lt;/li&gt;
&lt;li&gt;在服务器上建模一个聊天室和客户端&lt;/li&gt;
&lt;li&gt;构建一个使用HTML和JavaScript的聊天客户端&lt;/li&gt;
&lt;li&gt;跟踪代码获取内在的流程&lt;/li&gt;
&lt;li&gt;本章总结&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="第二章增加权限"&gt;&lt;strong&gt;第二章:增加权限&lt;/strong&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;拦截所有请求&lt;/li&gt;
&lt;li&gt;创建一个社交化的登录页面&lt;/li&gt;
&lt;li&gt;动态路径&lt;/li&gt;
&lt;li&gt;OAuth2&lt;/li&gt;
&lt;li&gt;把你的APP告诉权限提供者&lt;/li&gt;
&lt;li&gt;实现额外的登录&lt;/li&gt;
&lt;li&gt;本章总结&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="第三章3个方法去实现文件缩略图"&gt;&lt;strong&gt;第三章:3个方法去实现文件缩略图&lt;/strong&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;在权限服务器上的头像&lt;/li&gt;
&lt;li&gt;实现Gravatar&lt;/li&gt;
&lt;li&gt;上传头像图片&lt;/li&gt;
&lt;li&gt;整合3种实现&lt;/li&gt;
&lt;li&gt;本章总结&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="第四章查询域名的命令行工具"&gt;&lt;strong&gt;第四章:查询域名的命令行工具&lt;/strong&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;命令行工具的管道设计&lt;/li&gt;
&lt;li&gt;5个简单的程序&lt;/li&gt;
&lt;li&gt;编写所有5个程序&lt;/li&gt;
&lt;li&gt;本章总结&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="第五章构建分布式系统与复杂的数据交互"&gt;&lt;strong&gt;第五章:构建分布式系统,与复杂的数据交互&lt;/strong&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;系统设计&lt;/li&gt;
&lt;li&gt;安装环境&lt;/li&gt;
&lt;li&gt;获取Twitter的投票&lt;/li&gt;
&lt;li&gt;计算投票&lt;/li&gt;
&lt;li&gt;运行我们的解决方案&lt;/li&gt;
&lt;li&gt;本章总结&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="第六章通过restful-web数据接口对外提供数据和功能"&gt;&lt;strong&gt;第六章:通过RESTful web数据接口对外提供数据和功能&lt;/strong&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;RESTful API 设计&lt;/li&gt;
&lt;li&gt;在处理器间共享数据&lt;/li&gt;
&lt;li&gt;包装处理函数&lt;/li&gt;
&lt;li&gt;响应&lt;/li&gt;
&lt;li&gt;理解请求&lt;/li&gt;
&lt;li&gt;一个简单的主函数去处理我们的API&lt;/li&gt;
&lt;li&gt;处理节点&lt;/li&gt;
&lt;li&gt;一个web客户端去消费API&lt;/li&gt;
&lt;li&gt;运行解决方案&lt;/li&gt;
&lt;li&gt;本章总结&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="第七章随机推荐web服务"&gt;&lt;strong&gt;第七章:随机推荐Web服务&lt;/strong&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;项目预览&lt;/li&gt;
&lt;li&gt;用代码展示数据&lt;/li&gt;
&lt;li&gt;构造随机推荐&lt;/li&gt;
&lt;li&gt;本章总结&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="第八章文件备份系统"&gt;&lt;strong&gt;第八章:文件备份系统&lt;/strong&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;解决方案设计&lt;/li&gt;
&lt;li&gt;备份包&lt;/li&gt;
&lt;li&gt;用户命令行工具&lt;/li&gt;
&lt;li&gt;备份守护工具&lt;/li&gt;
&lt;li&gt;测试解决方案&lt;/li&gt;
&lt;li&gt;本章总结&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="模块3精通go的高并发"&gt;&lt;strong&gt;模块3:精通Go的高并发&lt;/strong&gt;&lt;/h1&gt;
&lt;h3 id="第一章介绍go并发编程"&gt;&lt;strong&gt;第一章:介绍Go并发编程&lt;/strong&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;介绍协程&lt;/li&gt;
&lt;li&gt;实现延迟控制机制&lt;/li&gt;
&lt;li&gt;理解协程与协同&lt;/li&gt;
&lt;li&gt;实现通道&lt;/li&gt;
&lt;li&gt;关闭与协程&lt;/li&gt;
&lt;li&gt;构建一个使用协程和通道的爬虫&lt;/li&gt;
&lt;li&gt;本章总结&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="第二章理解并发模型"&gt;&lt;strong&gt;第二章:理解并发模型&lt;/strong&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;理解协程如何工作&lt;/li&gt;
&lt;li&gt;同步和异步协程&lt;/li&gt;
&lt;li&gt;可视化并发&lt;/li&gt;
&lt;li&gt;RSS实战&lt;/li&gt;
&lt;li&gt;CSP的一点介绍&lt;/li&gt;
&lt;li&gt;Go和角色模型&lt;/li&gt;
&lt;li&gt;面向对象&lt;/li&gt;
&lt;li&gt;使用并发&lt;/li&gt;
&lt;li&gt;管理线程&lt;/li&gt;
&lt;li&gt;使用同步和互斥锁住数据&lt;/li&gt;
&lt;li&gt;本章总结&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="第三章开发并行策略"&gt;&lt;strong&gt;第三章:开发并行策略&lt;/strong&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;在复杂的并发中提高效率&lt;/li&gt;
&lt;li&gt;使用竞争检查识别竞争条件&lt;/li&gt;
&lt;li&gt;同步我们的并发操作&lt;/li&gt;
&lt;li&gt;项目-多用户预约日历&lt;/li&gt;
&lt;li&gt;一个多用户预约日历&lt;/li&gt;
&lt;li&gt;风格说明&lt;/li&gt;
&lt;li&gt;不变性说明&lt;/li&gt;
&lt;li&gt;本章总结&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="第四章应用中的数据完整性"&gt;&lt;strong&gt;第四章:应用中的数据完整性&lt;/strong&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;深入理解互斥与同步&lt;/li&gt;
&lt;li&gt;协程的代价&lt;/li&gt;
&lt;li&gt;处理文件&lt;/li&gt;
&lt;li&gt;更底层-实现C&lt;/li&gt;
&lt;li&gt;分布式的Go&lt;/li&gt;
&lt;li&gt;几种常见的一致性模型&lt;/li&gt;
&lt;li&gt;使用memcached&lt;/li&gt;
&lt;li&gt;本章总结&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="第五章锁区块和更好的通道"&gt;&lt;strong&gt;第五章:锁,区块和更好的通道&lt;/strong&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;理解Go中的区块方法&lt;/li&gt;
&lt;li&gt;清除协程&lt;/li&gt;
&lt;li&gt;创建通道的通道&lt;/li&gt;
&lt;li&gt;Pprof-一个令人惊叹的工具&lt;/li&gt;
&lt;li&gt;处理死锁和错误&lt;/li&gt;
&lt;li&gt;本章总结&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="第六章c10k-go中的一个无锁的web服务器"&gt;&lt;strong&gt;第六章:C10K-Go中的一个无锁的Web服务器&lt;/strong&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;攻克C10K问题&lt;/li&gt;
&lt;li&gt;创建我们的C10K Web服务器&lt;/li&gt;
&lt;li&gt;提供页面服务&lt;/li&gt;
&lt;li&gt;多线程和利用多核&lt;/li&gt;
&lt;li&gt;探索我们的Web服务器&lt;/li&gt;
&lt;li&gt;本章总结&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="第七章性能与可扩展性"&gt;&lt;strong&gt;第七章:性能与可扩展性&lt;/strong&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Go的高性能&lt;/li&gt;
&lt;li&gt;使用App Engine&lt;/li&gt;
&lt;li&gt;分布式的Go&lt;/li&gt;
&lt;li&gt;一些有用的库&lt;/li&gt;
&lt;li&gt;内存维护&lt;/li&gt;
&lt;li&gt;本章总结&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="第八章并发程序架构"&gt;&lt;strong&gt;第八章:并发程序架构&lt;/strong&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;设计我们的并发程序&lt;/li&gt;
&lt;li&gt;确定我们的需求&lt;/li&gt;
&lt;li&gt;在Go中使用NoSQL作为数据存储&lt;/li&gt;
&lt;li&gt;监控文件系统的变化&lt;/li&gt;
&lt;li&gt;管理日志文件&lt;/li&gt;
&lt;li&gt;处理配置文件&lt;/li&gt;
&lt;li&gt;检测文件变化&lt;/li&gt;
&lt;li&gt;备份文件&lt;/li&gt;
&lt;li&gt;设计Web接口&lt;/li&gt;
&lt;li&gt;还原文件的历史-命令行&lt;/li&gt;
&lt;li&gt;检查服务器的健康度&lt;/li&gt;
&lt;li&gt;本章总结&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="第九章在go中记录日志和测试并发"&gt;&lt;strong&gt;第九章:在Go中记录日志和测试并发&lt;/strong&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;处理错误和记录日志&lt;/li&gt;
&lt;li&gt;使用log4go包作为健壮的日志组件&lt;/li&gt;
&lt;li&gt;使用runtime包作为细粒度的堆栈跟踪组件&lt;/li&gt;
&lt;li&gt;本章总结&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="第十章先进的并发和最佳实践"&gt;&lt;strong&gt;第十章:先进的并发和最佳实践&lt;/strong&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;使用channels跨越基础&lt;/li&gt;
&lt;li&gt;构建工作者&lt;/li&gt;
&lt;li&gt;实现空通道区块&lt;/li&gt;
&lt;li&gt;使用tomb实现对协程更多的细粒度的控制&lt;/li&gt;
&lt;li&gt;使用通道定时&lt;/li&gt;
&lt;li&gt;通过并发模式构建负载均衡器&lt;/li&gt;
&lt;li&gt;选择单向和双向通道&lt;/li&gt;
&lt;li&gt;使用泛型通道&lt;/li&gt;
&lt;li&gt;使用Go的单元测试&lt;/li&gt;
&lt;li&gt;使用Google的App Engine&lt;/li&gt;
&lt;li&gt;使用最佳实践&lt;/li&gt;
&lt;li&gt;本章总结&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Redis高可用架构</title><link>https://blog.jimersylee.com/posts/redis%E9%AB%98%E5%8F%AF%E7%94%A8%E6%9E%B6%E6%9E%84/</link><pubDate>Tue, 05 Sep 2017 09:13:00 +0000</pubDate><guid>https://blog.jimersylee.com/posts/redis%E9%AB%98%E5%8F%AF%E7%94%A8%E6%9E%B6%E6%9E%84/</guid><description>&lt;h1 id="redis高可用架构"&gt;&lt;strong&gt;Redis高可用架构&lt;/strong&gt;&lt;/h1&gt;
&lt;h1 id="前言"&gt;&lt;strong&gt;前言&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;&lt;code&gt;Redis&lt;/code&gt;是一个高性能的&lt;code&gt;key-value&lt;/code&gt;数据库，现时越来越多企业与应用使用&lt;code&gt;Redis&lt;/code&gt;作为缓存服务器。楼主是一枚&lt;code&gt;JAVA&lt;/code&gt;后端程序员，也算是半个运维工程师了。在&lt;code&gt;Linux&lt;/code&gt;服务器上搭建&lt;code&gt;Redis&lt;/code&gt;，怎么可以不会呢？下面楼主就带着大家从0开始，依次搭建：&lt;code&gt;Redis&lt;/code&gt;单机服务器 -&amp;gt; &lt;code&gt;Redis&lt;/code&gt;主从复制 -&amp;gt;&lt;code&gt;Redis-Sentinel高可用&lt;/code&gt;。逐步搭建出高可用的Redis缓存服务器。&lt;/p&gt;
&lt;h1 id="搭建redis"&gt;&lt;strong&gt;搭建Redis&lt;/strong&gt;&lt;/h1&gt;
&lt;h3 id="1-下载并解压"&gt;&lt;strong&gt;1. 下载并解压&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;首先从&lt;code&gt;Redis&lt;/code&gt;官网下载&lt;code&gt;Redis&lt;/code&gt;并解压，楼主使用的版本是4.0.2。依次执行如下命令：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;cd /opt
wget http://download.redis.io/releases/redis-4.0.2.tar.gz
tar -zcvf redis-4.0.2.tar.gz
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;如果没有安装&lt;code&gt;gcc&lt;/code&gt;依赖包，则安装对应依赖包&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;yum install -y gcc-c++ tcl
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="2-编译并安装"&gt;&lt;strong&gt;2. 编译并安装&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;下载并解压完毕后，则对源码包进行编译安装，楼主的&lt;code&gt;Redis&lt;/code&gt;安装路径为&lt;code&gt;/usr/local/redis&lt;/code&gt;，同学们可以自行修改语句：&lt;code&gt;make install PREFIX=你想要安装的路径&lt;/code&gt;&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;cd /opt/redis-4.0.2
make install PREFIX=/usr/local
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;复制&lt;code&gt;Redis&lt;/code&gt;相关命令到&lt;code&gt;/usr/sbin&lt;/code&gt;目录下，这样就可以直接执行这些命令，不用写全路径&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;cd /usr/local/redis/bin
sudo cp redis-* /usr/sbin
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="3-建立redis配置文件"&gt;&lt;strong&gt;3. 建立Redis配置文件&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;安装完成之后将 &lt;code&gt;Redis&lt;/code&gt; 配置文件拷贝到系统配置目录&lt;code&gt;/etc/&lt;/code&gt;下，&lt;code&gt;redis.conf&lt;/code&gt; 是 &lt;code&gt;Redis&lt;/code&gt; 的配置文件，&lt;code&gt;redis.conf&lt;/code&gt; 在 &lt;code&gt;Redis&lt;/code&gt; 源码目录，&lt;code&gt;port&lt;/code&gt;默认 6379。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;cp /usr/local/redis-4.0.2/redis.conf /etc/
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;code&gt;Redis&lt;/code&gt;配置文件主要参数解析参考&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;daemonize no#redis进程是否以守护进程的方式运行,yes为是,no为否(不以守护进程的方式运行会占用一个终端)
pidfile /var/run/redis.pid#指定redis进程的PID文件存放位置
port 6379#redis进程的端口号
bind 127.0.0.1#绑定的主机地址
timeout 300#客户端闲置多长时间后关闭连接,默认此参数为0即关闭此功能
loglevel verbose#redis日志级别,可用的级别有debug.verbose.notice.warning
logfile stdout#log文件输出位置,如果进程以守护进程的方式运行,此处又将输出文件设置为stdout的话,就会将日志信息输出到/dev/null里面去了
databases 16#设置数据库的数量,默认为0可以使用select &amp;lt;dbid&amp;gt;命令在连接上指定数据库id
save &amp;lt;seconds&amp;gt;&amp;lt;changes&amp;gt;#指定在多少时间内刷新次数达到多少的时候会将数据同步到数据文件;
rdbcompression yes#指定存储至本地数据库时是否压缩文件,默认为yes即启用存储;
dbfilename dump.db#指定本地数据库文件名
dir ./#指定本地数据问就按存放位置;
slaveof &amp;lt;masterip&amp;gt;&amp;lt;masterport&amp;gt;#指定当本机为slave服务时,设置master服务的IP地址及端口,在redis启动的时候他会自动跟master进行数据同步
masterauth &amp;lt;master-password&amp;gt;#当master设置了密码保护时,slave服务连接master的密码;
requirepass footbared#设置redis连接密码,如果配置了连接密码,客户端在连接redis是需要通过AUTH&amp;lt;password&amp;gt;命令提供密码,默认关闭
maxclients 128#设置同一时间最大客户连接数,默认无限制;redis可以同时连接的客户端数为redis程序可以打开的最大文件描述符,如果设置 maxclients 0，表示不作限制。当客户端连接数到达限制时，Redis会关闭新的连接并向客户端返回max number of clients reached错误信息
maxmemory&amp;lt;bytes&amp;gt;#指定Redis最大内存限制，Redis在启动时会把数据加载到内存中，达到最大内存后，Redis会先尝试清除已到期或即将到期的Key，当此方法处理 后，仍然到达最大内存设置，将无法再进行写入操作，但仍然可以进行读取操作。Redis新的vm机制，会把Key存放内存，Value会存放在swap区
appendonly no#指定是否在每次更新操作后进行日志记录，Redis在默认情况下是异步的把数据写入磁盘，如果不开启，可能会在断电时导致一段时间内的数据丢失。因为 redis本身同步数据文件是按上面save条件来同步的，所以有的数据会在一段时间内只存在于内存中。默认为no
appendfilename appendonly.aof#指定跟新日志文件名默认为appendonly.aof
appendfsync everysec#指定更新日志的条件,有三个可选参数no：表示等操作系统进行数据缓存同步到磁盘(快),always：表示每次更新操作后手动调用fsync()将数据写到磁盘(慢，安全), everysec：表示每秒同步一次(折衷，默认值);
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="31-设置后端启动"&gt;&lt;strong&gt;3.1 设置后端启动：&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;由于&lt;code&gt;Redis&lt;/code&gt;默认是前端启动，必须保持在当前的窗口中，如果使用&lt;code&gt;ctrl + c&lt;/code&gt;退出，那么&lt;code&gt;Redis&lt;/code&gt;也就退出，不建议使用。&lt;/p&gt;</description></item><item><title>我眼中规范的开发流程</title><link>https://blog.jimersylee.com/posts/%E6%88%91%E7%9C%BC%E4%B8%AD%E8%A7%84%E8%8C%83%E7%9A%84%E5%BC%80%E5%8F%91%E6%B5%81%E7%A8%8B/</link><pubDate>Sat, 22 Jul 2017 09:12:00 +0000</pubDate><guid>https://blog.jimersylee.com/posts/%E6%88%91%E7%9C%BC%E4%B8%AD%E8%A7%84%E8%8C%83%E7%9A%84%E5%BC%80%E5%8F%91%E6%B5%81%E7%A8%8B/</guid><description>&lt;h1 id="我眼中规范的开发流程"&gt;我眼中规范的开发流程&lt;/h1&gt;
&lt;h1 id="基于自建svn的信息存储"&gt;&lt;strong&gt;基于自建SVN的信息存储&lt;/strong&gt;&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;存放开发文档&lt;/li&gt;
&lt;li&gt;存放测试用例&lt;/li&gt;
&lt;li&gt;存放三方对接文档&lt;/li&gt;
&lt;li&gt;存放同事的学习记录与分享&lt;/li&gt;
&lt;li&gt;存放会议纪要&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="基于git的开发流程"&gt;&lt;strong&gt;基于git的开发流程&lt;/strong&gt;&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;代码全部托管于git服务上&lt;/li&gt;
&lt;li&gt;完善的分支规范,区分开发,测试,生产分支&lt;/li&gt;
&lt;li&gt;基于gitflow的开发流程,区分feature,bugfix,hotfix等分支创建规则&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="完善的测试流程"&gt;&lt;strong&gt;完善的测试流程&lt;/strong&gt;&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;产品出文档测试即开始编写测试用例&lt;/li&gt;
&lt;li&gt;测试版本开发完成开始测试&lt;/li&gt;
&lt;li&gt;使用bugout进行记录与跟踪bug&lt;/li&gt;
&lt;li&gt;开发处理bug,在bugout上提交&lt;/li&gt;
&lt;li&gt;测试再次测试直到通过&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="基于持续构建工具的构建流程"&gt;&lt;strong&gt;基于持续构建工具的构建流程&lt;/strong&gt;&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;使用jenkin持续构建,单元测试,Sonar代码分析&lt;/li&gt;
&lt;li&gt;每个项目至少3个分支,dev,master,release分支&lt;/li&gt;
&lt;li&gt;测试在dev分支,预发布在master分支,线上使用release分支&lt;/li&gt;
&lt;li&gt;dev分支自动提交构建&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="平台架构"&gt;&lt;strong&gt;平台架构&lt;/strong&gt;&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;分布式的微服务架构&lt;/li&gt;
&lt;li&gt;保证单机宕机对整体服务没有影响,做到自动切换主备&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="统一开发环境与工具"&gt;&lt;strong&gt;统一开发环境与工具&lt;/strong&gt;&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;后端开发统一Jetbrains全家桶&lt;/li&gt;
&lt;li&gt;接口调试使用Postman&lt;/li&gt;
&lt;li&gt;文档使用showdoc&lt;/li&gt;
&lt;li&gt;代码管理使用git&lt;/li&gt;
&lt;li&gt;统一使用邮件沟通&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;致谢：&lt;/p&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;!-- raw HTML omitted --&gt;</description></item><item><title>Spring Cloud 之actuator模块简介</title><link>https://blog.jimersylee.com/posts/spring-cloud-%E4%B9%8Bactuator%E6%A8%A1%E5%9D%97%E7%AE%80%E4%BB%8B/</link><pubDate>Sat, 29 Apr 2017 10:59:00 +0000</pubDate><guid>https://blog.jimersylee.com/posts/spring-cloud-%E4%B9%8Bactuator%E6%A8%A1%E5%9D%97%E7%AE%80%E4%BB%8B/</guid><description>&lt;h1 id="spring-cloud-之actuator模块简介"&gt;Spring Cloud 之actuator模块简介&lt;/h1&gt;
&lt;p&gt;此模块提供监控与采集功能,通过在pom中引用此依赖,可以方便地使用其功能&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;lt;dependency&amp;gt;
&amp;lt;groupId&amp;gt;org.springframework.boot&amp;lt;/groupId&amp;gt;
&amp;lt;artifactId&amp;gt;spring-boot-starter-actuator&amp;lt;/artifactId&amp;gt;
&amp;lt;/dependency&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;h1 id="原生端点"&gt;&lt;strong&gt;原生端点&lt;/strong&gt;&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;应用配置类:获取应用程序中加载的应用配置,环境变量,自动化配置报告等与SpringBoot应用密切相关的配置类信息&lt;/li&gt;
&lt;li&gt;度量指标类:获取应用程序运行过程中用户监控的度量指标,比如内存信息,线程池信息,HTTP请求统计等&lt;/li&gt;
&lt;li&gt;操作控制类:提供了对应用的关闭操作类功能&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="应用配置类"&gt;&lt;strong&gt;应用配置类&lt;/strong&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;/autoconfig:该端点用来获取应用的自动化配置报告.包括条件匹配成功以及不成功的配置&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;positiveMatches中返回是条件匹配成功的自动化配置&lt;/li&gt;
&lt;li&gt;negativeMatches中返回的是条件匹配不成功的自动化配置&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;/beans:该端点用来获取应用上下文中创建的所有Bean&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;context&amp;#34;&lt;/span&gt;:&lt;span style="color:#e6db74"&gt;&amp;#34;application&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;parent&amp;#34;&lt;/span&gt;:&lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;beans&amp;#34;&lt;/span&gt;:[
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;bean&amp;#34;&lt;/span&gt;:&lt;span style="color:#e6db74"&gt;&amp;#34;helloApplication&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;aliases&amp;#34;&lt;/span&gt;:[
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;scope&amp;#34;&lt;/span&gt;:&lt;span style="color:#e6db74"&gt;&amp;#34;singleton&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;:&lt;span style="color:#e6db74"&gt;&amp;#34;com.jimersylee.hello.HelloApplication$$EnhancerBySpringCGLIB$$d3ebe421&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;resource&amp;#34;&lt;/span&gt;:&lt;span style="color:#e6db74"&gt;&amp;#34;null&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;dependencies&amp;#34;&lt;/span&gt;:[
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;每个Bean中都包含了下面这些信息&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;bean:Bean的名称&lt;/li&gt;
&lt;li&gt;scope:Bean的作用域&lt;/li&gt;
&lt;li&gt;type:Bean的Java类型&lt;/li&gt;
&lt;li&gt;resource:class文件的具体路径&lt;/li&gt;
&lt;li&gt;dependencies:依赖的Bean名称&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;/configprops:该端点用来获取应用中配置的属性信息报告,可以通过使用endpoints.configprops.enabled=false来关闭&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;env:该端点与/configprops不同,它用来获取应用所有可用的环境属性报告&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;profiles&amp;#34;&lt;/span&gt;:[
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;server.ports&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;local.server.port&amp;#34;&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;8080&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;servletContextInitParams&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;systemProperties&amp;#34;&lt;/span&gt;:{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;java.runtime.name&amp;#34;&lt;/span&gt;:&lt;span style="color:#e6db74"&gt;&amp;#34;Java(TM) SE Runtime Environment&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;awt.useSystemAAFontSettings&amp;#34;&lt;/span&gt;:&lt;span style="color:#e6db74"&gt;&amp;#34;gasp&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;sun.boot.library.path&amp;#34;&lt;/span&gt;:&lt;span style="color:#e6db74"&gt;&amp;#34;/opt/jdk1.8.0_144/jre/lib/amd64&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;java.vm.version&amp;#34;&lt;/span&gt;:&lt;span style="color:#e6db74"&gt;&amp;#34;25.144-b01&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;maven.multiModuleProjectDirectory&amp;#34;&lt;/span&gt;:&lt;span style="color:#e6db74"&gt;&amp;#34;/home/jimersylee/projects/java/spring-cloud-action/hello&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;/mappings:该端点用来返回所有Spring MVC的控制器映射关系报告.&lt;/p&gt;</description></item><item><title>Spring Cloud 入门</title><link>https://blog.jimersylee.com/posts/spring-cloud-%E5%85%A5%E9%97%A8/</link><pubDate>Fri, 28 Apr 2017 10:58:00 +0000</pubDate><guid>https://blog.jimersylee.com/posts/spring-cloud-%E5%85%A5%E9%97%A8/</guid><description>&lt;h1 id="spring-cloud-入门"&gt;Spring Cloud 入门&lt;/h1&gt;
&lt;p&gt;Spring Cloud Config:配置管理工具&lt;/p&gt;
&lt;p&gt;Spring Cloud Netflix:核心组件&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Eureka:服务治理组件&lt;/li&gt;
&lt;li&gt;Hystrix:容错管理组件&lt;/li&gt;
&lt;li&gt;Ribbon:客户端负载均衡的服务调用组件&lt;/li&gt;
&lt;li&gt;Feign:基于Ribbon和Hystrix的生命是服务调用组件&lt;/li&gt;
&lt;li&gt;Zuul:网关组件&lt;/li&gt;
&lt;li&gt;外部化配置组件&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Spring Cloud Bus:事件,消息总线&lt;/p&gt;
&lt;p&gt;Spring Cloud Cluster:针对Zookeeper,Redis,Hazelcast,Consul的选举算法和通用状态模式的实现&lt;/p&gt;
&lt;p&gt;Spring Cloud CloudFoundry:与Pivatal Cloudfoundy的整合支持&lt;/p&gt;
&lt;p&gt;Spring Cloud Consul:服务发现与配置管理工具&lt;/p&gt;
&lt;p&gt;Spring Cloud Stream:通过Redis,RabbitMQ和Kafka实现的消费微服务,可以通过简单的声明式模型来发送和接收消息&lt;/p&gt;
&lt;p&gt;Spring Cloud AWS:用于简化整合Amazon Web Service的组件&lt;/p&gt;
&lt;p&gt;Spring Cloud Security:安全工具包,提供在Zuul代理中对OAuth2客户端请求的中继器&lt;/p&gt;
&lt;p&gt;Spring Cloud Sleuth:Spring Cloud的应用分布式跟踪系统,可以完美整合Zipkin&lt;/p&gt;
&lt;p&gt;Spring Cloud Zookeeper:基于Zookeeper的服务发现与配置管理组件&lt;/p&gt;
&lt;p&gt;Spring Cloud Starters:Spring Cloud的基础组件,它是基于Spring Boot风格项目的基础依赖模块&lt;/p&gt;
&lt;p&gt;Spring Cloud CLI:用于在Groovy中快速创建Spring Cloud应用的Spring Boot CLI的插件&lt;/p&gt;</description></item><item><title>&lt;深入理解Java虚拟机&gt;学习笔记-第三章</title><link>https://blog.jimersylee.com/posts/%E6%B7%B1%E5%85%A5%E7%90%86%E8%A7%A3java%E8%99%9A%E6%8B%9F%E6%9C%BA%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0-%E7%AC%AC%E4%B8%89%E7%AB%A0/</link><pubDate>Sat, 20 Aug 2016 06:43:00 +0000</pubDate><guid>https://blog.jimersylee.com/posts/%E6%B7%B1%E5%85%A5%E7%90%86%E8%A7%A3java%E8%99%9A%E6%8B%9F%E6%9C%BA%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0-%E7%AC%AC%E4%B8%89%E7%AB%A0/</guid><description>&lt;h1 id="深入理解java虚拟机学习笔记-第三章"&gt;&amp;lt;深入理解Java虚拟机&amp;gt;学习笔记-第三章&lt;/h1&gt;
&lt;p&gt;项目地址: &lt;a href="http://github.com/jimersylee/javaStudy"&gt;http://github.com/jimersylee/javaStudy&lt;/a&gt;&lt;/p&gt;
&lt;h1 id="31概述"&gt;&lt;strong&gt;3.1概述&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;垃圾收集(Garbage Collection,GC),大部分人都把这项技术当做Java语言的伴生产物,事实上,1960年诞生于MIT的Lisp蚕食第一门真正使用内存动态分配和垃圾收集技术的语言&lt;/p&gt;
&lt;p&gt;GC的3件事情&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;那些内存需要回收&lt;/li&gt;
&lt;li&gt;什么时候回收&lt;/li&gt;
&lt;li&gt;如何回收&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;目前GC的技术已经相当成熟,为什么我们要了解&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;当需要排查各种内存溢出,内存泄露问题时&lt;/li&gt;
&lt;li&gt;当垃圾收集成为系统达到更高并发量瓶颈时&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="32对象已死吗"&gt;&lt;strong&gt;3.2对象已死吗&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;Java堆中存在对象实例,垃圾收集器在对堆进行回收前,第一件事就是要确定哪些对象还&amp;quot;活着&amp;quot;,哪些已经&amp;quot;死去&amp;quot;&lt;/p&gt;
&lt;h1 id="321-引用计数算法"&gt;&lt;strong&gt;3.2.1 引用计数算法&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;给对象中添加一个引用计数器:每当有一个地方引用它时,计数器加1;当引用失效时,计数器减1;任何时刻计数器为0的对象就是不可能再被使用的&lt;/p&gt;
&lt;p&gt;引用计数算法(Reference Counting)的实现简单,判定效率也高,例如FlashPlayer,Python都使用引用计数算法了内存管理,但是Java虚拟机中没有选用引用计数算法来管理内存,其实最重要的原因是它很难解决对象之间相互循环引用的问题&lt;/p&gt;
&lt;p&gt;testGC()方法,虽然两个对象已经不可能被访问,但是因为互相引用着,导致他们计数器都不为0,于是引用计数算法无法通知GC收集器来回收它们&lt;/p&gt;
&lt;p&gt;GC日志中包含了6747K-&amp;gt;416K(51200K),意味着虚拟机并没有因为这两个对象互相引用就不回收它们,这也从侧面说明虚拟机并不是通过引用计数算法来判断对象是否是存活的&lt;/p&gt;
&lt;h1 id="322-可达性分析算法"&gt;&lt;strong&gt;3.2.2 可达性分析算法&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;在主流的商用程序语言(Java,C#,甚至古老的Lisp)的主流实现中,都是通过可达性分析(Reachability Analysis)来判定对象是否存活的.这个算法的基本思路就是通过一系列的称为&amp;quot;GC Roots&amp;quot;的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链(Reference Chain),当一个对象到GC Roots没有任何引用链(用图论的话来说,就是从GC Root到这个对象不可达),则证明此对象是不可用的.&lt;/p&gt;
&lt;p&gt;在Java语言中,可作为GC Roots的对象包括下面几种:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;虚拟机栈(栈帧中的本地变量表)中引用的对象&lt;/li&gt;
&lt;li&gt;方法区中类静态属性引用的对象&lt;/li&gt;
&lt;li&gt;方法区中常量引用的对象&lt;/li&gt;
&lt;li&gt;本地方法栈中JNI(Native方法)引用的对象&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="323-再谈引用"&gt;&lt;strong&gt;3.2.3 再谈引用&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;jdk1.2后,对引用的概念进行了扩充&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;强引用 类型Object obj=new Object();这类的,只要强引用还在,垃圾收集器永远不会回收掉被引用的对象&lt;/li&gt;
&lt;li&gt;软引用 软引用用来描述一些还有用但并非必需的对象.在系统将要发生内存溢出异常之前,将会把这些对象列进回收范围内进行二次回收.如果这次回收还没有足够的内存,才会抛出内存溢出异常.在JDK1.2后,提供了SoftReference类来实现软引用.&lt;/li&gt;
&lt;li&gt;弱引用 弱引用也是用来描述非必需对象.当垃圾收集器工作时,无论当前内存是否足够,都会回收掉只被弱引用关联的对象.在JDK1.2后,提供了WeakReference类实现弱引用.&lt;/li&gt;
&lt;li&gt;虚引用 虚引用也称为幽灵引用或者幻影引用.一个对象是否有虚引用的存在,完全不会对其生存时间构成影响,也无法通过虚引用来获得一个对象实例.为一个对象设置虚引用是为了能在这个对象被回收时能收到系统通知.在JDK1.2后,提供了PhantomReference类实现虚引用&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="324-生存还是死亡"&gt;&lt;strong&gt;3.2.4 生存还是死亡&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;即使在可达性分析算法中不可达的对象,也并非是&amp;quot;非死不可&amp;quot;的,要宣告一个对象死亡,至少经历两次标记过程 代码清单3-2 一次对象自我拯救的演示&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;/**
* 此代码演示了两点
* 1.对象可以在被GC时自我拯救
* 2.这个自救机会只有一次
*
* @author jimersylee
*/publicclassFinalizeEscapeGC {
publicstatic FinalizeEscapeGC SAVE_HOOK =null;
publicvoidisAlive() {
System.out.println(&amp;#34;yes,i am still alive&amp;#34;);
}
@Override
protectedvoidfinalize() throws Throwable {
super.finalize();
System.out.println(&amp;#34;finalize method executed&amp;#34;);
FinalizeEscapeGC.SAVE_HOOK =this;
}
publicstaticvoidmain(String[] args) throws Throwable {
SAVE_HOOK =new FinalizeEscapeGC();
//对象第一次成功拯救自己演示//释放对象
SAVE_HOOK =null;
System.gc();
//因为finalize方法优先度低,所以暂停0.5秒等待它
Thread.sleep(500);
if (SAVE_HOOK !=null) {
SAVE_HOOK.isAlive();
}else {
System.out.println(&amp;#34;no,i am dead :(&amp;#34;);
}
//下面这段代码与上面的完全相同,但是这次自救却失败了
SAVE_HOOK =null;
System.gc();
//因为finalize方法优先度低,所以暂停0.5秒等待它
Thread.sleep(500);
if (SAVE_HOOK !=null) {
SAVE_HOOK.isAlive();
}else {
System.out.println(&amp;#34;no,i am dead :(&amp;#34;);
}
}
}
&lt;/code&gt;&lt;/pre&gt;&lt;h1 id="325-回收方法区"&gt;&lt;strong&gt;3.2.5 回收方法区&lt;/strong&gt;&lt;/h1&gt;</description></item><item><title>深入理解Java虚拟机 学习笔记-第二章</title><link>https://blog.jimersylee.com/posts/%E6%B7%B1%E5%85%A5%E7%90%86%E8%A7%A3java%E8%99%9A%E6%8B%9F%E6%9C%BA-%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0-%E7%AC%AC%E4%BA%8C%E7%AB%A0/</link><pubDate>Thu, 11 Aug 2016 10:54:00 +0000</pubDate><guid>https://blog.jimersylee.com/posts/%E6%B7%B1%E5%85%A5%E7%90%86%E8%A7%A3java%E8%99%9A%E6%8B%9F%E6%9C%BA-%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0-%E7%AC%AC%E4%BA%8C%E7%AB%A0/</guid><description>&lt;h1 id="深入理解java虚拟机学习笔记-第二章"&gt;&amp;lt;深入理解Java虚拟机&amp;gt;学习笔记-第二章&lt;/h1&gt;
&lt;p&gt;项目地址: &lt;a href="http://github.com/jimersylee/javaStudy"&gt;http://github.com/jimersylee/javaStudy&lt;/a&gt;&lt;/p&gt;
&lt;h1 id="21-概述"&gt;&lt;strong&gt;2.1 概述&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;内存管理领域&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;c,c++开发人员拥有最高权利,可以操作每一个对象,又需要维护每个对象的开始与销毁&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;java开发人员不需要为每一个对象写配对的delete/free代码,不容易出现内存泄露与内存溢出问题,不过,出现内存方面的问题,排查又是一项异常艰难的工作&lt;/p&gt;
&lt;h1 id="22运行时数据区域"&gt;&lt;strong&gt;2.2运行时数据区域&lt;/strong&gt;&lt;/h1&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;方法区Method Area&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;虚拟机栈VM Stack&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;本地方法栈Native Method Stack&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;堆 Heap&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;程序计数器 program Counter Register&lt;/p&gt;
&lt;h3 id="221-程序计数器"&gt;&lt;strong&gt;2.2.1 程序计数器&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;java虚拟机通过线程轮换来分配处理器执行时间,为了线程切换后能恢复到正确的执行位置,每条线程都需要一个独立的程序计数器,为&lt;em&gt;线程私有&lt;/em&gt;内存&lt;/p&gt;
&lt;h3 id="222-java虚拟机栈"&gt;&lt;strong&gt;2.2.2 Java虚拟机栈&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;与程序计数器一样,Java虚拟机栈也是线程私有的,它的生命周期与线程相同.&lt;/p&gt;
&lt;h3 id="223-本地方法栈"&gt;&lt;strong&gt;2.2.3 本地方法栈&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;本地方法栈为虚拟机使用到的Native方法服务&lt;/p&gt;
&lt;h3 id="224-java堆"&gt;&lt;strong&gt;2.2.4 Java堆&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Java堆(Heap)是Java虚拟机所管理的 内存中最大的一块,Java对是被所有线程共享的一块内存区域,在虚拟机启动时创建.此内存区域的唯一目的就是存放对象实例. Java堆是垃圾收集器管理的主要区域 现在的收集器基本采用分代收集算法&lt;/p&gt;
&lt;h3 id="java堆"&gt;&lt;strong&gt;Java堆&lt;/strong&gt;&lt;/h3&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;新生代&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;老年代 更细致&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Eden空间&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;From Survivor空间&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;To Survivor空间&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Java堆可以处于物理上不连续的空间中,只要逻辑上连续即可,既可以实现成固定大小的,也可以是可扩展的,通过 &lt;em&gt;-Xmx&lt;/em&gt; 和 &lt;em&gt;-Xms&lt;/em&gt;控制,如果堆中没有足够的内存完成实例分配,则报 &lt;em&gt;OutOfMemory&lt;/em&gt; 异常&lt;/p&gt;
&lt;h3 id="225"&gt;&lt;strong&gt;2.2.5&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;方法区与Java堆一样,是各个线程共享的内存区域,用于存放已被虚拟机加载的类信息,敞亮,静态变量,即时编译器编译后的代码等数据&lt;/p&gt;
&lt;p&gt;HotSpot上,方法区习惯性称为 &lt;em&gt;永久代(Permanent Generation)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;永久代有 &lt;em&gt;-XX:MaxPermSize&lt;/em&gt; 上限&lt;/p&gt;
&lt;h3 id="226-运行时常量池"&gt;&lt;strong&gt;2.2.6 运行时常量池&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;运行时常量池(Runtime Constant Pool)是方法区的一部分.用于存放编译期生成的各种字面量和符号引用.&lt;/p&gt;
&lt;p&gt;当常量池无法申请到内存报OutOfMemory异常&lt;/p&gt;
&lt;h3 id="直接内存"&gt;&lt;strong&gt;直接内存&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;JDK1.4中新加入NIO(New Input/Output)类,引入了一种基于通道(Channel)与缓冲区(Buffer)的I/O方式,它可以使用Native函数库直接分配堆外内存,然后通过一个存储在Java堆中的DirectByteBuffer对象作为这块内存的引用记性操作. 作用:提高性能 直接内存不收Java堆大小的限制,但是受本机总内存限制.除了设置 -Xmx等参数信息,也要注意直接内存&lt;/p&gt;</description></item><item><title>我的Linux桌面环境配置与必备软件</title><link>https://blog.jimersylee.com/posts/%E6%88%91%E7%9A%84linux%E6%A1%8C%E9%9D%A2%E7%8E%AF%E5%A2%83%E9%85%8D%E7%BD%AE%E4%B8%8E%E5%BF%85%E5%A4%87%E8%BD%AF%E4%BB%B6/</link><pubDate>Tue, 05 Jul 2016 10:37:00 +0000</pubDate><guid>https://blog.jimersylee.com/posts/%E6%88%91%E7%9A%84linux%E6%A1%8C%E9%9D%A2%E7%8E%AF%E5%A2%83%E9%85%8D%E7%BD%AE%E4%B8%8E%E5%BF%85%E5%A4%87%E8%BD%AF%E4%BB%B6/</guid><description>&lt;h1 id="我的linux桌面环境配置与必备软件"&gt;我的Linux桌面环境配置与必备软件&lt;/h1&gt;
&lt;h1 id="idea"&gt;&lt;strong&gt;Idea&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;主题 Monokai_2 字体 YaHei Consolas Hybrid&lt;/p&gt;
&lt;h1 id="phpstorm"&gt;&lt;strong&gt;phpstorm&lt;/strong&gt;&lt;/h1&gt;
&lt;h1 id="sublime"&gt;&lt;strong&gt;sublime&lt;/strong&gt;&lt;/h1&gt;
&lt;h1 id="jdk"&gt;&lt;strong&gt;jdk&lt;/strong&gt;&lt;/h1&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;设置环境变量
vim /etc/profile
JAVA_HOME=/opt/jdk1.8.0_141
PATH=$JAVA_HOME/bin:$PATH
CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
export JAVA_HOME
export PATH
export CLASSPATH
source /etc/profile
&lt;/code&gt;&lt;/pre&gt;&lt;h1 id="mysql-workbench"&gt;&lt;strong&gt;mysql workbench&lt;/strong&gt;&lt;/h1&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;apt install mysql-workbench
&lt;/code&gt;&lt;/pre&gt;&lt;h1 id="maven"&gt;&lt;strong&gt;maven&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;java包管理软件&lt;/p&gt;
&lt;h1 id="shadowsocks必备梯子"&gt;&lt;strong&gt;shadowsocks,必备梯子&lt;/strong&gt;&lt;/h1&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;sudo apt install shadowsocks-qt5
&lt;/code&gt;&lt;/pre&gt;&lt;h1 id="tomcat"&gt;&lt;strong&gt;tomcat&lt;/strong&gt;&lt;/h1&gt;
&lt;h1 id="redis-desktop-manager"&gt;&lt;strong&gt;redis-desktop-manager&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;redis跨平台客户端 &lt;a href="http://download.csdn.net/download/shuai825644975/9854471"&gt;下载地址&lt;/a&gt;&lt;/p&gt;
&lt;h1 id="配置lamp环境"&gt;&lt;strong&gt;配置lamp环境&lt;/strong&gt;&lt;/h1&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;安装xammp
到/opt
将bin路径加入path
vim /etc/profile
export $PTAH=$PATH:/opt/lampp/bin
这样就可以直接使用pecl来安装扩展了
pecl search redis
pecl install redis
&lt;/code&gt;&lt;/pre&gt;&lt;h1 id="nodejs-npm"&gt;&lt;strong&gt;nodejs npm&lt;/strong&gt;&lt;/h1&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;apt install nodejs
apt install npm
设置淘宝镜像
npm config set registry https://registry.npm.taobao.org
&lt;/code&gt;&lt;/pre&gt;&lt;h1 id="编译环境组件"&gt;&lt;strong&gt;编译环境组件&lt;/strong&gt;&lt;/h1&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;sudo apt install build-essential
&lt;/code&gt;&lt;/pre&gt;&lt;h1 id="nginx"&gt;&lt;strong&gt;Nginx&lt;/strong&gt;&lt;/h1&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;编译安装nginx
下载源码
tar zxvf nginx-x.tar
cd nginx
./configure \
--prefix=/usr \
--sbin-path=/usr/sbin/nginx \
--conf-path=/etc/nginx/nginx.conf \
--error-log-path=/var/log/nginx/error.log \
--pid-path=/var/run/nginx/nginx.pid \
--user=jimersylee \
--group=jimersylee \
--with-http_ssl_module \
--with-http_flv_module \
--with-http_gzip_static_module \
--http-log-path=/var/log/nginx/access.log \
--http-client-body-temp-path=/var/tmp/nginx/client \
--http-proxy-temp-path=/var/tmp/nginx/proxy \
--http-fastcgi-temp-path=/var/tmp/nginx/fcgi \
--with-http_stub_status_module
&lt;/code&gt;&lt;/pre&gt;</description></item><item><title>为域名配置免费SSL证书</title><link>https://blog.jimersylee.com/posts/%E4%B8%BA%E5%9F%9F%E5%90%8D%E9%85%8D%E7%BD%AE%E5%85%8D%E8%B4%B9ssl%E8%AF%81%E4%B9%A6/</link><pubDate>Sun, 08 May 2016 10:41:00 +0000</pubDate><guid>https://blog.jimersylee.com/posts/%E4%B8%BA%E5%9F%9F%E5%90%8D%E9%85%8D%E7%BD%AE%E5%85%8D%E8%B4%B9ssl%E8%AF%81%E4%B9%A6/</guid><description>&lt;h1 id="为域名配置免费ssl证书"&gt;为域名配置免费SSL证书&lt;/h1&gt;
&lt;h1 id="nginx配置ssl"&gt;&lt;strong&gt;Nginx配置ssl&lt;/strong&gt;&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;腾讯云申请证书&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" src="http://jimersyleetest.qiniudn.com/%E7%94%B3%E8%AF%B7%E8%AF%81%E4%B9%A6.png"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" src="http://jimersyleetest.qiniudn.com/%E9%AA%8C%E8%AF%81%E8%AF%81%E4%B9%A6.png"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" src="http://jimersyleetest.qiniudn.com/%E6%B7%BB%E5%8A%A0%E8%AE%B0%E5%BD%95.png"&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;阿里云域名解析验证证书&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" src="http://jimersyleetest.qiniudn.com/%E8%A7%A3%E6%9E%90%E8%AE%BE%E7%BD%AE.png"&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;安装证书&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;下载证书&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;上传配置证书&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;#将本地的jenkins.jimersylee.com.zip上传至jimersylee.com这个机子上的/data/ssl_cert目录scp jenkins.jimersylee.com.zip root@jimersylee.com:/data/ssl_cert
#登录主机解压文件
ssh root@jimersylee.com
cd /data/ssl_cert
unzip jenkins.jimersylee.com.zip
#各种web服务器的证书就解压完成了,然后去配置Nginx
[root@VM_77_132_centos ssl_cert]# tree
.
├── Apache
│   ├── 1_root_bundle.crt
│   ├── 2_blog.jimersylee.com.crt
│   ├── 2_jenkins.jimersylee.com.crt
│   ├── 2_jimersylee.com.crt
│   ├── 3_blog.jimersylee.com.key
│   ├── 3_jenkins.jimersylee.com.key
│   └── 3_jimersylee.com.key
├── blog.jimersylee.com.cert.zip
├── IIS
│   ├── blog.jimersylee.com.pfx
│   ├── jenkins.jimersylee.com.pfx
│   ├── jimersylee.com.pfx
│   └── keystorePass.txt
├── jenkins.jimersylee.com.zip
├── jimersylee.com.cert.zip
├── Nginx
│   ├── 1_blog.jimersylee.com_bundle.crt
│   ├── 1_jenkins.jimersylee.com_bundle.crt
│   ├── 1_jimersylee.com_bundle.crt
│   ├── 2_blog.jimersylee.com.key
│   ├── 2_jenkins.jimersylee.com.key
│   └── 2_jimersylee.com.key
└── Tomcat
├── jenkins.jimersylee.com.jks
└── keystorePass.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;nginx配置&lt;/p&gt;</description></item><item><title>机器学习实战-学习笔记之Logistic</title><link>https://blog.jimersylee.com/posts/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0%E5%AE%9E%E6%88%98-%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%E4%B9%8Blogistic/</link><pubDate>Thu, 05 May 2016 10:28:00 +0000</pubDate><guid>https://blog.jimersylee.com/posts/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0%E5%AE%9E%E6%88%98-%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%E4%B9%8Blogistic/</guid><description>&lt;p&gt;项目地址:&lt;a href="http://github.com/jimersylee/MachineLearningAction"&gt;http://github.com/jimersylee/MachineLearningAction&lt;/a&gt;&lt;/p&gt;
&lt;h1 id="logistic回归"&gt;&lt;strong&gt;Logistic回归&lt;/strong&gt;&lt;/h1&gt;
&lt;h1 id="本章内容"&gt;&lt;strong&gt;本章内容&lt;/strong&gt;&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Sigmoid函数和Logistic回归分类器&lt;/li&gt;
&lt;li&gt;最优化理论初步&lt;/li&gt;
&lt;li&gt;梯度下降最优化算法&lt;/li&gt;
&lt;li&gt;数据中的缺失项处理&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="最优化算法"&gt;&lt;strong&gt;最优化算法&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;比如如何在最短时间内从A点到B点?如何投入最少的工作量获得最大的收益&lt;/p&gt;
&lt;h1 id="logistic回归的一般过程"&gt;&lt;strong&gt;Logistic回归的一般过程&lt;/strong&gt;&lt;/h1&gt;
&lt;ol&gt;
&lt;li&gt;收集数据:采用任意方法收集数据&lt;/li&gt;
&lt;li&gt;准备数据:由于需要进行距离计算,因此要求数据类型为数值型.另外,结构化数据格式则最佳&lt;/li&gt;
&lt;li&gt;分析数据:采用任意方法对数据进行分析&lt;/li&gt;
&lt;li&gt;训练算法:大部分时间将将用于测试,训练的目的是为了找到最佳的分类回归系数&lt;/li&gt;
&lt;li&gt;测试算法:一旦训练步骤完成,分类将会很快&lt;/li&gt;
&lt;li&gt;使用算法:首先,我们需要输入一些数据,并将其转换成对应的结构化数值;接着,基于训练好的回归系数就可以对这些数值进行简单的回归计算,判定他们属于那个类别了;在这之后,我们就可以在输出的类别上做一些其他分析工作&lt;/li&gt;
&lt;/ol&gt;
&lt;h1 id="基于logistic回归和sigmoid函数的分类"&gt;&lt;strong&gt;基于Logistic回归和Sigmoid函数的分类&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;优点:计算代价不高,易于理解和实现 缺点:容易欠拟合,分类精度可能不高 适用数据类型:数值型和标称型数据&lt;/p&gt;
&lt;p&gt;我们想要的函数,能够接受所有的输入然后预测出类别. 使用单位阶跃函数 Sigmoid函数 f(z)=1/(1+e^-z)&lt;/p&gt;
&lt;h1 id="训练算法随机梯度上升"&gt;&lt;strong&gt;训练算法:随机梯度上升&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;梯度上升算法在每次更新回归系数时都需要遍历整个数据集,当数据集增加时,计算复杂度就太高了. 改进方法是一次禁用一个样本点来更新回归系数,该方法成为随机梯度上升算法.&lt;/p&gt;
&lt;h1 id="报错未解决"&gt;&lt;strong&gt;报错,未解决&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;weights = weights + alpha &lt;em&gt;error&lt;/em&gt; dataMatIn[i] ValueError: operands could not be broadcast together with shapes (3,) (0,)&lt;/p&gt;
&lt;h1 id="示例从疝气病预测兵马的死亡率"&gt;&lt;strong&gt;示例:从疝气病预测兵马的死亡率&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;本节使用Logistic回归来预测患有疝气病的马的存货问题 样本数据包含368个样本和28个特征 &lt;em&gt;有30%的数据的值是缺失的&lt;/em&gt;.下面将介绍如何处理数据集中的数据确实问题,然后再用Logistic回归和随机梯度上升算法来预测病马的生死&lt;/p&gt;
&lt;h1 id="准备数据"&gt;&lt;strong&gt;准备数据&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;数据缺失是个麻烦的问题.如何解决&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;使用可用特征的均值来填补缺失值&lt;/li&gt;
&lt;li&gt;使用特殊值来填补缺失值,如-1&lt;/li&gt;
&lt;li&gt;忽略有缺失值的样本&lt;/li&gt;
&lt;li&gt;使用相似样本的均值填补缺失值&lt;/li&gt;
&lt;li&gt;使用另外的机器学习算法来预测缺失值&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;from&lt;/span&gt; numpyimport &lt;span style="color:#f92672"&gt;*&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; matplotlib.pyplotas plt
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;defloadDataSet():
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; 载入测试数据
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; :return:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; dataMat &lt;span style="color:#f92672"&gt;=&lt;/span&gt; []
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; labelMat &lt;span style="color:#f92672"&gt;=&lt;/span&gt; []
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; fr &lt;span style="color:#f92672"&gt;=&lt;/span&gt; open(&lt;span style="color:#e6db74"&gt;&amp;#39;testSet.txt&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; linein fr&lt;span style="color:#f92672"&gt;.&lt;/span&gt;readlines():
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; lineArr &lt;span style="color:#f92672"&gt;=&lt;/span&gt; line&lt;span style="color:#f92672"&gt;.&lt;/span&gt;strip()&lt;span style="color:#f92672"&gt;.&lt;/span&gt;split()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; dataMat&lt;span style="color:#f92672"&gt;.&lt;/span&gt;append([&lt;span style="color:#ae81ff"&gt;1.0&lt;/span&gt;, float(lineArr[&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;]), float(lineArr[&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;])])&lt;span style="color:#75715e"&gt;# 为了计算方便,将X0设置为1.0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; labelMat&lt;span style="color:#f92672"&gt;.&lt;/span&gt;append(int(lineArr[&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;]))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; dataMat, labelMat
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;defsigmoid(inX):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; Sigmoid函数,单位阶跃函数
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; :param inX:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; :return:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1.0&lt;/span&gt; &lt;span style="color:#f92672"&gt;/&lt;/span&gt; (&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt; exp(&lt;span style="color:#f92672"&gt;-&lt;/span&gt;inX))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;defgradAscent(dataMatIn, classLabels):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; 梯度上升算法
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; :param dataMatIn: 输入的数据矩阵,存放的100*3的矩阵
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; :param classLabels: 输入的数据类别矩阵
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; :return:返回训练好的迭代次数
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 转换为NumPy矩阵类型&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; dataMatrix &lt;span style="color:#f92672"&gt;=&lt;/span&gt; mat(dataMatIn)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; labelMat &lt;span style="color:#f92672"&gt;=&lt;/span&gt; mat(classLabels)&lt;span style="color:#f92672"&gt;.&lt;/span&gt;transpose()&lt;span style="color:#75715e"&gt;# 初始为1*100的行向量,为了便于矩阵运算,使用transpose转置为列向量100*1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; m, n &lt;span style="color:#f92672"&gt;=&lt;/span&gt; shape(dataMatrix)&lt;span style="color:#75715e"&gt;# 得到矩阵大小&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; alpha &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0.001&lt;/span&gt;&lt;span style="color:#75715e"&gt;# 目标移动的步长&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; maxCycles &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;500&lt;/span&gt;&lt;span style="color:#75715e"&gt;# 最大迭代次数&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; weights &lt;span style="color:#f92672"&gt;=&lt;/span&gt; ones((n, &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; kin range(maxCycles):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 矩阵相乘,下面两行,计算真实类别与预测类别的差值,接下来就是按照该差值的方向调整回归系数&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; h &lt;span style="color:#f92672"&gt;=&lt;/span&gt; sigmoid(dataMatrix &lt;span style="color:#f92672"&gt;*&lt;/span&gt; weights)&lt;span style="color:#75715e"&gt;# 代表的不是一次乘积计算,事实上该运算包含了300次的乘积,变量h不是一个数,而是一个列向量,100&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; error &lt;span style="color:#f92672"&gt;=&lt;/span&gt; (labelMat &lt;span style="color:#f92672"&gt;-&lt;/span&gt; h)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; weights &lt;span style="color:#f92672"&gt;=&lt;/span&gt; weights &lt;span style="color:#f92672"&gt;+&lt;/span&gt; alpha &lt;span style="color:#f92672"&gt;*&lt;/span&gt; dataMatrix&lt;span style="color:#f92672"&gt;.&lt;/span&gt;transpose() &lt;span style="color:#f92672"&gt;*&lt;/span&gt; error
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; weights
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;defstocGradAscent0(dataMatIn, classLabels):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; m, n &lt;span style="color:#f92672"&gt;=&lt;/span&gt; shape(dataMatIn)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; alpha &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0.01&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; weights &lt;span style="color:#f92672"&gt;=&lt;/span&gt; ones(n)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; iin range(m):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; h &lt;span style="color:#f92672"&gt;=&lt;/span&gt; sigmoid(sum(dataMatIn[i] &lt;span style="color:#f92672"&gt;*&lt;/span&gt; weights))&lt;span style="color:#75715e"&gt;# h是向量&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; error &lt;span style="color:#f92672"&gt;=&lt;/span&gt; classLabels[i] &lt;span style="color:#f92672"&gt;-&lt;/span&gt; h&lt;span style="color:#75715e"&gt;# error是向量&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; weights &lt;span style="color:#f92672"&gt;=&lt;/span&gt; weights &lt;span style="color:#f92672"&gt;+&lt;/span&gt; alpha &lt;span style="color:#f92672"&gt;*&lt;/span&gt; error &lt;span style="color:#f92672"&gt;*&lt;/span&gt; dataMatIn[i]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; weights
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;defstocGradAscent1(dataMatIn, classLabels, numIter&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;150&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; 改进的随机梯度上升算法
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; :param dataMatIn:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; :param classLabels:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; :param numIter:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; :return:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; m, n &lt;span style="color:#f92672"&gt;=&lt;/span&gt; shape(dataMatIn)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; weights &lt;span style="color:#f92672"&gt;=&lt;/span&gt; ones(n)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; jin range(numIter):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; dataIndex &lt;span style="color:#f92672"&gt;=&lt;/span&gt; range(m)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; iin range(m):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; alpha &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt; &lt;span style="color:#f92672"&gt;/&lt;/span&gt; (&lt;span style="color:#ae81ff"&gt;1.0&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt; j &lt;span style="color:#f92672"&gt;+&lt;/span&gt; i) &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0.01&lt;/span&gt;&lt;span style="color:#75715e"&gt;# alpha每次迭代时需要调整&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; randIndex &lt;span style="color:#f92672"&gt;=&lt;/span&gt; int(random&lt;span style="color:#f92672"&gt;.&lt;/span&gt;uniform(&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, len(dataIndex)))&lt;span style="color:#75715e"&gt;# 随机选取更新&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; h &lt;span style="color:#f92672"&gt;=&lt;/span&gt; sigmoid(sum(dataMatIn[randIndex] &lt;span style="color:#f92672"&gt;*&lt;/span&gt; weights))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; error &lt;span style="color:#f92672"&gt;=&lt;/span&gt; classLabels[randIndex] &lt;span style="color:#f92672"&gt;-&lt;/span&gt; h
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; weights &lt;span style="color:#f92672"&gt;=&lt;/span&gt; weights &lt;span style="color:#f92672"&gt;+&lt;/span&gt; alpha &lt;span style="color:#f92672"&gt;*&lt;/span&gt; error &lt;span style="color:#f92672"&gt;*&lt;/span&gt; dataMatIn[randIndex]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;del&lt;/span&gt; (dataIndex[randIndex])
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; weights
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;defplotBestFit(weights):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; 画出数据集和Logistic回归最佳拟合直线的函数
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; :param weights:系数
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; :return:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; weights &lt;span style="color:#f92672"&gt;=&lt;/span&gt; weights&lt;span style="color:#f92672"&gt;.&lt;/span&gt;getA()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; dataMat, labelMat &lt;span style="color:#f92672"&gt;=&lt;/span&gt; loadDataSet()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; dataArr &lt;span style="color:#f92672"&gt;=&lt;/span&gt; array(dataMat)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; n &lt;span style="color:#f92672"&gt;=&lt;/span&gt; shape(dataArr)[&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; xcord1 &lt;span style="color:#f92672"&gt;=&lt;/span&gt; []
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ycord1 &lt;span style="color:#f92672"&gt;=&lt;/span&gt; []
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; xcord2 &lt;span style="color:#f92672"&gt;=&lt;/span&gt; []
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ycord2 &lt;span style="color:#f92672"&gt;=&lt;/span&gt; []
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; iin range(n):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; int(labelMat[i]) &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; xcord1&lt;span style="color:#f92672"&gt;.&lt;/span&gt;append(dataArr[i, &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ycord1&lt;span style="color:#f92672"&gt;.&lt;/span&gt;append(dataArr[i, &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;else&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; xcord2&lt;span style="color:#f92672"&gt;.&lt;/span&gt;append(dataArr[i, &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ycord2&lt;span style="color:#f92672"&gt;.&lt;/span&gt;append(dataArr[i, &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; fig &lt;span style="color:#f92672"&gt;=&lt;/span&gt; plt&lt;span style="color:#f92672"&gt;.&lt;/span&gt;figure()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ax &lt;span style="color:#f92672"&gt;=&lt;/span&gt; fig&lt;span style="color:#f92672"&gt;.&lt;/span&gt;add_subplot(&lt;span style="color:#ae81ff"&gt;111&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ax&lt;span style="color:#f92672"&gt;.&lt;/span&gt;scatter(xcord1, ycord1, s&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;30&lt;/span&gt;, c&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;red&amp;#39;&lt;/span&gt;, marker&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;s&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ax&lt;span style="color:#f92672"&gt;.&lt;/span&gt;scatter(xcord2, ycord2, s&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;30&lt;/span&gt;, c&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;green&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; x &lt;span style="color:#f92672"&gt;=&lt;/span&gt; arange(&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;3.0&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;3.0&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0.1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; y &lt;span style="color:#f92672"&gt;=&lt;/span&gt; (&lt;span style="color:#f92672"&gt;-&lt;/span&gt;weights[&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;] &lt;span style="color:#f92672"&gt;-&lt;/span&gt; weights[&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;] &lt;span style="color:#f92672"&gt;*&lt;/span&gt; x) &lt;span style="color:#f92672"&gt;/&lt;/span&gt; weights[&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ax&lt;span style="color:#f92672"&gt;.&lt;/span&gt;plot(x, y)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; plt&lt;span style="color:#f92672"&gt;.&lt;/span&gt;xlabel(&lt;span style="color:#e6db74"&gt;&amp;#34;X1&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; plt&lt;span style="color:#f92672"&gt;.&lt;/span&gt;ylabel(&lt;span style="color:#e6db74"&gt;&amp;#34;X2&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; plt&lt;span style="color:#f92672"&gt;.&lt;/span&gt;show()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;defclassifyVector(inX, weights):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; prob &lt;span style="color:#f92672"&gt;=&lt;/span&gt; sigmoid(sum(inX &lt;span style="color:#f92672"&gt;*&lt;/span&gt; weights))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; prob &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0.5&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1.0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;else&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0.0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;defcolicTest():
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; 疝气病马死亡分类测试
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; :return:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; frTrain &lt;span style="color:#f92672"&gt;=&lt;/span&gt; open(&lt;span style="color:#e6db74"&gt;&amp;#39;horseColicTraining.txt&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; frTest &lt;span style="color:#f92672"&gt;=&lt;/span&gt; open(&lt;span style="color:#e6db74"&gt;&amp;#39;horseColicTest.txt&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; trainingSet &lt;span style="color:#f92672"&gt;=&lt;/span&gt; []
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; trainingLabels &lt;span style="color:#f92672"&gt;=&lt;/span&gt; []
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; linein frTrain&lt;span style="color:#f92672"&gt;.&lt;/span&gt;readlines():
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; currLine &lt;span style="color:#f92672"&gt;=&lt;/span&gt; line&lt;span style="color:#f92672"&gt;.&lt;/span&gt;strip()&lt;span style="color:#f92672"&gt;.&lt;/span&gt;split(&lt;span style="color:#e6db74"&gt;&amp;#39;&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\t&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; lineArr &lt;span style="color:#f92672"&gt;=&lt;/span&gt; []
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; iin range(&lt;span style="color:#ae81ff"&gt;21&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; lineArr&lt;span style="color:#f92672"&gt;.&lt;/span&gt;append(float(currLine[i]))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; trainingSet&lt;span style="color:#f92672"&gt;.&lt;/span&gt;append(lineArr)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; trainingLabels&lt;span style="color:#f92672"&gt;.&lt;/span&gt;append(float(currLine[i]))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; trainWeights &lt;span style="color:#f92672"&gt;=&lt;/span&gt; stocGradAscent1(array(trainingSet), trainingLabels, &lt;span style="color:#ae81ff"&gt;500&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; errorCount &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; numTestVec &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0.0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; linein frTest&lt;span style="color:#f92672"&gt;.&lt;/span&gt;readlines():
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; numTestVec &lt;span style="color:#f92672"&gt;+=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1.0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; currLine &lt;span style="color:#f92672"&gt;=&lt;/span&gt; line&lt;span style="color:#f92672"&gt;.&lt;/span&gt;strip()&lt;span style="color:#f92672"&gt;.&lt;/span&gt;split(&lt;span style="color:#e6db74"&gt;&amp;#39;&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\t&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; lineArr &lt;span style="color:#f92672"&gt;=&lt;/span&gt; []
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; iin range(&lt;span style="color:#ae81ff"&gt;21&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; lineArr&lt;span style="color:#f92672"&gt;.&lt;/span&gt;append(float(currLine[i]))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; int(classifyVector(array(lineArr), trainWeights)) &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; int(currLine[&lt;span style="color:#ae81ff"&gt;21&lt;/span&gt;]):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; errorCount &lt;span style="color:#f92672"&gt;+=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; errorRate &lt;span style="color:#f92672"&gt;=&lt;/span&gt; (float(errorCount &lt;span style="color:#f92672"&gt;/&lt;/span&gt; numTestVec))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;print &lt;span style="color:#e6db74"&gt;&amp;#34;the error rate of this test is: &lt;/span&gt;&lt;span style="color:#e6db74"&gt;%f&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;%&lt;/span&gt; errorRate
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; errorRate
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;defmultiTest():
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; numTests &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; errorSum &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0.0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; kin range(numTests):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; errorSum &lt;span style="color:#f92672"&gt;+=&lt;/span&gt; colicTest()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;print &lt;span style="color:#e6db74"&gt;&amp;#34;after &lt;/span&gt;&lt;span style="color:#e6db74"&gt;%d&lt;/span&gt;&lt;span style="color:#e6db74"&gt; iterations the average error rate is: &lt;/span&gt;&lt;span style="color:#e6db74"&gt;%f&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;%&lt;/span&gt; (numTests, errorSum &lt;span style="color:#f92672"&gt;/&lt;/span&gt; float(numTests))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;deftestCal():
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; dataArr, labelMat &lt;span style="color:#f92672"&gt;=&lt;/span&gt; loadDataSet()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; weights &lt;span style="color:#f92672"&gt;=&lt;/span&gt; gradAscent(dataArr, labelMat)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;print weights
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; 得到一组回归系数,它确定了不同类别数据之间的分割线
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; [[ 4.12414349]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; [ 0.48007329]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; [-0.6168482 ]]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;deftestGradAscent():
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; 测试梯度上升算法,画图
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; :return:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; dataArr, labelMat &lt;span style="color:#f92672"&gt;=&lt;/span&gt; loadDataSet()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; weights &lt;span style="color:#f92672"&gt;=&lt;/span&gt; gradAscent(dataArr, labelMat)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; plotBestFit(weights)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;deftestStocGradAscent0():
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; 测试随机梯度上升算法,画图
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; :return:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; dataArr, labelMat &lt;span style="color:#f92672"&gt;=&lt;/span&gt; loadDataSet()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; weights &lt;span style="color:#f92672"&gt;=&lt;/span&gt; stocGradAscent0(dataArr, labelMat)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; plotBestFit(weights)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;deftestStocGradAscent1():
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; 测试随机梯度上升算法,画图
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; :return:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; dataArr, labelMat &lt;span style="color:#f92672"&gt;=&lt;/span&gt; loadDataSet()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; weights &lt;span style="color:#f92672"&gt;=&lt;/span&gt; stocGradAscent1(dataArr, labelMat)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; plotBestFit(weights)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# testCal()#testGradAscent()# testStocGradAscent0()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;multiTest()
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>机器学习实战 学习笔记之KNN-约会数据识别</title><link>https://blog.jimersylee.com/posts/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0%E5%AE%9E%E6%88%98-%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%E4%B9%8Bknn-%E7%BA%A6%E4%BC%9A%E6%95%B0%E6%8D%AE%E8%AF%86%E5%88%AB/</link><pubDate>Wed, 04 May 2016 10:24:00 +0000</pubDate><guid>https://blog.jimersylee.com/posts/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0%E5%AE%9E%E6%88%98-%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%E4%B9%8Bknn-%E7%BA%A6%E4%BC%9A%E6%95%B0%E6%8D%AE%E8%AF%86%E5%88%AB/</guid><description>&lt;h1 id="机器学习实战学习笔记之knn-约会数据识别"&gt;&amp;lt;机器学习实战&amp;gt;学习笔记之KNN-约会数据识别&lt;/h1&gt;
&lt;p&gt;项目地址:&lt;a href="http://github.com/jimersylee/MachineLearningAction"&gt;http://github.com/jimersylee/MachineLearningAction&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# -*- coding: utf-8 -*-&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;约会数据kNN
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;from numpyimport *
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;import matplotlib.pyplotas plt
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;import operator
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;defclassify0(inX, dataSet, labels, k):
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; dataSetSize = dataSet.shape[0]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; diffMat = tile(inX, (dataSetSize, 1)) - dataSet
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; sqDiffMat = diffMat ** 2
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; sqDistances = sqDiffMat.sum(axis=1)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; distances = sqDistances ** 0.5
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; sortedDistIndicies = distances.argsort()
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; classCount = &lt;/span&gt;&lt;span style="color:#e6db74"&gt;{}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;for iin range(k):
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; voteIlabel = labels[sortedDistIndicies[i]]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; sortedClassCount = sorted(classCount.iteritems(), key=operator.itemgetter(1), reverse=True)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;return sortedClassCount[0][0]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;deffile2matrix(filename):
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; fr = open(filename)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; numberOfLines = len(fr.readlines())# get the number of lines in the file
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; returnMat = zeros((numberOfLines, 3))# prepare matrix to return
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; classLabelVector = []# prepare labels return
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; fr = open(filename)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; index = 0
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;for linein fr.readlines():
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; line = line.strip()
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; listFromLine = line.split(&amp;#39;&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\t&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; returnMat[index, :] = listFromLine[0:3]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; classLabelVector.append(int(listFromLine[-1]))
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; index += 1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;return returnMat, classLabelVector
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;defautoNorm(dataSet):
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 归一化数值
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 因为计算距离的时候,差值最大的属性对计算结果的影响最大,如果对于此数据,我们认为权重一样,则需要将数据进行处理,将数值归一化
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 将属性的取值范围处理为0到1或者&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;到1,使用下面的公式
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; newValue&lt;span style="color:#f92672"&gt;=&lt;/span&gt;(oldValue&lt;span style="color:#f92672"&gt;-&lt;/span&gt;min)&lt;span style="color:#f92672"&gt;/&lt;/span&gt;(max&lt;span style="color:#f92672"&gt;-&lt;/span&gt;min)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; :param dataSet:矩阵
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; :&lt;span style="color:#66d9ef"&gt;return&lt;/span&gt;:normDataSet:归一化后的矩阵
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; range:取值范围
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; minVals:最小值
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; minVals = dataSet.min(0)# 0代表第一列,取得第一列最小值
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; maxVals = dataSet.max(0)# 取得第一列最大值
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; ranges = maxVals - minVals# 可能的取值范围
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; normDataSet = zeros(shape(dataSet))# 创建新的返回矩阵
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; m = dataSet.shape[0]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; normDataSet = dataSet - tile(minVals, (m, 1))
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; normDataSet = normDataSet / tile(ranges, (m, 1))# element wise dividereturn normDataSet, ranges, minVals
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;defdatingClassTest():
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; hoRatio = 0.50# hold out 10%
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; datingDataMat, datingLabels = file2matrix(&amp;#39;datingData/datingTestSet2.txt&amp;#39;)# load data setfrom file
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; normMat, ranges, minVals = autoNorm(datingDataMat)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; m = normMat.shape[0]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; numTestVecs = int(m * hoRatio)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; errorCount = 0.0
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;for iin range(numTestVecs):
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; classifierResult = classify0(normMat[i, :], normMat[numTestVecs:m, :], datingLabels[numTestVecs:m], 3)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;print &amp;#34;the classifier came back with: &lt;/span&gt;&lt;span style="color:#e6db74"&gt;%d&lt;/span&gt;&lt;span style="color:#e6db74"&gt;, the real answer is: &lt;/span&gt;&lt;span style="color:#e6db74"&gt;%d&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34; % (classifierResult, datingLabels[i])
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;if (classifierResult != datingLabels[i]): errorCount += 1.0
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;print &amp;#34;the total error rate is: &lt;/span&gt;&lt;span style="color:#e6db74"&gt;%f&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34; % (errorCount / float(numTestVecs))
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;print errorCount
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;defshowNormal():
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 最基本散点图
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 没有样本类别标签的约会数据散点图&lt;span style="color:#f92672"&gt;.&lt;/span&gt;难以辨识途中的点究竟属于那个样本分类
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; :&lt;span style="color:#66d9ef"&gt;return&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; datingDataMat, datingLables = file2matrix(&amp;#39;datingData/datingTestSet2.txt&amp;#39;)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; fig = plt.figure()
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; ax = fig.add_subplot(111)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; ax.scatter(datingDataMat[:, 1], datingDataMat[:, 2])
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; plt.xlabel(&amp;#34;Percentage of Time Spent Playing Video Games&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; plt.ylabel(&amp;#34;Liters of Icc Cream Consumed Per Week&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; plt.show()
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;defshowLable():
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 带有样本分类标签的约会数据散点图
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 虽然能够比较容易区分数据点丛书类别,但依然很那根据这张图得出结论性信息
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; :&lt;span style="color:#66d9ef"&gt;return&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; datingDataMat, datingLables = file2matrix(&amp;#39;datingData/datingTestSet2.txt&amp;#39;)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; fig = plt.figure()
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; ax = fig.add_subplot(111)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; ax.scatter(datingDataMat[:, 1], datingDataMat[:, 2], 15.0 * array(datingLables), 15.0 * array(datingLables))
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; ax.axis([-2, 25, -0.2, 2.0])
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; plt.xlabel(&amp;#34;Percentage of Time Spent Playing Video Games&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; plt.ylabel(&amp;#34;Liters of Icc Cream Consumed Per Week&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; plt.show()
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;defshowClass():
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 显示不同的分类
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 标识了三个不同的样本分类区域,具有不同爱好的人其类别区域也不同
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 每年赢得的飞行常客里程数与玩游戏视频游戏所占百分比的约会数据散点图
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 约会数据有三个分类标签,通过途中展示的两个特征更容易区分数据点从属的类别
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; :&lt;span style="color:#66d9ef"&gt;return&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; n = 1000# number of points to create
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; xcord1 = [];
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; ycord1 = []
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; xcord2 = [];
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; ycord2 = []
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; xcord3 = [];
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; ycord3 = []
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; markers = []
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; colors = []
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; fw = open(&amp;#39;datingData/datingTestSet.txt&amp;#39;, &amp;#39;w&amp;#39;)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;for iin range(n):
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; [r0, r1] = random.standard_normal(2)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; myClass = random.uniform(0, 1)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;if (myClass &amp;lt;= 0.16):
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; fFlyer = random.uniform(22000, 60000)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; tats = 3 + 1.6 * r1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; markers.append(20)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; colors.append(2.1)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; classLabel = 1# &amp;#39;didntLike&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; xcord1.append(fFlyer);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; ycord1.append(tats)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;elif ((myClass &amp;gt; 0.16)and (myClass &amp;lt;= 0.33)):
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; fFlyer = 6000 * r0 + 70000
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; tats = 10 + 3 * r1 + 2 * r0
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; markers.append(20)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; colors.append(1.1)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; classLabel = 1# &amp;#39;didntLike&amp;#39;if (tats &amp;lt; 0): tats = 0
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;if (fFlyer &amp;lt; 0): fFlyer = 0
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; xcord1.append(fFlyer);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; ycord1.append(tats)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;elif ((myClass &amp;gt; 0.33)and (myClass &amp;lt;= 0.66)):
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; fFlyer = 5000 * r0 + 10000
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; tats = 3 + 2.8 * r1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; markers.append(30)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; colors.append(1.1)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; classLabel = 2# &amp;#39;smallDoses&amp;#39;if (tats &amp;lt; 0): tats = 0
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;if (fFlyer &amp;lt; 0): fFlyer = 0
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; xcord2.append(fFlyer);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; ycord2.append(tats)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;else:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; fFlyer = 10000 * r0 + 35000
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; tats = 10 + 2.0 * r1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; markers.append(50)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; colors.append(0.1)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; classLabel = 3# &amp;#39;largeDoses&amp;#39;if (tats &amp;lt; 0): tats = 0
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;if (fFlyer &amp;lt; 0): fFlyer = 0
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; xcord3.append(fFlyer);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; ycord3.append(tats)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; fw.close()
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; fig = plt.figure()
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; ax = fig.add_subplot(111)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;# ax.scatter(xcord,ycord, c=colors, s=markers)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; type1 = ax.scatter(xcord1, ycord1, s=20, c=&amp;#39;red&amp;#39;)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; type2 = ax.scatter(xcord2, ycord2, s=30, c=&amp;#39;green&amp;#39;)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; type3 = ax.scatter(xcord3, ycord3, s=50, c=&amp;#39;blue&amp;#39;)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; ax.legend([type1, type2, type3], [&amp;#34;Did Not Like&amp;#34;, &amp;#34;Liked in Small Doses&amp;#34;, &amp;#34;Liked in Large Doses&amp;#34;], loc=2)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; ax.axis([-5000, 100000, -2, 25])
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; plt.xlabel(&amp;#39;Frequent Flyier Miles Earned Per Year&amp;#39;)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; plt.ylabel(&amp;#39;Percentage of Time Spent Playing Video Games&amp;#39;)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; plt.show()
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;showNormal()
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;showLable()
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;showClass()
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;datingClassTest()
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>我的后端开发书架2015版</title><link>https://blog.jimersylee.com/posts/%E6%88%91%E7%9A%84%E5%90%8E%E7%AB%AF%E5%BC%80%E5%8F%91%E4%B9%A6%E6%9E%B62015%E7%89%88/</link><pubDate>Thu, 29 Oct 2015 13:38:00 +0000</pubDate><guid>https://blog.jimersylee.com/posts/%E6%88%91%E7%9A%84%E5%90%8E%E7%AB%AF%E5%BC%80%E5%8F%91%E4%B9%A6%E6%9E%B62015%E7%89%88/</guid><description>&lt;p&gt;原文出处： 江南白衣（@江南白衣Calvin)&lt;/p&gt;
&lt;p&gt;小学生作文的开头：光阴似箭，日月如梭…..半年过去了，床底下又多了不少书，更新一个2.0版。&lt;/p&gt;
&lt;p&gt;自从技术书的书架设定为”床底下“之后，又多了很多买书的空间。中国什么都贵，就是书便宜。&lt;/p&gt;
&lt;p&gt;很多书没有全部看完，看一部分觉得值得推荐就放上来了，但在碎片化的阅读下难免错评，不定期更新修正。&lt;/p&gt;
&lt;p&gt;书架主要针对Java后端开发。&lt;/p&gt;
&lt;p&gt;更偏爱那些能用简短流畅的话，把少壮不努力的程序员所需的基础补回来的薄书，而有些教课书可能很著名，但干涩枯燥，喋喋不休的把你带回到大学课堂上昏昏欲睡，不录。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;操作系统与网络的书&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;《Linux内核设计与实现 – Linux Kernel Development 第3版》 Robert Love用最薄的篇幅，顺畅的文字将Linux内核主要的算法讲清楚了，比《深入理解Linux内核》，《深入Linux内核架构》之类厚厚的全是代码的，不是专门的内核程序员看这本足够了。&lt;/p&gt;
&lt;p&gt;《Linux系统编程 第2版》 继续是Robert Love，比起APUE也是以薄见长，专门针对重要的系统调用讲解。&lt;/p&gt;
&lt;p&gt;《性能之巅》 操作系统的性能调优、监控、工具和方法论，看这本就够了，足够厚。还有本薄一点的，东抄西编格调没那么高的叫《Linux性能优化大师》。&lt;/p&gt;
&lt;p&gt;《TCP/IP详解 卷1:协议》 这么多年过去了，TCP的书好像还是只有这一本，有点旧了，看了也还是半懂不懂。后人在2011年写了第二版，看目录清晰明了与时俱进了很多，机械工业正在翻译。&lt;/p&gt;
&lt;p&gt;《现代操作系统 第3版》 如果看LKD未尽兴，可以回头看看这本基础概念，感觉比那本枯燥的《操作系统概念》(恐龙书)读起来舒服。&lt;/p&gt;
&lt;p&gt;PS. 《UNIX环境高级编程》和《UNIX网络编程》，APUE和UNP更多作为一本超厚工具书存在。《Unix 编程艺术》，扯的都是闲篇，厚厚的一本其实略读一下就行。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;算法的书&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;《数据结构与算法分析-Java语言描述 第2版》 够薄，数据结构与算法分析的点基本都涵盖了，而且示例代码还是Java写的。&lt;/p&gt;
&lt;p&gt;《算法 第4版》 可与上一本对比着读，厚一些，也多些图，但知识点没上面的全，也是Java的。&lt;/p&gt;
&lt;p&gt;《算法设计与分析基础 第3版》 数学系偏爱无比枯燥很多公式的《算法导论》， 计算机系喜欢这本实用主义的典型。翻开就看到一段很文艺很贴心的话：“效率能用数学的严密性进行精确定义，而简单性就像“美”一样，很大程度取决于审视者 的眼光。简单的算法更容易理解和实现，因而相应的程序也往往更少的Bug。当然对于简单性的美学诉求也是让人无法抗拒的。” PS. 《数学之美》、《编程珠玑》，都是专栏文章，讲得并不系统，可以当兴趣读物来看。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;架构设计的书&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;《恰如其分的软件架构 – 风险驱动的设计方法》 由于人类与生俱来的惰性，计算机原本科学的、精准的设计方式，有了敏捷的借口之后就很难再维持了。本书就是在这种背景下，提出由风险来决定设计的度，当然，这个风险是广义的。除了开始的风险驱动部分，其余部分就是规规矩矩标标准准的架构师教科书。&lt;/p&gt;
&lt;p&gt;《软件系统架构：使用视点和视角与利益相关者合作 第2版》 也是教科书，最难得的是，这本老书在十年后的去年升级了第二版。&lt;/p&gt;
&lt;p&gt;《程序员必读之软件架构 – Software Architecture for Developers》 作者维护着codingthearchitecture.com 。不过中文书名叫“必读”有点过。薄书里的两部分内容：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;编码的架构师：一直是我的职业模板，我记的笔记。&lt;/li&gt;
&lt;li&gt;架构的表达： 当年我觉得RUP的4+1 UML视图不足以表达系统时，Simon Brown的模板给了很好的过渡范例。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;《发布！软件的设计与部署 – Release It!: Design and Deploy Production-Ready Software 》 关于高可靠性的软件，学校里不会教，出来社会却要面对的那部分，英文的原标题更清晰。&lt;/p&gt;</description></item><item><title>机器学习和数据挖掘的推荐书单</title><link>https://blog.jimersylee.com/posts/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0%E5%92%8C%E6%95%B0%E6%8D%AE%E6%8C%96%E6%8E%98%E7%9A%84%E6%8E%A8%E8%8D%90%E4%B9%A6%E5%8D%95/</link><pubDate>Mon, 26 Oct 2015 13:38:00 +0000</pubDate><guid>https://blog.jimersylee.com/posts/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0%E5%92%8C%E6%95%B0%E6%8D%AE%E6%8C%96%E6%8E%98%E7%9A%84%E6%8E%A8%E8%8D%90%E4%B9%A6%E5%8D%95/</guid><description>&lt;h1 id="机器学习和数据挖掘的推荐书单"&gt;机器学习和数据挖掘的推荐书单&lt;/h1&gt;
&lt;p&gt;本文作者： 伯乐在线 - 天才白痴梦 。&lt;/p&gt;
&lt;p&gt;有了这些书，再也不愁下了班没妹纸该咋办了。慢慢来，认真学，揭开机器学习和数据挖掘这一神秘的面纱吧！&lt;/p&gt;
&lt;p&gt;《机器学习实战》： 本书第一部分主要介绍机器学习基础，以及如何利用算法进行分类，并逐步介绍了多种经典的监督学习算法，如k近邻算法、朴素贝叶斯算法、Logistic回 归算法、支持向量机、AdaBoost集成方法、基于树的回归算法和分类回归树（CART）算法等。第三部分则重点介绍无监督学习及其一些主要算法：k均 值聚类算法、Apriori算法、FP-Growth算法。第四部分介绍了机器学习算法的一些附属工具。&lt;/p&gt;
&lt;p&gt;全书通过精心编排的实例，切入日常工作任务，摒弃学术化语言，利用高效的可复用Python代码来阐释如何处理统计数据，进行数据分析及可视化。通 过各种实例，读者可从中学会机器学习的核心算法，并能将其运用于一些策略性任务中，如分类、预测、推荐。另外，还可用它们来实现一些更高级的功能，如汇总 和简化等。&lt;/p&gt;
&lt;p&gt;之前看过一部分这本书，但是实习工作涉及到用Java代码处理数据，所以暂时先搁一下，目前正在李航的那本书。&lt;/p&gt;
&lt;p&gt;《数据挖掘-实用机器学习技术》： 本书介绍数据挖掘的基本理论与实践方法。主要内容包括：各种模型(决策树，关联规则、线性模型、聚类、贝叶斯网以及神经网络)以及在实践中的运用，所存任 缺陷的分析。安全地清理数据集、建立以及评估模型的预测质量的方法，并且提供了一个公开的数据挖掘工作平台Weka。Weka系统拥有进行数据挖掘仟务的 图形用户界面，有助于理解模型，是一个实用并且深受欢迎的工具。&lt;/p&gt;
&lt;p&gt;《数据挖掘：概念与技术》： 本书全面地讲述数据挖掘领域的重要知识和技术创新。在第1版内容相当全面的基础上，第2版展示了该领域的最新研究成果，例如挖掘流、时序和序列数据以及挖 掘时间空间、多媒体、文本和Web数据。本书可作为数据挖掘和知识发现领域的教师、研究人员和开发人员的一本必读书。&lt;/p&gt;
&lt;p&gt;《统计学习基础 数据挖掘、推理与预测》：尽管应用的是统计学方法，但强调的是概念，而不是数学。许多例子附以彩图。《统计学习基础:数据挖掘、推 理与预测》内容广泛，从有指导的学习（预测）到无指导的学习，应有尽有。包括神经网络、支持向量机、分类树和提升等主题，是同类书籍中介绍得最全面的。计 算和信息技术的飞速发展带来了医学、生物学、财经和营销等诸多领域的海量数据。理解这些数据是一种挑战，这导致了统计学领域新工具的发展，并延伸到诸如数 据挖掘、机器学习和生物信息学等新领域。&lt;/p&gt;
&lt;p&gt;《机器学习》 （Mitchell）：展示了机器学习中核心的算法和理论，并阐明了算法的运行过程。《机器学习》综合了许多的研究成果，例如统计学、人工智能、哲学、信 息论、生物学、认知科学、计算复杂性和控制论等，并以此来理解问题的背景、算法和其中的隐含假定。《机器学习》可作为计算机专业 本科生、研究生教材，也 可作为相关领域研究人员、教师的参考书。&lt;/p&gt;
&lt;p&gt;《统计学习方法》： 本书全面系统地介绍了统计学习的主要方法，特别是监督学习方法，包括感知机、k近邻法、朴素贝叶斯法、决策树、逻辑斯谛回归与最大熵模型、支持向量机、提 升方法、em算法、隐马尔可夫模型和条件随机场等。除第1章概论和最后一章总结外，每章介绍一种方法。叙述从具体问题或实例入手，由浅入深，阐明思路，给 出必要的数学推导，便于读者掌握统计学习方法的实质，学会运用。为满足读者进一步学习的需要，书中还介绍了一些相关研究，给出了少量习题，列出了主要参考 文献。&lt;/p&gt;
&lt;p&gt;《机器学习导论》：对机器学习的定义和应用实例进行了介绍，涵盖了监督学习。贝叶斯决策理论。参数方法、多元方法、维度归约、聚类、非参数方法、决策树。线性判别式、多层感知器，局部模型、隐马尔可夫模型。分类算法评估和比较，组合多学习器以及增强学习等。&lt;/p&gt;
&lt;p&gt;《机器学习及其应用》：全书共分14章，内容分别涉及因果推断、流形学习与降维、迁移学习、类别不平衡学习、演化聚类、多标记学习、排序学习、半监督学习等技术和协同过滤、社区推荐、机器翻译等应用，以及互联网应用对机器学习技术需求的探讨。&lt;/p&gt;
&lt;p&gt;《模式分类》第二版：除了保留了第1版的关于统计模式识别和结构模式识别的主要内容以外，读者将会发现新增了许多近25年来的新理论和新方法，其中包括神经网络、机器学习、数据挖掘、进化计算、不变量理论、隐马尔可夫模型、统计学习理论和支持向量机等。&lt;/p&gt;
&lt;p&gt;《推荐系统实践》：过大量代码和图表全面系统地阐述了和推荐系统有关的理论基础，介绍了评价推荐系统优劣的各种标准(比如覆盖率、满意度)和方法(比如AB测试)，总结了当今互联网领域中各种和推荐有关的产品和服务。&lt;/p&gt;
&lt;p&gt;《深入搜索引擎：海量信息的压缩、索引和查询》：理论和实践并重，深入浅出地给出了海量信息数据处理的整套解决方案，包括压缩、索引和查询的方方面面。其最大的特色在于不仅仅满足信息检索理论学习的需要，更重要的是给出了实践中可能面对的各种问题及其解决方法。&lt;/p&gt;
&lt;p&gt;《概率论与数理统计》：这本书不用过多介绍了吧，普遍大学里大一时期的教科书，只恨当年没听课啊，现在正在慢慢啃。。。&lt;/p&gt;
&lt;p&gt;《大数据：互联网大规模数据挖掘与分布式处理》：主要内容包括分布式文件系统、相似性搜索、搜索引擎技术、频繁项集挖掘、聚类算法、广告管理及推荐系统。&lt;/p&gt;
&lt;p&gt;《Web数据挖掘》： 信息检索领域的书籍，该书深入讲解了从大量非结构化Web数据中提取和产生知识的技术。书中首先论述了Web的基础（包括Web信息采集机制、Web标引 机制以及基于关键字或基于相似性搜索机制），然后系统地描述了Web挖掘的基础知识，着重介绍基于超文本的机器学习和数据挖掘方法，如聚类、协同过滤、监 督学习、半监督学习，最后讲述了这些基本原理在Web挖掘中的应用。《Web数据挖掘》为读者提供了坚实的技术背景和最新的知识。&lt;/p&gt;
&lt;p&gt;《数据之巅》：对大数据追根溯源，提出当前信息技术的发展，已经让中国获得了后发优势，中国要在大数据时代的全球竞争中胜出，必须把大数据从科技符号提升成为文化符号，在全社会倡导数据文化。&lt;/p&gt;
&lt;p&gt;《深入浅出统计学》：本书涵盖的知识点包括：信息可视化、概率计算、几何分布、二项分布及泊松分布、正态分布、统计抽样、置信区间的构建、假设检验、卡方分布、相关与回归等等，完整涵盖AP考试范围。&lt;/p&gt;
&lt;p&gt;《矩阵分析》： 本书从数学分析的角度论述矩阵分析的经典方法和现代方法，取材新，有一定的深度，并给出在多元微积分、复分析、微分方程、量优化、逼近理论中的许多重要应 用。主要内容包括：特征值、特征向量和相似性，酉等价和正规矩阵，标准形，Hermite矩阵和对称矩阵，向量范数和矩阵范数，特征值和估计和扰动，正定 矩阵，非负矩阵。&lt;/p&gt;</description></item><item><title>JS规则-使用js的最佳实践</title><link>https://blog.jimersylee.com/posts/js%E8%A7%84%E5%88%99-%E4%BD%BF%E7%94%A8js%E7%9A%84%E6%9C%80%E4%BD%B3%E5%AE%9E%E8%B7%B5/</link><pubDate>Tue, 13 Oct 2015 10:17:00 +0000</pubDate><guid>https://blog.jimersylee.com/posts/js%E8%A7%84%E5%88%99-%E4%BD%BF%E7%94%A8js%E7%9A%84%E6%9C%80%E4%BD%B3%E5%AE%9E%E8%B7%B5/</guid><description>&lt;h1 id="1-js应该放到-js-文件中"&gt;&lt;strong&gt;1. JS应该放到 .js 文件中&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;“额，只有那么几行而已…”，是的，我的意思是所有的 JS 都应该放在.js文件中。为什么呢？因为这有助于可读性，节省带宽。行内 JavaScript 在每次页面加载时都会重新下载，相反的，单独的.js文件则会被缓存起来。正如你所看到的，这个规则有助于支持如下一长串的其他规则。这就是为什么它的规则# 1。&lt;/p&gt;
&lt;h1 id="2-js-应该是静态的"&gt;&lt;strong&gt;2. JS 应该是静态的&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;我看到过很多程序员喜欢动态的使用JavaScript。他们喜欢像使用服务器端语言如C#, Ruby, Java那样来动态的使用JavaScript。千万不要这么做。你失去了代码着色、语法高亮显示和智能感知的支持。记住，JavaScript 应该属于一个.js文件(见规则 #1)。&lt;/p&gt;
&lt;p&gt;然而，使用JSON引入动态行为。我把这称为JavaScript配置对象模式。具体方法如下：把JSON注入到你应用程序的头部，并根据业务逻辑 的需要利用这些数据。你可能会想：“嘿，这违背了规则 #1”。我把 JSON 看作是数据，而不是代码，所以我破例，为了支持静态的、单独的JavaScript文件。&lt;/p&gt;
&lt;p&gt;StackOverflow 使用的这种模式，Google 也是。&lt;/p&gt;
&lt;h1 id="3-js-应该被压缩"&gt;&lt;strong&gt;3. JS 应该被压缩&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;压缩可以减小文件体积，从而提升页面加载速度。记住，性能也是一项功能。因为，为了压缩，你需要把 JS 放到一个单独的文件中(见规则 #1)。压缩JS曾经很麻烦，但现在完全是简单自动化的。有一打的方式可以做到，而Gulp和gulp-uglify是一种低摩擦和自动化的办法。&lt;/p&gt;
&lt;h1 id="4-js-应该位于页面底部"&gt;&lt;strong&gt;4. JS 应该位于页面底部&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;如果你把&lt;!-- raw HTML omitted --&gt;标签放在&lt;!-- raw HTML omitted --&gt;中，它会阻碍页面渲染。位于&lt;!-- raw HTML omitted --&gt;中的脚本必须在页面显示前加载，因此把&lt;!-- raw HTML omitted --&gt;放在底部的 前面可以先显示页面，而不用等 JS 文件下载完毕。这有助于提升感知性能。如果你的JavaSctipe必须位于&lt;!-- raw HTML omitted --&gt;中，可以考虑使用 jQuery 的$(document).ready这样你的脚本可以等到 DOM 加载完毕后再执行。&lt;/p&gt;
&lt;h1 id="5-js-应该实时的-linted"&gt;&lt;strong&gt;5. JS 应该实时的 Linted&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;Linting 遵循代码风格、发现错别字、有助于避免错误。有很多这样的工具，我建议使用ESLint。你可以使用 Gulp 的gulp-eslint来运行它。Gulp 可以查看你所有的 JS 文件，并在你每次保存的时候运行 linter。另外，你需要把你的 JS 代码放在单独的 .js 文件中才能运行 linter 。&lt;/p&gt;</description></item><item><title>使用scrapy写爬虫</title><link>https://blog.jimersylee.com/posts/%E4%BD%BF%E7%94%A8scrapy%E5%86%99%E7%88%AC%E8%99%AB/</link><pubDate>Tue, 04 Aug 2015 10:27:00 +0000</pubDate><guid>https://blog.jimersylee.com/posts/%E4%BD%BF%E7%94%A8scrapy%E5%86%99%E7%88%AC%E8%99%AB/</guid><description>&lt;h1 id="使用scrapy写爬虫"&gt;使用scrapy写爬虫&lt;/h1&gt;
&lt;p&gt;一开始想在windows环境下安装scrapy,无奈安装多次都失败,转向linux&lt;/p&gt;
&lt;p&gt;linux自带python2.7 因此只需要安装scrapy模块就行&lt;/p&gt;
&lt;p&gt;先用pip安装Scrapy 失败&lt;/p&gt;
&lt;p&gt;于是安装easy_install&lt;/p&gt;
&lt;p&gt;命令行 sudo apt-get install python-setuptools&lt;/p&gt;
&lt;p&gt;sudo easy_install Scrapy&lt;/p&gt;
&lt;p&gt;出现错误,搜索知道必须使用python的dev版本&lt;/p&gt;
&lt;p&gt;于是 sudo apt-get install python-dev&lt;/p&gt;
&lt;p&gt;再次 sudo easy_install Scrapy&lt;/p&gt;
&lt;p&gt;安装成功&lt;/p&gt;
&lt;p&gt;然后安装mongodb&lt;/p&gt;
&lt;p&gt;sudo easy_instal pymongo&lt;/p&gt;</description></item><item><title>spacevim安装与使用</title><link>https://blog.jimersylee.com/posts/spacevim%E5%AE%89%E8%A3%85%E4%B8%8E%E4%BD%BF%E7%94%A8/</link><pubDate>Mon, 03 Aug 2015 09:47:00 +0000</pubDate><guid>https://blog.jimersylee.com/posts/spacevim%E5%AE%89%E8%A3%85%E4%B8%8E%E4%BD%BF%E7%94%A8/</guid><description>&lt;h1 id="安装"&gt;&lt;strong&gt;安装&lt;/strong&gt;&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;安装spacevim的前提是安装好vim,一般linux系统自带&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;#redhat系列
sudo yuminstall vim / sudo dnfinstall vim
#debian系列
sudo aptinstall vim
#或者
sudo apt-getinstall vim
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;安装spacevim&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;curl -sLf https://spacevim.org/install.sh | bash
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;启动spacevim,等待下载插件&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;vim test.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="使用"&gt;&lt;strong&gt;使用&lt;/strong&gt;&lt;/h1&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;#打开目录
vim path
#右边就会出现目录,移动光标到目录上,按回车键,就能进入目录;移动到文件上,按回车键就能打开文件;按退格键能返回上级目录
#切换工程目录区与编辑的文件
&amp;lt;ctrl+tab&amp;gt;#创建文件
在工程区移动到文件夹下,按&amp;lt;shift+n&amp;gt;,下方提示栏就会出现提示,输入文件名,回车,创建文件
#删除文件
在工程区移动到文件夹下,按&lt;!-- raw HTML omitted --&gt;,下方提示栏就会出现提示,是否要删除,输入yes删除&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&lt;/code&gt;&lt;/pre&gt;</description></item><item><title>PHP字符串常用函数学习</title><link>https://blog.jimersylee.com/posts/php%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%B8%B8%E7%94%A8%E5%87%BD%E6%95%B0%E5%AD%A6%E4%B9%A0/</link><pubDate>Sun, 19 Jul 2015 09:45:00 +0000</pubDate><guid>https://blog.jimersylee.com/posts/php%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%B8%B8%E7%94%A8%E5%87%BD%E6%95%B0%E5%AD%A6%E4%B9%A0/</guid><description>&lt;h1 id="php字符串常用函数学习"&gt;PHP字符串常用函数学习&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;html&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;head&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;meta&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;http-equiv&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;content-type&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;content&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;text/html;charset=utf-8&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;body&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;/&lt;span style="color:#f92672"&gt;body&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;/&lt;span style="color:#f92672"&gt;head&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;/&lt;span style="color:#f92672"&gt;html&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;&amp;lt;?php
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;echo &amp;#39;1 int crc32(string str),产生32位长的crc多项式,比如crc32(&amp;#34;helllo&amp;#34;)&amp;lt;br/&amp;gt;&amp;#39;;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;echo crc32 (&amp;#34;jkkajjjk\n&amp;#34;);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;echo &amp;#39;&amp;lt;br/&amp;gt;&amp;#39;;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;echo &amp;#39;2 string bin2hex(string str) , 把二进制转换为十六进制,比如bin2hex(&amp;#34;helloworld&amp;#34;)&amp;lt;br/&amp;gt;&amp;#39;;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;echo bin2hex(&amp;#34;hello world&amp;#34;);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;echo &amp;#39;&amp;lt;br/&amp;gt;&amp;#39;;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;echo &amp;#39;3 string chop(string str),移除str后面多余的空白,返回新的字符串&amp;lt;br/&amp;gt;&amp;#39;;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;echo &amp;#39;kkkj l &amp;#39;;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;echo &amp;#39;hahah&amp;#39;;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;echo chop(&amp;#34;kkkj l &amp;#34;);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;echo &amp;#39;hahah&amp;#39;;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;echo &amp;#39;&amp;lt;br/&amp;gt;&amp;#39;;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;echo &amp;#39;4 string chr(int ascii),返回指定ascii码表示的字符,如chr(100)&amp;lt;br/&amp;gt;&amp;#39;;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;echo chr(100);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;echo &amp;#39;&amp;lt;br/&amp;gt;&amp;#39;;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;echo &amp;#39;5 int ord(string str),返回str字符串第一个字符的ascii码,如ord(&amp;#34;d&amp;#34;),&amp;lt;br/&amp;gt;&amp;#39;;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;echo ord(&amp;#34;d&amp;#34;);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;echo &amp;#34;&amp;lt;br/&amp;gt;&amp;#34;;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;echo &amp;#39;6 string chunk_split(string str,int chunklen, string end),把字符串没隔一定数目就分割,如chunk_split(&amp;#34;jasdjkasjdkasadas&amp;#34;,5,&amp;#34;|&amp;#34;),就是把字符串每5个字符用|分割&amp;lt;br/&amp;gt;&amp;#39;;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;echo chunk_split(&amp;#34;jasdjkasjdkasadas&amp;#34;,5,&amp;#34;|&amp;#34;);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;echo &amp;#39;&amp;lt;br/&amp;gt;&amp;#39;;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;echo &amp;#39;7 string crypt(string str,string salt),单向加密,无解密函数~&amp;#39;;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;echo &amp;#39;&amp;lt;br/&amp;gt;&amp;#39;;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;echo crypt(&amp;#34;hello world&amp;#34;,&amp;#34;kk&amp;#34;);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;echo &amp;#39;&amp;lt;br/&amp;gt;&amp;#39;;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;echo &amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;CRYPT_STD_DES - 基于标准 DES 算法的散列使用 &amp;#34;./0-9A-Za-z&amp;#34; 字符中的两个字符作为盐值。在盐值中使用非法的字符将导致 crypt() 失败。
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;CRYPT_EXT_DES - 扩展的基于 DES 算法的散列。其盐值为 9 个字符的字符串，由 1 个下划线后面跟着 4 字节循环次数和 4 字节盐值组成。它们被编码成可打印字符，每个字符 6 位，有效位最少的优先。0 到 63 被编码为 &amp;#34;./0-9A-Za-z&amp;#34;。在盐值中使用非法的字符将导致 crypt() 失败。
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;CRYPT_MD5 - MD5 散列使用一个以 $1$ 开始的 12 字符的字符串盐值。
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;CRYPT_BLOWFISH - Blowfish 算法使用如下盐值：“$2a$”，一个两位 cost 参数，“$” 以及 64 位由 “./0-9A-Za-z” 中的字符组合而成的字符串。在盐值中使用此范围之外的字符将导致 crypt() 返回一个空字符串。两位 cost 参数是循环次数以 2 为底的对数，它的范围是 04-31，超出这个范围将导致 crypt() 失败。
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;CRYPT_SHA256 - SHA-256 算法使用一个以 $5$ 开头的 16 字符字符串盐值进行散列。如果盐值字符串以 “rounds=&amp;lt;N&amp;gt;$” 开头，N 的数字值将被用来指定散列循环的执行次数，这点很像 Blowfish 算法的 cost 参数。默认的循环次数是 5000，最小是 1000，最大是 999,999,999。超出这个范围的 N 将会被转换为最接近的值。
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;CRYPT_SHA512 - SHA-512 算法使用一个以 $6$ 开头的 16 字符字符串盐值进行散列。如果盐值字符串以 “rounds=&amp;lt;N&amp;gt;$” 开头，N 的数字值将被用来指定散列循环的执行次数，这点很像 Blowfish 算法的 cost 参数。默认的循环次数是 5000，最小是 1000，最大是 999,999,999。超出这个范围的 N 将会被转换为最接近的值。
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;&amp;#39;;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;if (CRYPT_STD_DES == 1)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;echo &amp;#34;Standard DES: &amp;#34;.crypt(&amp;#34;hello world&amp;#34;).&amp;#34;\n&amp;lt;br /&amp;gt;&amp;#34;;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;else
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;echo &amp;#34;Standard DES not supported.\n&amp;lt;br /&amp;gt;&amp;#34;;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;if (CRYPT_EXT_DES == 1)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;echo &amp;#34;Extended DES: &amp;#34;.crypt(&amp;#34;hello world&amp;#34;).&amp;#34;\n&amp;lt;br /&amp;gt;&amp;#34;;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;else
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;echo &amp;#34;Extended DES not supported.\n&amp;lt;br /&amp;gt;&amp;#34;;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;if (CRYPT_MD5 == 1)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;echo &amp;#34;MD5: &amp;#34;.crypt(&amp;#34;hello world&amp;#34;).&amp;#34;\n&amp;lt;br /&amp;gt;&amp;#34;;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;else
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;echo &amp;#34;MD5 not supported.\n&amp;lt;br /&amp;gt;&amp;#34;;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;if (CRYPT_BLOWFISH == 1)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;echo &amp;#34;Blowfish: &amp;#34;.crypt(&amp;#34;hello world&amp;#34;);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;else
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;echo &amp;#34;Blowfish DES not supported.&amp;#34;;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;echo &amp;#39;&amp;lt;br/&amp;gt;&amp;#39;;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;echo &amp;#39; 8 array explode (string separator, string string [, int limit]),传回一个字符串的数组，以参数 separator为界线将参数 string切开，如果有设定参数 limit，则传回的数组最多将会包含 limit个元素，而最后一个元素将会包含 string全部剩余的部份。&amp;lt;br/&amp;gt;&amp;#39;;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;$pizza=&amp;#34;haa kkkk kllom lljjijj iioo &amp;#34;;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;$pieces=explode(&amp;#34; &amp;#34;,$pizza);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;foreach($pieces as $val){
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;echo $val;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;echo &amp;#39;&amp;lt;br/&amp;gt;&amp;#39;;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;echo &amp;#39;9 string implode (string glue, array pieces) 以参数glue将数组pieces的各个元素结合起来成字符串返回.与join(string glue,array pieces)相同用法&amp;lt;br/&amp;gt;&amp;#39;;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;echo implode (&amp;#34;:&amp;#34;, $pieces);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;echo &amp;#39;&amp;lt;br/&amp;gt;&amp;#39;;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;echo &amp;#39;10 array split (string pattern, string string [, int limit]),以正则把字符串切开 &amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;?&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>机器学习实战-学习笔记之NaiveBayes</title><link>https://blog.jimersylee.com/posts/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0%E5%AE%9E%E6%88%98-%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%E4%B9%8Bnaivebayes/</link><pubDate>Fri, 22 May 2015 10:33:00 +0000</pubDate><guid>https://blog.jimersylee.com/posts/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0%E5%AE%9E%E6%88%98-%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%E4%B9%8Bnaivebayes/</guid><description>&lt;p&gt;项目地址:&lt;a href="http://github.com/jimersylee/MachineLearningAction"&gt;http://github.com/jimersylee/MachineLearningAction&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="基于概率论的分类方法"&gt;&lt;strong&gt;基于概率论的分类方法&lt;/strong&gt;&lt;/h3&gt;
&lt;h3 id="朴素贝叶斯"&gt;&lt;strong&gt;朴素贝叶斯&lt;/strong&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;使用概率分布进行分类&lt;/li&gt;
&lt;li&gt;学习朴素贝叶斯分类器&lt;/li&gt;
&lt;li&gt;解析RSS源数据&lt;/li&gt;
&lt;li&gt;使用朴素贝叶斯来分析不同地区的态度&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="朴素贝叶斯-1"&gt;&lt;strong&gt;朴素贝叶斯&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;优点:在数据较少的情况下仍然有效,可以处理多类别问题 缺点:对于输入数据的准备方式较为敏感 使用数据类型:标称型数据&lt;/p&gt;
&lt;h3 id="贝叶斯决策理论的核心思想"&gt;&lt;strong&gt;贝叶斯决策理论的核心思想&amp;ndash;即选择具有最高概率的决策&lt;/strong&gt;&lt;/h3&gt;
&lt;h1 id="条件概率"&gt;&lt;strong&gt;条件概率&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;P(A|B)=&lt;/p&gt;
&lt;p&gt;P(AB)−−−−−−\P(B)&lt;/p&gt;
&lt;h3 id="使用贝叶斯准则进行条件与结果的互换计算"&gt;&lt;strong&gt;使用贝叶斯准则,进行条件与结果的互换计算&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;已知P(A|B),求P(B|A)&lt;/p&gt;
&lt;p&gt;P(B|A)=&lt;/p&gt;
&lt;p&gt;P(A|B)P(B)−−−−−−−−−−\P(A)&lt;/p&gt;
&lt;p&gt;推导&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;给定某个点(x,y),那么该点来自ci的概率为P(ci|x,y)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;P(&lt;/p&gt;
&lt;p&gt;ci&lt;/p&gt;
&lt;p&gt;|x,y)=&lt;/p&gt;
&lt;p&gt;P(x,y|ci)P(ci)−−−−−−−−−−−−\P(x,y)&lt;/p&gt;
&lt;p&gt;结论&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;如果P(c1|x,y)&amp;gt;P(c2|x,y),那么(x,y)属于c1如果P(c2|x,y)&amp;gt;P(c1|x,y),那么(x,y)属于c2&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id="使用朴素贝叶斯进行文档分类"&gt;&lt;strong&gt;使用朴素贝叶斯进行文档分类&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;朴素贝叶斯是贝叶斯分类器的一个扩展,是用于文档分类的常用算法 朴素贝叶斯的一帮过程&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;收集数据:可以使用任何方法,本章使用RSS源&lt;/li&gt;
&lt;li&gt;准备数据:需要数值型或者布尔型数据&lt;/li&gt;
&lt;li&gt;分析数据:有大量特征时,绘制特征作用不大,此时使用直方图效果较好&lt;/li&gt;
&lt;li&gt;训练算法:计算不同的独立特征的条件概率&lt;/li&gt;
&lt;li&gt;测试算法:计算错误率&lt;/li&gt;
&lt;li&gt;使用算法:一个常见的朴素贝叶斯应用是文档分类.可以在任意的分类场景中使用朴素贝叶斯分类器,不一定非要是文本.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;假设词汇表有1000个单词,要得到好的概率分布,需要足够的样本,假设样本数为N&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;由统计学知,如果每个特征需要N个样本,那么对于x个特征,将需要Nx个样本&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;对于1000个特征的词汇表将需要&lt;/p&gt;
&lt;p&gt;N1000&lt;/p&gt;
&lt;p&gt;个样本,可以看到,所需要的样本数会随着特征数目的增大而迅速增长 如果特征之间项目独立,那么样本数就能从&lt;/p&gt;
&lt;p&gt;N1000&lt;/p&gt;
&lt;p&gt;减少到N*1000.所谓独立,指的是&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;统计学上的独立,即一个特征或者单词出现的可能性与它和其他相邻单词没关系&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id="示例使用python进行恶意留言分类"&gt;&lt;strong&gt;示例:使用Python进行恶意留言分类&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;当论坛中用户发表评论时,总会存在一些恶意言论,如何识别是否为恶意评论,而不让其发送呢?&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;准备数据:从文本中构建词向量,详见bayes.py中的 createVocabList setOfWords2Vec&lt;/li&gt;
&lt;li&gt;训练算法:从词向量计算概率&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;重写贝叶斯准则,将之前的x,y替换为&lt;em&gt;w&lt;/em&gt;,粗体&lt;em&gt;w&lt;/em&gt;表示一个向量,即它是由多个数值组成.在这个例子中,数值个数与词汇表中的词个数相同 P(&lt;/p&gt;
&lt;p&gt;ci&lt;/p&gt;
&lt;p&gt;|w)=&lt;/p&gt;
&lt;p&gt;P(w|ci)P(ci)−−−−−−−−−−\P(w)&lt;/p&gt;
&lt;p&gt;如何计算?首先通过类别i(侮辱性或者非侮辱性留言)中的文档数除以总的文档数的计算概率p(&lt;/p&gt;
&lt;p&gt;ci&lt;/p&gt;
&lt;p&gt;),接下来计算P(&lt;/p&gt;
&lt;p&gt;ci&lt;/p&gt;
&lt;p&gt;|w),这里就用到了朴素贝叶斯假设&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;如果将w展开为一个个独立特征,那么可以将上述概率写做P(w0,w1,&amp;hellip;,wN|ci).这里假设所有事件都独立,它意味着可以使用P(w0|ci)P(w1|ci)&amp;hellip;P(wN|ci)来计算概率,这极大地简化了计算过程 该函数的伪代码如下 计算每个类别中的文档数目 对每篇训练文档:&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;对每个类别: 如果词条出现文档中-&amp;gt;增加该词条的计数值 增加所有词条的计数值 对每个类别: 对每个词条: 将该词条的数目除以总词条数目得到条件概率 返回每个类别的条件概率&lt;/p&gt;</description></item><item><title>设计模式之模板方法模式</title><link>https://blog.jimersylee.com/posts/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E4%B9%8B%E6%A8%A1%E6%9D%BF%E6%96%B9%E6%B3%95%E6%A8%A1%E5%BC%8F/</link><pubDate>Fri, 22 May 2015 09:43:00 +0000</pubDate><guid>https://blog.jimersylee.com/posts/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E4%B9%8B%E6%A8%A1%E6%9D%BF%E6%96%B9%E6%B3%95%E6%A8%A1%E5%BC%8F/</guid><description>&lt;h1 id="模板方法模式"&gt;&lt;strong&gt;模板方法模式&lt;/strong&gt;&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;模板方法模式在一个方法中定义了一个算法的骨架,而将一些步骤延迟到子类中.模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;这个模式是用来创建一个算法的模板.什么是模板?模板就是一个方法.更具体地说,这个方法将算法定义为一组步骤,其中的任何步骤都可以是抽象的,由子类负责实现.这可以确保算法的结构保持不变,同时由子类提供部分实现.&lt;/p&gt;
&lt;h1 id="快速搞定咖啡和茶的类"&gt;&lt;strong&gt;快速搞定咖啡和茶的类&lt;/strong&gt;&lt;/h1&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;/**
* 这是我们的咖啡类,用来煮咖啡
*/publicclassCoffee {
voidprepareRecipe(){
boilWater();
brewCoffeeGrinds();
pourInCup();
addSugarAndMilk();
}
privatevoidaddSugarAndMilk() {
System.out.println(&amp;#34;addSugarAndMilk&amp;#34;);
}
privatevoidpourInCup() {
System.out.println(&amp;#34;pourInCup&amp;#34;);
}
privatevoidbrewCoffeeGrinds() {
System.out.println(&amp;#34;brewCoffeeGrinds&amp;#34;);
}
privatevoidboilWater() {
System.out.println(&amp;#34;boilWater&amp;#34;);
}
}
publicclassTea {
voidprepareRecipe(){
boilWater();
steepTeaBag();
pourInCup();
addLemon();
}
privatevoidaddLemon() {
System.out.println(&amp;#34;addLemon&amp;#34;);
}
privatevoidpourInCup() {
System.out.println(&amp;#34;pourInCup&amp;#34;);
}
privatevoidsteepTeaBag() {
System.out.println(&amp;#34;steepTeaBag&amp;#34;);
}
privatevoidboilWater() {
System.out.println(&amp;#34;boilWater&amp;#34;);
}
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;请注意,boilWater()和pourCup()这两个方法完全一样,也就是说这里出现了重复的代码&lt;/p&gt;
&lt;p&gt;在这里,茶和咖啡是如此的相似,可以提取基类&lt;/p&gt;
&lt;p&gt;注意两份冲泡法都采用了相同的算法&lt;/p&gt;
&lt;p&gt;抽象prepareRecipe()&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;voidprepareRecipe(){
boilwater();
brew();
pourInCup();
addCondiments();
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;prepareRecipe()就是我们的模板方法&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;它是一个方法&lt;/li&gt;
&lt;li&gt;它用作一个算法的模板,在这个例子中,算法是用来制作咖啡饮料的&lt;/li&gt;
&lt;li&gt;在这个模板中,算法内的每一个步骤都被一个方法代表了&lt;/li&gt;
&lt;li&gt;某些方法是由这个类(也就是超类)处理的&lt;/li&gt;
&lt;li&gt;某些方法是由子类处理的&lt;/li&gt;
&lt;li&gt;需要由子类提供的方法,必须在超类中声明为抽象&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="优劣对比"&gt;&lt;strong&gt;优劣对比&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;不好的茶和咖啡的实现&lt;/p&gt;</description></item><item><title>设计模式之适配器模式</title><link>https://blog.jimersylee.com/posts/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E4%B9%8B%E9%80%82%E9%85%8D%E5%99%A8%E6%A8%A1%E5%BC%8F/</link><pubDate>Fri, 22 May 2015 09:42:00 +0000</pubDate><guid>https://blog.jimersylee.com/posts/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E4%B9%8B%E9%80%82%E9%85%8D%E5%99%A8%E6%A8%A1%E5%BC%8F/</guid><description>&lt;h1 id="适配器模式与外观模式"&gt;&lt;strong&gt;适配器模式与外观模式&lt;/strong&gt;&lt;/h1&gt;
&lt;h1 id="适配器模式"&gt;&lt;strong&gt;适配器模式&lt;/strong&gt;&lt;/h1&gt;
&lt;h3 id="需求"&gt;&lt;strong&gt;需求&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;现在已经存在IDuck接口,Turkey接口,假设你缺鸭子对象,想用一些火鸡对象来冒充.显而易见,因为火鸡的接口不同,所以我们不能公然拿来用,那么写个适配器吧&lt;/p&gt;
&lt;h3 id="faq"&gt;&lt;strong&gt;FAQ&lt;/strong&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;一个适配器需要做多少适配工作?&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;实现一个适配器所需要进行的工作,和目标接口的大小成正.如果不用适配器,你就必须改写客户端的代码来调用这个新的接口.相比之下,使用适配器成本更少&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;一个适配器只能封装一个类吗?&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;虽然大多数的适配器模式所采取的例子都是让一个适配器包装一个被适配者,但还是会有状况需要让一个适配器包装多个被适配者.这设计到另一个模式,被称为外观模式(Facade Pattern),人们常常将外观模式和适配器模式混为一谈,本章稍后对此详细说明&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;万一我的系统中新旧并存,是不是不使用适配器更好&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;可以创建一个双向的适配器,支持两边的接口.这样,这个适配器可以当做旧的接口,或者当做新的接口使用&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="外观模式"&gt;&lt;strong&gt;外观模式&lt;/strong&gt;&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;外观模式提供了一个统一的接口,用来访问子系统中的一群接口.外观定了一个高层接口,让子系统更容易使用.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;外观模式的意图是提供一个简单的接口,好让一个子系统更易于使用&lt;/p&gt;
&lt;h1 id="要点"&gt;&lt;strong&gt;要点&lt;/strong&gt;&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;当需要使用一个现有的类而其接口并不符合你的需求时,就使用适配器&lt;/li&gt;
&lt;li&gt;当需要简化并统一一个很大的接口或者一群复杂的接口时,使用外观&lt;/li&gt;
&lt;li&gt;适配器改变接口以符合客户的期望&lt;/li&gt;
&lt;li&gt;外观将客户从一个复杂的子系统中解耦&lt;/li&gt;
&lt;li&gt;实现一个适配器可能需要一番功夫,也可能不费功夫,视目标接口的大小与复杂度而定&lt;/li&gt;
&lt;li&gt;实现一个外观,需要将子系统组合进外观中,然后将工作委托给给子系统执行&lt;/li&gt;
&lt;li&gt;适配器模式有两种形式:对象适配器和类适配器.类适配器需要用到多重继承&lt;/li&gt;
&lt;li&gt;你可以为一个子系统实现一个以上的外观&lt;/li&gt;
&lt;li&gt;适配器将一个对象包装起来以改变其接口;装饰着将一个对象包装起来以增加新的行为和责任;而外观将一群对象&amp;quot;包装&amp;quot;起来以简化其接口&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="项目地址"&gt;&lt;strong&gt;项目地址&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://github.com/jimersylee/DesignPattern"&gt;java设计模式实现&lt;/a&gt; 如果觉得有点收获,记得在项目上点star哦!&lt;/p&gt;</description></item><item><title>设计模式之命令模式</title><link>https://blog.jimersylee.com/posts/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E4%B9%8B%E5%91%BD%E4%BB%A4%E6%A8%A1%E5%BC%8F/</link><pubDate>Mon, 11 May 2015 09:41:00 +0000</pubDate><guid>https://blog.jimersylee.com/posts/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E4%B9%8B%E5%91%BD%E4%BB%A4%E6%A8%A1%E5%BC%8F/</guid><description>&lt;h1 id="命令模式"&gt;&lt;strong&gt;命令模式&lt;/strong&gt;&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;命令模式将发出请求的对象和执行请求的对象解耦&lt;/li&gt;
&lt;li&gt;在被解耦的两者之间是通过命令对象进行沟通的.命令对象封装了接收者和一个或者一组动作&lt;/li&gt;
&lt;li&gt;调用者通过调用命令封装execute()发出请求,这会使得接收者的动作被调用&lt;/li&gt;
&lt;li&gt;调用者可以接受命令当做参数,甚至在运行时动态地进行&lt;/li&gt;
&lt;li&gt;命令可以支持撤销,做法是实现一个undo()方法来回到execute()被执行前的状态&lt;/li&gt;
&lt;li&gt;宏命令是命令的一种简单的延伸,允许调用多个命令.宏方法也可以支持注销&lt;/li&gt;
&lt;li&gt;实际操作时,很常见使用&amp;quot;聪明&amp;quot;命令对象,也就是直接实现了请求,而不是将工作委托给接收者&lt;/li&gt;
&lt;li&gt;命令也可以用来实现日志和事务系统&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="项目地址"&gt;&lt;strong&gt;项目地址&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://github.com/jimersylee/DesignPattern"&gt;java设计模式实现&lt;/a&gt; 如果觉得有点收获,记得在项目上点star哦!&lt;/p&gt;</description></item><item><title>设计模式之单例模式</title><link>https://blog.jimersylee.com/posts/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E4%B9%8B%E5%8D%95%E4%BE%8B%E6%A8%A1%E5%BC%8F/</link><pubDate>Sun, 10 May 2015 09:40:00 +0000</pubDate><guid>https://blog.jimersylee.com/posts/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E4%B9%8B%E5%8D%95%E4%BE%8B%E6%A8%A1%E5%BC%8F/</guid><description>&lt;h1 id="有什么用处"&gt;&lt;strong&gt;有什么用处&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;有些对象其实我们只需要一个,比方说:线程池,缓存,对话框,注册表,日志对象&amp;hellip;如果制造出多个实例,就会导致许多问题产生,例如程序的行为异常,资源使用过量,数据不一致&lt;/p&gt;
&lt;h1 id="如何做"&gt;&lt;strong&gt;如何做&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;利用静态类变量,静态方法和适当的访问修饰符&lt;/p&gt;
&lt;h1 id="定义"&gt;&lt;strong&gt;定义&lt;/strong&gt;&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;单例模式,确保一个类只有一个实例,并提供一个全局访问点&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h1 id="注意点多线程中使用单例"&gt;&lt;strong&gt;注意点,多线程中使用单例&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;如果有多个线程同时调用getInstance(),可能会产生多个实例,那就用synchronized(同步)关键字修饰 但是同步会降低性能,实际上也就第一次getInstance()时需要考虑同步问题,之后就没有同步问题.&lt;/p&gt;
&lt;h1 id="1如果getinstance的性能对应用程序不是很关键就加上synchronized关键字"&gt;&lt;strong&gt;1.如果getInstance()的性能对应用程序不是很关键,就加上synchronized关键字&lt;/strong&gt;&lt;/h1&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;/**
* 单例模式之懒汉模式
* 优点:在需要实例的时候才进行第一次实例化,在资源紧缺的时候,可以减少不必要的资源消耗
* 缺点:同步了getInstance(),会造成性能浪费
*/publicclassSingletonLazy {
/**
* 利用一个静态变量来记录Singleton类的唯一实例
*/privatestatic SingletonLazy instance;
/**
* 构造器声明为私有的,只有自己Singleton类才可以调用构造器
*/privateSingletonLazy() {
}
/**
* 用getInstance()实例化对象,并返回这个实例
* 在多线程中必须使用synchronized关键字修饰
* @return
*/publicstatic synchronized SingletonLazygetInstance() {
//懒汉模式//如果未被实例化,则newif (instance ==null) {
instance =new SingletonLazy();
}
//如果已经实例化,则返回实例return instance;
}
}
&lt;/code&gt;&lt;/pre&gt;&lt;h1 id="2如果getinstance的性能对应用程序很关键那就使用饿汉模式"&gt;&lt;strong&gt;2.如果getInstance()的性能对应用程序很关键,那就使用饿汉模式&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;使用饿汉模式&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;publicclassSingletonLazy{
//在静态初始化器(static initialize)中创建单例.这段代码保证了线程安全(Thread Safe)privatestatic SingletonLazy instance=new SingletonLazy();
privateSingletonLazy(){
}
publicstatic SingletonLazygetInstance(){
//到这里,一定存在实例了,直接使用它return instance;
}
}
&lt;/code&gt;&lt;/pre&gt;&lt;h1 id="3使用双重检查锁double-checked-locking在getinstance中减少使用同步"&gt;&lt;strong&gt;3.使用&amp;quot;双重检查锁&amp;quot;(double-checked locking),在getInstance()中减少使用同步&lt;/strong&gt;&lt;/h1&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;/**
* 单例模式之使用&amp;#34;双重检查加锁&amp;#34;
* 过程:在getInstance()中进行双重检查,确保一个实例
* 优点:在getInstance()中减少同步,增强性能,可以在多线程中使用
* 缺点:暂无
*/publicclassSingletonDoubleCheckedLocking {
/**
* 利用一个静态变量来记录Singleton类的唯一实例
* volatile关键字确保:当instance变量被初始化为Singleton实例时,多个线程正确地处理instance变量
*/privatestaticvolatile SingletonDoubleCheckedLocking instance;
/**
* 构造器声明为私有的,只有自己Singleton类才可以调用构造器
*/privateSingletonDoubleCheckedLocking() {
}
/**
* 用getInstance()实例化对象,并返回这个实例
* 方法不必用synchronized关键字修饰
* @return
*/publicstatic SingletonDoubleCheckedLockinggetInstance() {
if(instance==null){//检查实例,如果不存在,则进入同步区块//注意:只有第一次调用getInstance()方法才彻底执行这里的代码
synchronized (SingletonDoubleCheckedLocking.class){
if(instance==null){//进入区块后,再检查一次,如果是null,才创建实例
instance=new SingletonDoubleCheckedLocking();
}
}
}
return instance;
}
}
&lt;/code&gt;&lt;/pre&gt;&lt;h1 id="项目地址"&gt;&lt;strong&gt;项目地址&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://github.com/jimersylee/DesignPattern"&gt;java设计模式实现&lt;/a&gt; 如果觉得有点收获,记得在项目上点star哦!&lt;/p&gt;</description></item><item><title>机器学习实战-学习笔记之KNN-手写数据识别</title><link>https://blog.jimersylee.com/posts/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0%E5%AE%9E%E6%88%98-%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%E4%B9%8Bknn-%E6%89%8B%E5%86%99%E6%95%B0%E6%8D%AE%E8%AF%86%E5%88%AB/</link><pubDate>Mon, 04 May 2015 10:25:00 +0000</pubDate><guid>https://blog.jimersylee.com/posts/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0%E5%AE%9E%E6%88%98-%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%E4%B9%8Bknn-%E6%89%8B%E5%86%99%E6%95%B0%E6%8D%AE%E8%AF%86%E5%88%AB/</guid><description>&lt;h1 id="机器学习实战学习笔记之knn-手写数据识别"&gt;&amp;lt;机器学习实战&amp;gt;学习笔记之KNN-手写数据识别&lt;/h1&gt;</description></item><item><title>设计模式之工厂模式</title><link>https://blog.jimersylee.com/posts/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E4%B9%8B%E5%B7%A5%E5%8E%82%E6%A8%A1%E5%BC%8F/</link><pubDate>Mon, 20 Apr 2015 09:39:00 +0000</pubDate><guid>https://blog.jimersylee.com/posts/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E4%B9%8B%E5%B7%A5%E5%8E%82%E6%A8%A1%E5%BC%8F/</guid><description>&lt;h1 id="工厂模式"&gt;&lt;strong&gt;工厂模式&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;针对接口编程,可以隔离掉以后系统可能发生的一大堆改变 为了让系统有弹性,我们希望一个类是抽象类或接口.但如果这样,这些类或接口就无法直接实例化 根据类的类型,我们实例化正确的具体类,然后返回具体类的对象,这些具体类必须实现抽象类接口 但是压力来自于增加更多的具体类类型 把创建对象的代码从具体方法中抽离,把创建的过程搬到另一个对象中,这个对象只管如何创建对象. 我们称这个对象为&lt;em&gt;工厂&lt;/em&gt;,现在我们就来实现一个披萨工厂&lt;/p&gt;
&lt;h1 id="简单工厂模式"&gt;&lt;strong&gt;简单工厂模式&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;创建对象的过程在工厂类中&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;/**
* 简单工厂
* 披萨工厂类
*/publicclassSimplePizzaFactory {
/**
* 首先,在这个工厂类定义一个createPizza()方法,所有客户使用这个方法来实例化对象
* @param type:披萨类型
* @return Pizza
*/public Pizza createPizza(String type){
Pizza pizza=null;
if(type.equals(&amp;#34;cheese&amp;#34;)){
pizza=new CheesePizza();
}elseif(type.equals(&amp;#34;pepperoni&amp;#34;)){
pizza=new Pepperoni();
}
return pizza;
}
}
&lt;/code&gt;&lt;/pre&gt;&lt;h1 id="工厂方法模式"&gt;&lt;strong&gt;工厂方法模式&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;工厂方法用来处理对象的创建,并将这样的行为封装在子类中.这样,客户程序中关于超类的代码就和子类对象创建代码解耦了.工厂方法可能需要参数,也可能不需要.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;abstract Product factoryMethod(String type)
abstract:工厂方法是抽象的
Product:工厂方法必须返回一个产品.超类中定义的方法,通常使用工厂方法的返回值
factoryMethod:工厂方法将客户(也就是超类中的代码,列入orderPizza())和实际创建具体产品的代码分割开来
type:工厂方法可能需要/不需要参数来制定所要的产品
&lt;/code&gt;&lt;/pre&gt;&lt;h1 id="项目地址"&gt;&lt;strong&gt;项目地址&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://github.com/jimersylee/DesignPattern"&gt;java设计模式实现&lt;/a&gt; 如果觉得有点收获,记得在项目上点star哦!&lt;/p&gt;</description></item><item><title>设计模式之观察者模式</title><link>https://blog.jimersylee.com/posts/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E4%B9%8B%E8%A7%82%E5%AF%9F%E8%80%85%E6%A8%A1%E5%BC%8F/</link><pubDate>Wed, 08 Apr 2015 09:36:00 +0000</pubDate><guid>https://blog.jimersylee.com/posts/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E4%B9%8B%E8%A7%82%E5%AF%9F%E8%80%85%E6%A8%A1%E5%BC%8F/</guid><description>&lt;h1 id="观察者模式observer"&gt;&lt;strong&gt;观察者模式(Observer)&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;让你的对象知悉现况&lt;/p&gt;
&lt;p&gt;使用自定义的Subject(主题)与Observer(观察者模式)&lt;/p&gt;
&lt;p&gt;设计原则&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;找出程序中会变化的方面,然后将其和固定不变的部分分离&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;在观察者模式中,会改变的事主题的状态,以及观察者的数目和类型.用这个模式,你可以改变依赖于主题状态的对象,却不改变主题.这就叫提前规划&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;针对接口编程,不针对实现编程&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;主题与观察者都使用接口:观察者利用主题的接口向主题注册,二主题利用观察者接口通知观察者.这样可以让两者之前运作正常,同时具有松耦合的优点&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;多用组合,少用继承&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;观察者模式利用&amp;quot;组合&amp;quot;将许多观察者组合进主题中.对象之前的这种关系不是通过继承产生的,而是在运行时利用组合的方式而产生的.&lt;/p&gt;
&lt;h1 id="自己实现观察者模式"&gt;&lt;strong&gt;自己实现观察者模式&lt;/strong&gt;&lt;/h1&gt;
&lt;h1 id="我们先定义主题接口"&gt;&lt;strong&gt;我们先定义主题接口&lt;/strong&gt;&lt;/h1&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;/**
* 主题接口
*/publicinterfaceSubject {
publicvoidregisterObserver(Observer o);
publicvoidremoveObserver(Observer o);
publicvoidnotifyObservers();
}
&lt;/code&gt;&lt;/pre&gt;&lt;h1 id="定义观察者接口"&gt;&lt;strong&gt;定义观察者接口&lt;/strong&gt;&lt;/h1&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;/**
* 观察者接口
*/publicinterfaceObserver {
publicvoidupdate(float temp,float humidity,float pressure);
}
&lt;/code&gt;&lt;/pre&gt;&lt;h1 id="显示元素接口"&gt;&lt;strong&gt;显示元素接口&lt;/strong&gt;&lt;/h1&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;/**
* 显示元素接口
*/publicinterfaceDisplayElement {
publicvoiddisplay();
}
&lt;/code&gt;&lt;/pre&gt;&lt;h1 id="编写公告板实现实现了观察者接口与显示元素接口"&gt;&lt;strong&gt;编写公告板实现,实现了观察者接口与显示元素接口&lt;/strong&gt;&lt;/h1&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;/**
* 公告板实现
*/publicclassCurrentConditionDisplayimplementsObserver,DisplayElement {
privatefloat temperature;
privatefloat humidity;
private Subject weatherData;
/**
* 构造器需要weatherData对象(也就是主题)作为注册之用
* @param weatherData:天气对象
*/publicCurrentConditionDisplay(Subject weatherData){
this.weatherData=weatherData;
weatherData.registerObserver(this);
}
/**
* display()方法就只是把最近的问的和湿度显示出来
*/@Override
publicvoiddisplay() {
System.out.println(&amp;#34;Current conditions:&amp;#34;+temperature+&amp;#34;F degree and &amp;#34;+humidity+&amp;#34;% humidity&amp;#34;);
}
/**
* 当update被调用时,我们把温度和湿度保存起来,然后调用display
* @param temp
* @param humidity
* @param pressure
*/@Override
publicvoidupdate(float temp,float humidity,float pressure) {
this.temperature=temp;
this.humidity=humidity;
display();
}
}
&lt;/code&gt;&lt;/pre&gt;&lt;h1 id="天气数据实现主题接口"&gt;&lt;strong&gt;天气数据实现主题接口&lt;/strong&gt;&lt;/h1&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;import java.util.ArrayList;
/**
* 天气数据类实现了Subject(主题)接口
*/publicclassWeatherDataimplementsSubject {
private ArrayList&amp;lt;Observer&amp;gt; observers;
privatefloat temperature;
privatefloat humidity;
privatefloat pressure;
publicWeatherData(){
observers=new ArrayList&amp;lt;&amp;gt;();
}
@Override
publicvoidregisterObserver(Observer o) {
observers.add(o);
}
@Override
publicvoidremoveObserver(Observer o) {
int i=observers.indexOf(o);
if(i&amp;gt;=0){
observers.remove(i);
}
}
@Override
publicvoidnotifyObservers() {
for (Observer observer : observers) {
observer.update(temperature, humidity, pressure);
}
}
/**
* 此方法会在气象值变化时被调用
*/publicvoidmeasurementsChanged(){
notifyObservers();
}
publicvoidsetMeasurements(float temperature,float humidity,float pressure){
this.temperature=temperature;
this.humidity=humidity;
this.pressure=pressure;
measurementsChanged();
}
}
&lt;/code&gt;&lt;/pre&gt;&lt;h1 id="来个测试吧"&gt;&lt;strong&gt;来个测试吧&lt;/strong&gt;&lt;/h1&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;publicclass WeatherStation {
publicstaticvoidmain(String[] args){
WeatherData weatherData=new WeatherData();
CurrentConditionDisplay currentConditionDisplay=new CurrentConditionDisplay(weatherData);
weatherData.setMeasurements(80,65,30.4f);
}
}
#输出
Current conditions:80.0F degree and 65.0% humidity
&lt;/code&gt;&lt;/pre&gt;&lt;h1 id="使用java自带的observer"&gt;&lt;strong&gt;使用java自带的Observer&lt;/strong&gt;&lt;/h1&gt;
&lt;h1 id="定义显示元素接口"&gt;&lt;strong&gt;定义显示元素接口&lt;/strong&gt;&lt;/h1&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;package Observable;
publicinterfaceDisplayElement {
publicvoiddisplay();
}
&lt;/code&gt;&lt;/pre&gt;&lt;h1 id="实现观察者接口和显示元素接口"&gt;&lt;strong&gt;实现观察者接口和显示元素接口&lt;/strong&gt;&lt;/h1&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;package Observable;
import java.util.Observable;
import java.util.Observer;
/**
* 天气状况布告板
* Created by jimersylee on
*/publicclassCurrentConditionDisplayimplementsObserver,DisplayElement {
Observable observable;
privatefloat temperature;
privatefloat humidity;
publicCurrentConditionDisplay(Observable observable){
this.observable=observable;
observable.addObserver(this);
}
publicvoidupdate(Observable obs,Object arg){
if(obsinstanceof WeatherData){
WeatherData weatherData=(WeatherData)obs;
this.temperature=weatherData.getTemperature();
this.humidity=weatherData.getHumidity();
display();
}
}
publicvoiddisplay(){
System.out.println(&amp;#34;Current conditions:&amp;#34;+temperature+&amp;#34;F degrees and &amp;#34;+humidity+&amp;#34;% humidity&amp;#34;);
}
}
&lt;/code&gt;&lt;/pre&gt;&lt;h1 id="实现观察者抽象类"&gt;&lt;strong&gt;实现观察者抽象类&lt;/strong&gt;&lt;/h1&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;package Observable;
import java.util.Observable;
/**
* 使用java.util内置的观察者模式实现
* Created by jimersylee
*/publicclassWeatherDataextendsObservable {
privatefloat temperature;
privatefloat humidity;
privatefloat pressure;
publicWeatherData(){
}
publicvoidmeasurementsChanged(){
setChanged();
notifyObservers();
}
publicfloatgetTemperature(){
return temperature;
}
publicfloatgetHumidity(){
return humidity;
}
publicfloatgetPressure(){
return pressure;
}
publicvoidsetMeasurements(float temperature,float humidity,float pressure){
this.temperature=temperature;
this.humidity=humidity;
this.pressure=pressure;
measurementsChanged();
}
}
&lt;/code&gt;&lt;/pre&gt;&lt;h1 id="写个测试吧"&gt;&lt;strong&gt;写个测试吧&lt;/strong&gt;&lt;/h1&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;package Observable;
publicclass WeatherStation {
publicstaticvoidmain(String[] args){
WeatherData weatherData=new WeatherData();
CurrentConditionDisplay currentConditionDisplay=new CurrentConditionDisplay(weatherData);
weatherData.setMeasurements(80,30,33.2f);
}
}
#输出
Current conditions:80.0F degrees and 30.0% humidity
&lt;/code&gt;&lt;/pre&gt;&lt;h1 id="项目地址"&gt;&lt;strong&gt;项目地址&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://github.com/jimersylee/DesignPattern"&gt;java设计模式实现&lt;/a&gt; 如果觉得有点收获,记得在项目上点star哦!&lt;/p&gt;</description></item><item><title>设计模式之面向接口</title><link>https://blog.jimersylee.com/posts/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E4%B9%8B%E9%9D%A2%E5%90%91%E6%8E%A5%E5%8F%A3/</link><pubDate>Sat, 14 Mar 2015 09:33:00 +0000</pubDate><guid>https://blog.jimersylee.com/posts/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E4%B9%8B%E9%9D%A2%E5%90%91%E6%8E%A5%E5%8F%A3/</guid><description>&lt;h1 id="软件开发的一个不变真理"&gt;&lt;strong&gt;软件开发的一个不变真理&lt;/strong&gt;&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;不变的就是变化&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;驱动改变的因素很多.找出你的应用中需要改变代码的原因&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;用户需要新的功能&lt;/li&gt;
&lt;li&gt;需要推出新的活动&lt;/li&gt;
&lt;li&gt;应用改版&lt;/li&gt;
&lt;li&gt;为了更好的性能&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;继承不能很好的解决问题,因为对象的行为在子类里不断地改变,并且让所有子类都有这些行为是不恰当的. 使用Fooable等接口,只用能实现的类才继承Fooable接口,但是java接口不具有实现代码,所以继承接口无法达到代码的复用.&lt;/p&gt;
&lt;p&gt;引出一个&lt;strong&gt;设计原则&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;找出应用中可能需要变化之处,把它独立出来,不要和那些不需要变化的代码混在一起&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;设计原则&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;针对接口编程,而不是针对实现编程&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h1 id="假设有很多鸭子有真鸭模型鸭如何实现他们的行为呢"&gt;&lt;strong&gt;假设有很多鸭子,有真鸭,模型鸭,如何实现他们的行为呢?&lt;/strong&gt;&lt;/h1&gt;
&lt;h1 id="先定义个一个抽象的duck类"&gt;&lt;strong&gt;先定义个一个抽象的Duck类&lt;/strong&gt;&lt;/h1&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;/**
* 鸭子的抽象类
*/publicabstractclassDuck{
private String _headColor=&amp;#34;yellow&amp;#34;;//Duck对象必备的属性public Stringget_headColor() {
return _headColor;
}
publicvoidset_headColor(String _headColor) {
this._headColor = _headColor;
}
public IFlyBehavior flyBehavior;//为行为接口类型声明引用变量,所有鸭子子类都继承他们public IFlyBehaviorgetFlyBehavior() {
return flyBehavior;
}
publicvoidsetFlyBehavior(IFlyBehavior flyBehavior) {
this.flyBehavior = flyBehavior;
}
public IQuackBehaviorgetQuackBehavior() {
return quackBehavior;
}
publicvoidsetQuackBehavior(IQuackBehavior quackBehavior) {
this.quackBehavior = quackBehavior;
}
public IQuackBehavior quackBehavior;//同上publicDuck(){
}
publicvoidperformQuack(){
quackBehavior.quack();//委托给行为类
}
publicvoidperformFly(){
flyBehavior.fly();//委托给行为类
}
publicabstractvoiddisplay();
/**
* Duck必备的行为
*/publicvoidswim(){
System.out.println(&amp;#34;All ducks float,even decoys!&amp;#34;);
}
}
&lt;/code&gt;&lt;/pre&gt;&lt;h1 id="绿头鸭继承duck"&gt;&lt;strong&gt;绿头鸭继承Duck&lt;/strong&gt;&lt;/h1&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;/**
* 绿头鸭类
*/publicclassMallardDuckextendsDuck {
publicMallardDuck(){
quackBehavior=new Quack();//绿头鸭使用Quack类处理叫,所以当performQuack()被调用时,叫的职责被委托给Quack
flyBehavior=new FlyWithWings();//同理
}
publicvoiddisplay(){
System.out.println(&amp;#34;I&amp;#39;m a real Mallard duck&amp;#34;);
}
}
&lt;/code&gt;&lt;/pre&gt;&lt;h1 id="模型鸭"&gt;&lt;strong&gt;模型鸭&lt;/strong&gt;&lt;/h1&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;/*
* 模型鸭
*/publicclassModelDuckextendsDuck {
publicModelDuck(){
flyBehavior=new FlyNoWay();//一开始,模型鸭不会飞
quackBehavior=new Quack();//一开始,模型鸭会呱呱叫
}
@Override
publicvoiddisplay() {
}
}
&lt;/code&gt;&lt;/pre&gt;&lt;h1 id="鸭子的鸣叫行为接口类"&gt;&lt;strong&gt;鸭子的鸣叫行为接口类&lt;/strong&gt;&lt;/h1&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;/**
* 叫行为接口类
*/publicinterfaceIQuackBehavior{
publicvoidquack();
}
&lt;/code&gt;&lt;/pre&gt;&lt;h1 id="鸭子的飞行行为接口类"&gt;&lt;strong&gt;鸭子的飞行行为接口类&lt;/strong&gt;&lt;/h1&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;/**
* 飞行行为接口类
*/publicinterfaceIFlyBehavior{
publicvoidfly();
}
&lt;/code&gt;&lt;/pre&gt;&lt;h1 id="各种实现了飞行行为的实现类"&gt;&lt;strong&gt;各种实现了飞行行为的实现类&lt;/strong&gt;&lt;/h1&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;/**
* 这是飞行行为的实现,给真会飞的鸭子用
*/publicclassFlyWithWingsimplementsIFlyBehavior {
@Override
publicvoidfly() {
System.out.println(&amp;#34;fly with wings&amp;#34;);
}
}
/**
* 火箭动力的飞行行为
*/publicclassFlyWithRocketimplementsIFlyBehavior {
@Override
publicvoidfly() {
System.out.println(&amp;#34;I&amp;#39;m flying with a rocket!&amp;#34;);
}
}
/**
* 这是飞行行为的实现,给不会飞的鸭子用
*/publicclassFlyNoWayimplementsIFlyBehavior {
@Override
publicvoidfly() {
System.out.println(&amp;#34;I can&amp;#39;t fly!&amp;#34;);
}
}
&lt;/code&gt;&lt;/pre&gt;&lt;h1 id="各种实现了鸣叫行为的实现类"&gt;&lt;strong&gt;各种实现了鸣叫行为的实现类&lt;/strong&gt;&lt;/h1&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;/**
* 叫的实现,给会呱呱叫的鸭子用
*/publicclassQuackimplementsIQuackBehavior {
@Override
publicvoidquack() {
System.out.println(&amp;#34;Quack,gua gua gua!&amp;#34;);
}
}
/**
* 鸭子叫的沉默实现,给不会叫的鸭子用
*/publicclassQuackMuteimplementsIQuackBehavior {
@Override
publicvoidquack() {
System.out.println(&amp;#34;&amp;lt;&amp;lt;Silence&amp;gt;&amp;gt;&amp;#34;);
}
}
&lt;/code&gt;&lt;/pre&gt;&lt;h1 id="测试我们的鸭子们"&gt;&lt;strong&gt;测试我们的鸭子们&lt;/strong&gt;&lt;/h1&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;publicclassTest {
publicstatic void main(String args[]){
MallardDuck mallardDuck=new MallardDuck();
mallardDuck.display();
mallardDuck.performFly();
mallardDuck.performQuack();
//搞一只模型鸭
ModelDuck md=new ModelDuck();
md.performFly();//第一次调用飞行时,委托给FlyNoWay
md.setFlyBehavior(new FlyWithRocket());//继承来的设置飞行模式的方法,给予火箭动力
md.performFly();//现在能飞啦~
}
}
//输出
Bobble gobble
I&amp;#39;m flying a short distance
gua!gua!gua!
I&amp;#39;m flying a long distance
Bobble gobble
I&amp;#39;m flying a short distance
I&amp;#39;m flying a short distance
I&amp;#39;m flying a short distance
I&amp;#39;m flying a short distance
I&amp;#39;m flying a short distance
&lt;/code&gt;&lt;/pre&gt;&lt;h1 id="项目地址"&gt;&lt;strong&gt;项目地址&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://github.com/jimersylee/DesignPattern"&gt;java设计模式实现&lt;/a&gt; 如果觉得有点收获,记得在项目上点star哦!&lt;/p&gt;</description></item><item><title>linux系统命令</title><link>https://blog.jimersylee.com/posts/linux%E7%B3%BB%E7%BB%9F%E5%91%BD%E4%BB%A4/</link><pubDate>Fri, 14 Nov 2014 09:31:00 +0000</pubDate><guid>https://blog.jimersylee.com/posts/linux%E7%B3%BB%E7%BB%9F%E5%91%BD%E4%BB%A4/</guid><description>&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;文件和目录:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# cd /home 进入 &amp;#39;/home&amp;#39; 目录&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# cd .. 返回上一级目录&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# cd ../.. 返回上两级目录&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# cd - 返回上次所在目录&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# cp file1 file2 将file1复制为file2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# cp -a dir1 dir2 复制一个目录&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# cp -a /tmp/dir1 . 复制一个目录到当前工作目录（.代表当前目录）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# ls 查看目录中的文件&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# ls -a 显示隐藏文件&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# ls -l 显示详细信息&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# ls -lrt 按时间显示文件（l表示详细列表，r表示反向排序，t表示按时间排序）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# pwd 显示工作路径&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# mkdir dir1 创建 &amp;#39;dir1&amp;#39; 目录&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# mkdir dir1 dir2 同时创建两个目录&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# mkdir -p /tmp/dir1/dir2 创建一个目录树&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# mv dir1 dir2 移动/重命名一个目录&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# rm -f file1 删除 &amp;#39;file1&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# rm -rf dir1 删除 &amp;#39;dir1&amp;#39; 目录及其子目录内容&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;查看文件内容:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# cat file1 从第一个字节开始正向查看文件的内容&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# head -2 file1 查看一个文件的前两行&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# more file1 查看一个长文件的内容&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# tac file1 从最后一行开始反向查看一个文件的内容&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# tail -3 file1 查看一个文件的最后三行&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;文本处理:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# grep str /tmp/test 在文件 &amp;#39;/tmp/test&amp;#39; 中查找 &amp;#34;str&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# grep ^str /tmp/test 在文件 &amp;#39;/tmp/test&amp;#39; 中查找以 &amp;#34;str&amp;#34; 开始的行&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# grep [0-9] /tmp/test 查找 &amp;#39;/tmp/test&amp;#39; 文件中所有包含数字的行&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# grep str -r /tmp/* 在目录 &amp;#39;/tmp&amp;#39; 及其子目录中查找 &amp;#34;str&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# diff file1 file2 找出两个文件的不同处&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# sdiff file1 file2 以对比的方式显示两个文件的不同&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;查找:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# find / -name file1 从 &amp;#39;/&amp;#39; 开始进入根文件系统查找文件和目录&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# find / -user user1 查找属于用户 &amp;#39;user1&amp;#39; 的文件和目录&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# find /home/user1 -name \*.bin 在目录 &amp;#39;/ home/user1&amp;#39; 中查找以 &amp;#39;.bin&amp;#39; 结尾的文件&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# find /usr/bin -type f -atime +100 查找在过去100天内未被使用过的执行文件&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# find /usr/bin -type f -mtime -10 查找在10天内被创建或者修改过的文件&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# locate \*.ps 寻找以 &amp;#39;.ps&amp;#39; 结尾的文件，先运行 &amp;#39;updatedb&amp;#39; 命令&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# find -name &amp;#39;*.[ch]&amp;#39; | xargs grep -E &amp;#39;expr&amp;#39; 在当前目录及其子目录所有.c和.h文件中查找 &amp;#39;expr&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# find -type f -print0 | xargs -r0 grep -F &amp;#39;expr&amp;#39; 在当前目录及其子目录的常规文件中查找 &amp;#39;expr&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# find -maxdepth 1 -type f | xargs grep -F &amp;#39;expr&amp;#39; 在当前目录中查找 &amp;#39;expr&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;压缩和解压:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# bzip2 file1 压缩 file1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# bunzip2 file1.bz2 解压 file1.bz2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# gzip file1 压缩 file1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# gzip -9 file1 最大程度压缩 file1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# gunzip file1.gz 解压 file1.gz&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# tar -cvf archive.tar file1 把file1打包成 archive.tar&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;（-c: 建立压缩档案；-v: 显示所有过程；-f: 使用档案名字，是必须的，是最后一个参数）
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# tar -cvf archive.tar file1 dir1 把 file1，dir1 打包成 archive.tar&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# tar -tf archive.tar 显示一个包中的内容&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# tar -xvf archive.tar 释放一个包&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# tar -xvf archive.tar -C /tmp 把压缩包释放到 /tmp目录下&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# zip file1.zip file1 创建一个zip格式的压缩包&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# zip -r file1.zip file1 dir1 把文件和目录压缩成一个zip格式的压缩包&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# unzip file1.zip 解压一个zip格式的压缩包到当前目录&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# unzip test.zip -d /tmp/ 解压一个zip格式的压缩包到 /tmp 目录&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;yum工具:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# yum -y install [package] 下载并安装一个rpm包&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# yum localinstall [package.rpm] 安装一个rpm包，使用你自己的软件仓库解决所有依赖关系&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# yum -y update 更新当前系统中安装的所有rpm包&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# yum update [package] 更新一个rpm包&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# yum remove [package] 删除一个rpm包&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# yum list 列出当前系统中安装的所有包&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# yum search [package] 在rpm仓库中搜寻软件包&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# yum clean [package] 清除缓存目录（/var/cache/yum）下的软件包&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# yum clean headers 删除所有头文件&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# yum clean all 删除所有缓存的包和头文件&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;网络:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# ifconfig eth0 显示一个以太网卡的配置&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# ifconfig eth0 192.168.1.1 netmask 255.255.255.0 配置网卡的IP地址&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# ifdown eth0 禁用 &amp;#39;eth0&amp;#39; 网络设备&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# ifup eth0 启用 &amp;#39;eth0&amp;#39; 网络设备&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# iwconfig eth1 显示一个无线网卡的配置&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# iwlist scan 显示无线网络&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# ip addr show 显示网卡的IP地址&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;其他:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# su - 切换到root权限（与su有区别）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# shutdown -h now 关机&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# shutdown -r now 重启&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# top 罗列使用CPU资源最多的linux任务 （输入q退出）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# pstree 以树状图显示程序&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# man ping 查看参考手册（例如ping 命令）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# passwd 修改密码&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# df -h 显示磁盘的使用情况&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# cal -3 显示前一个月，当前月以及下一个月的月历&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# cal 10 1988 显示指定月，年的月历&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# date --date &amp;#39;1970-01-01 UTC 1427888888 seconds&amp;#39; 把一相对于1970-01-01 00:00的秒数转换成时间&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Ctrl + u 删除光标之前到行首的字符
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Ctrl + k 删除光标之前到行尾的字符
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Ctrl + c 取消当前行输入的命令，相当于Ctrl + Break
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Ctrl + a 光标移动到行首（ahead of line），相当于通常的Home键
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Ctrl + e 光标移动到行尾（end of line）
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Ctrl + f 光标向前（forward）移动一个字符位置
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Ctrl + b 光标往回（backward）移动一个字符位置
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Ctrl + l 清屏，相当于执行clear命令
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Ctrl + r 显示:号提示，根据用户输入查找相关历史命令（reverse-i-search）
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Ctrl + w 删除从光标位置前到当前所处单词（word）的开头
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Ctrl + t 交换光标位置前的两个字符
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Ctrl + y 粘贴最后一次被删除的单词
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Ctrl + Alt + d 显示桌面
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Alt + b 光标往回（backward）移动到前一个单词
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Alt + d 删除从光标位置到当前所处单词的末尾
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Alt + F2 运行
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Alt + F4 关闭当前窗口
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Alt + F9 最小化当前窗口
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Alt + F10 最大化当前窗口
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Alt + Tab 切换窗口
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Alt +按住左键 移动窗口（或在最下面的任务栏滚动鼠标滑轮）
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;鼠标中间键&lt;span style="color:#f92672"&gt;]&lt;/span&gt; 粘贴突出显示的文本。使用鼠标左键来选择文本。把光标指向想粘贴文本的地方。点击鼠标中间键来粘贴。
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;Tab&lt;span style="color:#f92672"&gt;]&lt;/span&gt; 命令行自动补全。使用 shell 提示时可使用这一方式。键入命令或文件名的前几个字符，然后按 &lt;span style="color:#f92672"&gt;[&lt;/span&gt;Tab&lt;span style="color:#f92672"&gt;]&lt;/span&gt; 键，它会自动补全命令或显示匹配键入字符的所有命令。
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;在桌面或文件管理器中直接按 / 就可以输入位置，打开文件管理器。
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;快速搜索：在 vi 或 Firefox 中直接按 / 即可进入搜索状态。
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;网站链接和图片可直接拖放到桌面或者目录，可以马上下载。
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;直接将文件管理器中的文件拖到终端中就可以在终端中得到完整的路径名。
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;在滚动条的空白处点击鼠标中键，屏幕即滚动到那个地方。
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>养成好习惯</title><link>https://blog.jimersylee.com/posts/%E5%85%BB%E6%88%90%E5%A5%BD%E4%B9%A0%E6%83%AF/</link><pubDate>Wed, 20 Aug 2014 09:28:00 +0000</pubDate><guid>https://blog.jimersylee.com/posts/%E5%85%BB%E6%88%90%E5%A5%BD%E4%B9%A0%E6%83%AF/</guid><description>&lt;p&gt;安装了一个新的app 叫微习惯 督促自己每天都做一些事 今天努力完成了所有小事 就差一个30分钟的写作了 于是现在在写 每做完一件事然后打勾 还是很有成就感的 父母在我很小的时候就教育我 说人生最难的就是坚持 小时候不以为意 现在明白了 人都是倾向于虎头蛇尾的 坚持的确是件最难的事 但是 我希望可以改变 可以从一个个的小习惯开始 改变自己 加油 明天早点起床&lt;/p&gt;</description></item><item><title>游泳杂感</title><link>https://blog.jimersylee.com/posts/%E6%B8%B8%E6%B3%B3%E6%9D%82%E6%84%9F/</link><pubDate>Wed, 23 Jul 2014 09:27:00 +0000</pubDate><guid>https://blog.jimersylee.com/posts/%E6%B8%B8%E6%B3%B3%E6%9D%82%E6%84%9F/</guid><description>&lt;p&gt;七月二十三日， 晴，好热&lt;/p&gt;
&lt;p&gt;于是去游泳。&lt;/p&gt;
&lt;p&gt;一个人，一条裤衩，不戴泳镜，更不需要救生圈。 地点是泄洪坝底下下冲刷而成的水潭，虽没有桃花潭水深千尺，但是十尺还是有的。前几日连绵大雨，所以泄洪了，于是水潭中都是新鲜的水库水，经过水的冲刷，现在水底很清澈，可以直接看到水底。也没有水藻。非常适合游泳呐。 在靠近岸边的地方下水，岸边还是很浅的，踩着圆润的水底砂石，仿佛有种回到童年的感觉。那个瘦瘦小小的小孩，双手撑在河底，双脚扑腾着学习游泳的小孩。嘴巴进水，鼻子进水，咳嗽，鼻酸，长时间潜水后强烈想要呼吸的感觉，潜到深处胸腔感受到的压力，以及水中唯一听得到的隆隆声，虽历历在目，声声在耳，却是多久没感受过了。&lt;/p&gt;
&lt;p&gt;自由泳，蛙泳，仰泳，潜泳，狗刨式，全部来一套。原来游泳这个技能，一旦学会，就完全不会忘呢。什么学会呢，先天技能，幼时就在子宫里游来游去。 水底的世界就像是近视眼看到的世界一样，模糊，但是色彩斑斓。尤其对白色的物体尤为敏感。白色的石头，闪着光。随意潜入水中，就可以捞起一些石头，这是幼时最喜爱的游泳游戏。可是现在，却没有幼时的欣喜。&lt;/p&gt;</description></item><item><title>理解Linux系统负荷load average</title><link>https://blog.jimersylee.com/posts/%E7%90%86%E8%A7%A3linux%E7%B3%BB%E7%BB%9F%E8%B4%9F%E8%8D%B7load-average/</link><pubDate>Tue, 28 Jan 2014 10:27:00 +0000</pubDate><guid>https://blog.jimersylee.com/posts/%E7%90%86%E8%A7%A3linux%E7%B3%BB%E7%BB%9F%E8%B4%9F%E8%8D%B7load-average/</guid><description>&lt;h1 id="理解linux系统负荷load-average"&gt;理解Linux系统负荷load average&lt;/h1&gt;
&lt;p&gt;Update time: July 21, 2022 10:27 AM&lt;/p&gt;
&lt;h1 id="一查看系统负荷"&gt;&lt;strong&gt;一、查看系统负荷&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;如果你的电脑很慢，你或许想查看一下，它的工作量是否太大了。 在Linux系统中，我们一般使用uptime命令查看（w命令和top命令也行）。（另外，它们在苹果公司的Mac电脑上也适用。） 你在终端窗口键入uptime，系统会返回一行信息。&lt;/p&gt;
&lt;p&gt;这行信息的后半部分，显示&amp;quot;load average&amp;quot;，它的意思是&amp;quot;系统的平均负荷&amp;quot;，里面有三个数字，我们可以从中判断系统负荷是大还是小。&lt;/p&gt;
&lt;p&gt;为什么会有三个数字呢？你从手册中查到，它们的意思分别是1分钟、5分钟、15分钟内系统的平均负荷。 如果你继续看手册，它还会告诉你，当CPU完全空闲的时候，平均负荷为0；当CPU工作量饱和的时候，平均负荷为1。 那么很显然，&amp;ldquo;load average&amp;quot;的值越低，比如等于0.2或0.3，就说明电脑的工作量越小，系统负荷比较轻。 但是，什么时候能看出系统负荷比较重呢？等于1的时候，还是等于0.5或等于1.5的时候？如果1分钟、5分钟、15分钟三个值不一样，怎么办？&lt;/p&gt;
&lt;h1 id="二一个类比"&gt;&lt;strong&gt;二、一个类比&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;判断系统负荷是否过重，必须理解load average的真正含义。下面，我根据&amp;quot;Understanding Linux CPU Load&amp;quot;这篇文章，尝试用最通俗的语言，解释这个问题。 首先，假设最简单的情况，你的电脑只有一个CPU，所有的运算都必须由这个CPU来完成。 那么，我们不妨把这个CPU想象成一座大桥，桥上只有一根车道，所有车辆都必须从这根车道上通过。（很显然，这座桥只能单向通行。） 系统负荷为0，意味着大桥上一辆车也没有。&lt;/p&gt;
&lt;p&gt;系统负荷为0.5，意味着大桥一半的路段有车。&lt;/p&gt;
&lt;p&gt;系统负荷为1.0，意味着大桥的所有路段都有车，也就是说大桥已经&amp;quot;满&amp;quot;了。但是必须注意的是，直到此时大桥还是能顺畅通行的。&lt;/p&gt;
&lt;p&gt;系统负荷为1.7，意味着车辆太多了，大桥已经被占满了（100%），后面等着上桥的车辆为桥面车辆的70%。以此类推，系统负荷2.0，意味着等待上桥的车辆与桥面的车辆一样多；系统负荷3.0，意味着等待上桥的车辆是桥面车辆的2倍。总之，当系统负荷大于1，后面的车辆就必须等待了；系统负荷越大，过桥就必须等得越久。&lt;/p&gt;
&lt;p&gt;CPU的系统负荷，基本上等同于上面的类比。大桥的通行能力，就是CPU的最大工作量；桥梁上的车辆，就是一个个等待CPU处理的进程（process）。 如果CPU每分钟最多处理100个进程，那么系统负荷0.2，意味着CPU在这1分钟里只处理20个进程；系统负荷1.0，意味着CPU在这1分钟里正好处理100个进程；系统负荷1.7，意味着除了CPU正在处理的100个进程以外，还有70个进程正排队等着CPU处理。 为了电脑顺畅运行，系统负荷最好不要超过1.0，这样就没有进程需要等待了，所有进程都能第一时间得到处理。很显然，1.0是一个关键值，超过这个值，系统就不在最佳状态了，你要动手干预了。&lt;/p&gt;
&lt;h1 id="三系统负荷的经验法则"&gt;&lt;strong&gt;三、系统负荷的经验法则&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;1.0是系统负荷的理想值吗？ 不一定，系统管理员往往会留一点余地，当这个值达到0.7，就应当引起注意了。经验法则是这样的： 当系统负荷持续大于0.7，你必须开始调查了，问题出在哪里，防止情况恶化。 当系统负荷持续大于1.0，你必须动手寻找解决办法，把这个值降下来。 当系统负荷达到5.0，就表明你的系统有很严重的问题，长时间没有响应，或者接近死机了。你不应该让系统达到这个值。&lt;/p&gt;
&lt;h1 id="四多处理器"&gt;&lt;strong&gt;四、多处理器&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;上面，我们假设你的电脑只有1个CPU。如果你的电脑装了2个CPU，会发生什么情况呢？ 2个CPU，意味着电脑的处理能力翻了一倍，能够同时处理的进程数量也翻了一倍。 还是用大桥来类比，两个CPU就意味着大桥有两根车道了，通车能力翻倍了。&lt;/p&gt;
&lt;p&gt;所以，2个CPU表明系统负荷可以达到2.0，此时每个CPU都达到100%的工作量。推广开来，n个CPU的电脑，可接受的系统负荷最大为n.0。&lt;/p&gt;
&lt;h1 id="五多核处理器"&gt;&lt;strong&gt;五、多核处理器&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;芯片厂商往往在一个CPU内部，包含多个CPU核心，这被称为多核CPU。 在系统负荷方面，多核CPU与多CPU效果类似，所以考虑系统负荷的时候，必须考虑这台电脑有几个CPU、每个CPU有几个核心。然后，把系统负荷除以总的核心数，只要每个核心的负荷不超过1.0，就表明电脑正常运行。 怎么知道电脑有多少个CPU核心呢？ &amp;ldquo;cat /proc/cpuinfo&amp;quot;命令，可以查看CPU信息。&amp;ldquo;grep -c &amp;lsquo;model name&amp;rsquo; /proc/cpuinfo&amp;quot;命令，直接返回CPU的总核心数。&lt;/p&gt;
&lt;h1 id="六最佳观察时长"&gt;&lt;strong&gt;六、最佳观察时长&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;最后一个问题，&amp;ldquo;load average&amp;quot;一共返回三个平均值&amp;mdash;-1分钟系统负荷、5分钟系统负荷，15分钟系统负荷，&amp;mdash;-应该参考哪个值？ 如果只有1分钟的系统负荷大于1.0，其他两个时间段都小于1.0，这表明只是暂时现象，问题不大。 如果15分钟内，平均系统负荷大于1.0（调整CPU核心数之后），表明问题持续存在，不是暂时现象。所以，你应该主要观察&amp;quot;15分钟系统负荷&amp;rdquo;，将它作为电脑正常运行的指标。&lt;/p&gt;</description></item><item><title>CentOS7安装Jenkins</title><link>https://blog.jimersylee.com/posts/centos7%E5%AE%89%E8%A3%85jenkins/</link><pubDate>Sun, 05 Jan 2014 09:24:00 +0000</pubDate><guid>https://blog.jimersylee.com/posts/centos7%E5%AE%89%E8%A3%85jenkins/</guid><description>&lt;p&gt;环境:CentOS7&lt;/p&gt;
&lt;p&gt;1.下载安装包 在https://jenkins.io/download/找到相应的包下载地址&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;wget https://pkg.jenkins.io/redhat/jenkins-2.76-1.1.noarch.rpm
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;2.安装包&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;sudo rpm -i jenkins-2.76-1.1.noarch.rpm
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;3.启动jenkins&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;sudo service jenkins start
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;4.配置nginx&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;vim /etc/nginx/conf.d/jenkins.conf
server {
2listen 443;
3 server_name jenkins.jimersylee.com;
4 ssl on;
5 ssl_certificate /data/ssl_cert/Nginx/1_jimersylee.com_bundle.crt;
6 ssl_certificate_key /data/ssl_cert/Nginx/2_jimersylee.com.key;
7 ssl_session_timeout 5m;
8 ssl_protocols TLSv1 TLSv1.1 TLSv1.2;#按照这个协议配置9 ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;#按照这个套件配置10 ssl_prefer_server_ciphers on;
11# root /data/www/www;12
13indexindex.htmlindex.htmindex.php;
14 location /
15 {
16 proxy_pass http://127.0.0.1:8080;
17 }
18
19 access_log /data/logs/jenkins/jenkins.log main;
20 }
21
22 server {
23listen 80;
24 server_name jenkins.jimersylee.com;
25 rewrite ^ https://$server_name$request_uri? permanent;
26 }
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;5.访问https://jenkins.jimersylee.com/ 发现没有账号密码,修改jenkins为不需要账号密码&lt;/p&gt;</description></item><item><title>20220823-&lt;谷歌的软件工程&gt;读后感</title><link>https://blog.jimersylee.com/posts/20220823-%E8%B0%B7%E6%AD%8C%E7%9A%84%E8%BD%AF%E4%BB%B6%E5%B7%A5%E7%A8%8B%E8%AF%BB%E5%90%8E%E6%84%9F/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://blog.jimersylee.com/posts/20220823-%E8%B0%B7%E6%AD%8C%E7%9A%84%E8%BD%AF%E4%BB%B6%E5%B7%A5%E7%A8%8B%E8%AF%BB%E5%90%8E%E6%84%9F/</guid><description>&lt;h1 id="前言"&gt;前言&lt;/h1&gt;
&lt;p&gt;近期,阅读了&amp;lt;&lt;a href="https://u.jd.com/7ISYFMp"&gt;谷歌的软件工程&lt;/a&gt;&amp;gt;,记录一下.&lt;/p&gt;
&lt;p&gt;我对谷歌这家公司还是比较好奇和欣赏的,不管都是对于拉里佩奇,还是现在阿尔法特(谷歌母公司)的CEO 桑达尔·皮查伊, 个人都非常敬佩.毕竟都是有真正实力的大佬.&lt;/p&gt;
&lt;p&gt;谷歌运行着目前世界上最大的服务器集群,这个不容置疑.我个人也非常好奇,如此庞大的规模的机器,他们如何调度,如何监控,我们这种小公司是否有可以借鉴的地方.因此,当我发现这本书的时候,我觉得这就是我一直寻找的书.&lt;/p&gt;
&lt;p&gt;其实在这之前,我已经看过&lt;a href="https://u.jd.com/7KSnc8z"&gt;&amp;lt;Sre google运维解密&amp;gt;&lt;/a&gt;,收获良多,我的DevOps概念就是从这本书中学来的.个人在之后的工作中也引入了这套工作流程,砍掉了运维工程师,由开发自己负责从开发部署,持续运维监控的全流程,开发人员反馈良好,接触到了很多之前不可能接触到的生产服务器,积累了宝贵的线上故障处理经验,培养了项目主人公的感觉.&lt;/p&gt;
&lt;p&gt;以下为书籍内容的摘抄,仅供参考.&lt;/p&gt;
&lt;h1 id="第一章"&gt;第一章&lt;/h1&gt;
&lt;h2 id="失败奖励"&gt;失败奖励&lt;/h2&gt;
&lt;p&gt;在谷歌X部门——该部门负责研究自动驾驶汽车和通过热气球提供互联网接入等 &amp;ldquo;登月计划&amp;rdquo;——故意将失败次数纳入其激励系统。人们会想出一些稀奇古怪的想法，同事们也会受到积极的鼓励尽快实现它们。每个人都会得到奖励（甚至是竞争），看看他们能在一段固定的时间内反驳或否定多少观点。只有当一个概念真的不能在白板上被所有同行揭穿时，它才能进入早期原型。&lt;/p&gt;
&lt;h2 id="无责的事后文化"&gt;无责的事后文化&lt;/h2&gt;
&lt;p&gt;在谷歌X部门——该部门负责研究自动驾驶汽车和通过热气球提供互联网接入等 &amp;ldquo;登月计划&amp;rdquo;——故意将失败次数纳入其激励系统。人们会想出一些稀奇古怪的想法，同事们也会受到积极的鼓励尽快实现它们。每个人都会得到奖励（甚至是竞争），看看他们能在一段固定的时间内反驳或否定多少观点。只有当一个概念真的不能在白板上被所有同行揭穿时，它才能进入早期原型。&lt;/p&gt;
&lt;h2 id="谷歌味儿"&gt;谷歌味儿&lt;/h2&gt;
&lt;p&gt;谷歌最终解决了这个问题，明确定义了我们所说的“谷歌特质”（Googleyness）——我们所寻找的一套属性和行为，代表了强大的领导力，体现了 &amp;ldquo;谦逊、尊重和信任&amp;rdquo;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;在模棱两可中茁壮成长&lt;/em&gt;
即使在环境不断变化的情况下，也能处理相互冲突的信息或方向，建立共识，并对问题做出改进。&lt;/li&gt;
&lt;li&gt;&lt;em&gt;重视反馈&lt;/em&gt;
谦虚优雅地接受和给出反馈，理解反馈对个人（和团队）发展的价值。&lt;/li&gt;
&lt;li&gt;&lt;em&gt;走出舒适区&lt;/em&gt;
能够设定宏伟的目标并去追求，即使有来自他人的抵制或惰性。&lt;/li&gt;
&lt;li&gt;&lt;em&gt;客户第一&lt;/em&gt;
对谷歌产品的用户抱有同情和尊重，并追求符合其最佳利益的行动。&lt;/li&gt;
&lt;li&gt;&lt;em&gt;关心团队&lt;/em&gt;
对同事抱有同情心和尊重，并积极主动地帮助他们，提高团队凝聚力。&lt;/li&gt;
&lt;li&gt;&lt;em&gt;做正确的事&lt;/em&gt;
对自己所做的一切有强烈的主人感；愿意做出困难或不易的决定以保护团队和产品的完整。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href="https://www.notion.so/8a4678c8b20844dd9fe2543fe8a378a0?pvs=21"&gt;每个专家都曾经是菜鸟：一个组织的成功取决于其员工的成长和投入。&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.notion.so/4e666e67b8e94df5aff0e8046254d72d?pvs=21"&gt;离开营地时要比你发现时更干净&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="如何激励人们记录工作"&gt;如何激励人们记录工作&lt;/h2&gt;
&lt;p&gt;传统上，鼓励工程师记录他们的工作可能是困难的。编写文档需要消耗编码的时间和精力，而且这些工作所带来的好处并不直接，大部分是由其他人获益的。鉴于许多人可以从少数人的时间中获益，像这样的不对称权衡对整个组织来说是好的，但如果没有好的激励措施，鼓励这样的行为是很有挑战性的。我们在第57页的 &amp;ldquo;激励和认可 &amp;ldquo;一节中讨论了其中的一些结构性激励。&lt;/p&gt;
&lt;h2 id="奖励方式"&gt;奖励方式&lt;/h2&gt;
&lt;p&gt;工作阶梯的期望是一种自上而下引导文化的方式，但文化也是自下而上形成的。在谷歌，同行奖金计划是我们拥抱自下而上文化的一种方式。同行奖金是一种货币奖励和正式认可，任何谷歌员工都可以将其授予任何其他谷歌员工，以表彰他们的超越性工作。例如，当Ravi将同行奖金发给Julia，因为她是一个邮件列表的顶级贡献者——定期回答问题，使许多读者受益，他公开承认她的知识共享工作及其对团队以外的影响。由于同行奖金是由员工驱动的，而不是由管理层驱动的，因此它们可以产生重要而强大的基层效应。&lt;/p&gt;
&lt;h2 id="第三章-知识分享-内容提要"&gt;第三章 知识分享 内容提要&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;心理安全是培养知识共享环境的基础。&lt;/li&gt;
&lt;li&gt;从小事做起：问问题，把事情写下来。&lt;/li&gt;
&lt;li&gt;让人们可以很容易地从专家和有记录的参考资料中获得他们需要的帮助。&lt;/li&gt;
&lt;li&gt;在系统的层面上，鼓励和奖励那些花时间去教授和扩大他们的专业知识，而不仅仅是他们自己、他们的团队或他们的组织。&lt;/li&gt;
&lt;li&gt;没有什么灵丹妙药：增强知识共享文化需要多种策略的结合，而最适合你的组织的确切组合可能会随着时间的推移而改变。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="第四章-公平工程"&gt;第四章 公平工程&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;偏见是默认的。&lt;/li&gt;
&lt;li&gt;多样性是正确设计综合用户群所必需的。&lt;/li&gt;
&lt;li&gt;包容性不仅对于改善代表不足的群体的招聘渠道至关重要，而且对于为所有人提供一个真正支持性的工作环境也至关重要。&lt;/li&gt;
&lt;li&gt;产品速度必须根据提供对所有用户真正有用的产品来评估。与其发布一个可能对某些用户造成伤害的产品，还不如放慢速度。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="第六章-规模优先"&gt;第六章 规模优先&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;至此，假设我们已经知道了领导的本质，那么到底什么才能让你提升为一个真正优秀的管理者呢？这就是我们这里想要讨论的，我们称之为“管理上的三个总是”：始终保持决断力，始终保持离开，始终保持扩张。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="第七章-测试工程效率"&gt;第七章 测试工程效率&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;如何测量软件过程
&lt;ul&gt;
&lt;li&gt;在谷歌，我们使用目标/信号/指标（GSM/ goal signal metric）框架来指导指标创建。&lt;/li&gt;
&lt;li&gt;&lt;em&gt;目标&lt;/em&gt;是一个期望的最终结果。它是根据你希望在高层次上理解的内容来表述的，不应包含对具体测量方法的引用。。&lt;/li&gt;
&lt;li&gt;&lt;em&gt;信号&lt;/em&gt;是你如何知道你已经实现了最终结果。信号是我们&lt;em&gt;想要&lt;/em&gt;衡量的东西，但它们本身可能是不可测量的。&lt;/li&gt;
&lt;li&gt;&lt;em&gt;指标&lt;/em&gt;是信号的代表。它是我们实际上可以测量的东西。它可能不是理想的测量，但它是我们认为足够接近的东西。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="第十章-文档"&gt;第十章 文档&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;工程师们越是把文档工作当作软件开发的必要任务之一，他们就越是不反感写文档的前期成本，也就越能获得长期的收益。此外，让文档工作变得更容易，可以减少这些前期成本。&lt;/li&gt;
&lt;li&gt;写文档的秘诀
&lt;ul&gt;
&lt;li&gt;5W,who,what,when. where, why&lt;/li&gt;
&lt;li&gt;who: 文档受众&lt;/li&gt;
&lt;li&gt;what: 确定文档用途的内容&lt;/li&gt;
&lt;li&gt;when: 何时确定本文件的创建、审查或更新时间&lt;/li&gt;
&lt;li&gt;where: 文档应该放在哪里&lt;/li&gt;
&lt;li&gt;why: 设定文件的目的&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="第十一章-测试概述"&gt;第十一章 测试概述&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;GWS的经验告诉我们的一个重要启示是，你不能仅仅依靠程序员的能力来避免产品缺陷。即使每个工程师只是偶尔写一些bug，当你有足够多的人在同一个项目上工作时，你也会被不断增长的缺陷列表所淹没。想象一下，一个假设的100人的团队，其工程师非常优秀，他们每个人每月只写一个bug。而这群了不起的工程师在每个工作日仍然会产生5个新的bug。更糟糕的是，在一个复杂的系统中，修复一个错误往往会导致另一个错误，因为工程师们会适配已知的bug并围绕它们编写代码。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;概要&lt;/p&gt;</description></item></channel></rss>