<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>工具 on Liangweidong's blog</title><link>https://liangweidonggood.github.io/categories/%E5%B7%A5%E5%85%B7/</link><description>Recent content in 工具 on Liangweidong's blog</description><generator>Hugo -- gohugo.io</generator><language>zh-cn</language><lastBuildDate>Mon, 15 Jan 2024 10:00:00 +0800</lastBuildDate><atom:link href="https://liangweidonggood.github.io/categories/%E5%B7%A5%E5%85%B7/index.xml" rel="self" type="application/rss+xml"/><item><title>Nginx 反向代理配置详解</title><link>https://liangweidonggood.github.io/p/nginx-config/</link><pubDate>Mon, 15 Jan 2024 10:00:00 +0800</pubDate><guid>https://liangweidonggood.github.io/p/nginx-config/</guid><description>&lt;p&gt;Nginx 是一款高性能的 HTTP 和反向代理服务器，几乎是后端架构的标配。本文记录常用的反向代理配置。&lt;/p&gt;
&lt;h2 id="最简单的反向代理"&gt;最简单的反向代理
&lt;/h2&gt;&lt;p&gt;将所有请求转发到后端应用服务器：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-nginx" data-lang="nginx"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;server_name&lt;/span&gt; &lt;span class="s"&gt;example.com&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="s"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;proxy_pass&lt;/span&gt; &lt;span class="s"&gt;http://127.0.0.1:3000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;Host&lt;/span&gt; &lt;span class="nv"&gt;$host&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;X-Real-IP&lt;/span&gt; &lt;span class="nv"&gt;$remote_addr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;X-Forwarded-For&lt;/span&gt; &lt;span class="nv"&gt;$proxy_add_x_forwarded_for&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;关键指令说明：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;proxy_pass&lt;/code&gt;：后端地址&lt;/li&gt;
&lt;li&gt;&lt;code&gt;proxy_set_header Host&lt;/code&gt;：传递原始域名&lt;/li&gt;
&lt;li&gt;&lt;code&gt;X-Real-IP&lt;/code&gt; / &lt;code&gt;X-Forwarded-For&lt;/code&gt;：让后端拿到真实客户端 IP&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="负载均衡"&gt;负载均衡
&lt;/h2&gt;&lt;p&gt;用 &lt;code&gt;upstream&lt;/code&gt; 块定义后端池：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-nginx" data-lang="nginx"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;upstream&lt;/span&gt; &lt;span class="s"&gt;backend&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;least_conn&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;server&lt;/span&gt; &lt;span class="n"&gt;10.0.0.1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;3000&lt;/span&gt; &lt;span class="s"&gt;weight=3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;server&lt;/span&gt; &lt;span class="n"&gt;10.0.0.2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;3000&lt;/span&gt; &lt;span class="s"&gt;weight=2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;server&lt;/span&gt; &lt;span class="n"&gt;10.0.0.3&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="s"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;proxy_pass&lt;/span&gt; &lt;span class="s"&gt;http://backend&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;常用策略：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;默认&lt;strong&gt;轮询&lt;/strong&gt;：请求依次分配&lt;/li&gt;
&lt;li&gt;&lt;code&gt;weight=&lt;/code&gt;：权重越大分到的越多&lt;/li&gt;
&lt;li&gt;&lt;code&gt;least_conn&lt;/code&gt;：连接数最少的优先&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ip_hash&lt;/code&gt;：同一客户端固定到同一后端&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="websocket-代理"&gt;WebSocket 代理
&lt;/h2&gt;&lt;p&gt;Nginx 默认不支持 WebSocket 转发，需要显式声明 Upgrade 头：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-nginx" data-lang="nginx"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="s"&gt;/ws&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;proxy_pass&lt;/span&gt; &lt;span class="s"&gt;http://backend&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;proxy_http_version&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="s"&gt;.1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;Upgrade&lt;/span&gt; &lt;span class="nv"&gt;$http_upgrade&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;Connection&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;upgrade&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id="https-终结"&gt;HTTPS 终结
&lt;/h2&gt;&lt;p&gt;让 Nginx 处理 HTTPS，后端走明文 HTTP（仅内网用）：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;span class="lnt"&gt;8
&lt;/span&gt;&lt;span class="lnt"&gt;9
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-nginx" data-lang="nginx"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;443&lt;/span&gt; &lt;span class="s"&gt;ssl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;ssl_certificate&lt;/span&gt; &lt;span class="s"&gt;/etc/nginx/ssl/cert.pem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;ssl_certificate_key&lt;/span&gt; &lt;span class="s"&gt;/etc/nginx/ssl/key.pem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="s"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;proxy_pass&lt;/span&gt; &lt;span class="s"&gt;http://127.0.0.1:3000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id="小结"&gt;小结
&lt;/h2&gt;&lt;p&gt;Nginx 的反向代理功能强大，配置简洁，是后端架构中不可或缺的组件。掌握 &lt;code&gt;proxy_pass&lt;/code&gt;、&lt;code&gt;upstream&lt;/code&gt;、WebSocket Upgrade 头这三个核心点，基本能覆盖 80% 的日常场景。&lt;/p&gt;</description></item><item><title>docker.io，docker-ce，docker-ee 的区别</title><link>https://liangweidonggood.github.io/p/docker-ji-chu-zhi-shi/</link><pubDate>Thu, 06 Mar 2014 00:00:00 +0000</pubDate><guid>https://liangweidonggood.github.io/p/docker-ji-chu-zhi-shi/</guid><description>&lt;h1 id="dockeriodocker-cedocker-ee-的区别"&gt;docker.io，docker-ce，docker-ee 的区别
&lt;/h1&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-plaintext" data-lang="plaintext"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker.io：是debian/ubuntu 官方基于docker社区源码封装的版本,有时候比docker-ce版本还要新，特点是将docker的依赖直接转接到主系统上
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker-ce：docker.com 放出来的社区版,仅维护源码，特点是使用golang将依赖封装在一个包中
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker-ee：docker.com 维护的商业版,主要有以下三个级别:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 基本:用于认证基础架构的Docker平台,得到Docker Inc.的支持以及来自Docker Store的认证容器和插件
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	 标准:添加了高级映像和容器管理,LDAP / AD用户集成以及基于角色的访问控制.这些功能共同构成了Docker企业版
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 高级:添加Docker安全扫描和连续漏洞监控
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker-ce有一个致命缺陷-依赖:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	docker本身依赖成百上千个第三方依赖
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	理论上只要有一个依赖出问题就需要完全重新编译docker,否则会被各种hack😂
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	反观 docker.io 将依赖托管给系统,只需要更新docker主程序即可
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;结论：apt包使用docker.io,其他系统使用通用脚本安装，付费用docker-ee
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;服务器使用debian/ubuntu
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;</description></item><item><title>工具说明</title><link>https://liangweidonggood.github.io/p/tools/</link><pubDate>Mon, 15 Jan 2007 10:00:00 +0800</pubDate><guid>https://liangweidonggood.github.io/p/tools/</guid><description>&lt;h1 id="工具说明"&gt;工具说明
&lt;/h1&gt;&lt;h2 id="1软件开发工具"&gt;1.软件开发工具
&lt;/h2&gt;&lt;p&gt;对应软件开发过程的各种活动，软件开发工具有需求分析工具、设计工具、。编码与排错工具、测试工具等。&lt;/p&gt;
&lt;h3 id="1需求分析工具"&gt;（1）需求分析工具
&lt;/h3&gt;&lt;p&gt;需求分析工具用以辅助软件需求分析活动，辅助系统分析员从需求定义出发，生成完整的、清晰的、一致的功能规范。功能规范是软件所要完成的功能精确而完整的陈述，描述该软件要做什么及只做什么，是软件开发者和用户间的契约，同时也是软件设计者的和实现者的依据。功能规范应正确、完整地反映用户对软件的功能要求，其表达是清晰的、无歧义的。需求分析工具的目标就是帮助分析员形成这样的功能规范。&lt;/p&gt;
&lt;h3 id="2基于自然语言或图形描述的工具"&gt;（2）基于自然语言或图形描述的工具
&lt;/h3&gt;&lt;p&gt;这类工具采用分解与抽象等基本手段，对用户问题逐步求精，并在检测机制的辅助下，发现其中可能存在的问题（如一致性），通过对问题描述的修改，逐步形成能正确反映用户需求的功能规范。它能帮助分析员提高需求文档的质量，降低功能规范的维护费用。这里以支持结构化方法的需求分析工具为例介绍。&lt;/p&gt;
&lt;p&gt;结构化分析方法采用数据流图的描述方法，分析的主要结果是一套分层的数据流图和一个数据词典。结构化需求分析工具通常由图形编辑器、数据词典管理器和检测机制三部分组成。使用图形编辑器绘制数据流图，该图形编辑器应支持图形的分层结构，以构成分层数据流图。在构造数据流图的同时把数据流图的有关信息填入数据词典。在填写数据词典的过程中，数据词典管理器即可�出重名等错误。在构造出分层数据流图后，可通过检测机制来检查分层数据流图的合法性，可发现诸如父图与子图不平衡，遗漏的数据流，只有读文件没有写文件或只有写文件没有读文件等错误。然后将修改后的数据流图和词典与用户交流，考察它是否符合用户的功能需求。若不一致，再使用图形编辑器进行修改。需求分析工具还应具备同步修改的功能，即修改数据流图的同时也修改数据词典中的有关信息，以保持数据流图与数据词典的一致性。经过多次反复的交流和修改，使功能规范逐步达到准确、完整和一致，最后形成有效的功能规范。除此以外，该工具还可浏览数据词典，生成各种统计或查询报告。&lt;/p&gt;
&lt;h3 id="3基于形式化需求定义语言的工具"&gt;（3）基于形式化需求定义语言的工具
&lt;/h3&gt;&lt;p&gt;基于形式化需求定义语言的工具大多以基于知识的需求智能助手的形式出现，并把人工智能技术运用于软件工程。这类工具通常具有一个知识库和一个推理机制。知识库中存放需求分析所需的公共知识，以及特定的应用领域知识。这些知识能用来理解需求定义中的省略写法，能部分消除不完整性和歧义性。推理机制能容忍需求定义的无序性，部分解决描述中的不一致性。这类工具接受用形式化语言书写的功能描述，运用知识库中的知识，通过推理，发现需求定义中的矛盾和不足，经补充、更新知识库中的知识和规则，以及与系统分析员的不断交互，得到完整的功能规范。&lt;/p&gt;
&lt;h3 id="4其他需求分析工具"&gt;（4）其他需求分析工具
&lt;/h3&gt;&lt;p&gt;可执行规范语言以及原型技术为需求分析工具提供了另一条实现途径，这些工具通过运行可执行规范或原型，将有关的结果显示给用户和系统分析员，以便进行需求确认。&lt;/p&gt;
&lt;h2 id="2设计工具"&gt;2.设计工具
&lt;/h2&gt;&lt;p&gt;设计工具用以辅助软件设计活动，辅助设计人员从软件功能规范出发，得到相应的设计规范。&lt;/p&gt;
&lt;p&gt;设计规范是符合功能规范和需求定义中所指定的功能及性能要求，对软件的组织或其组成部分的内部结构的描述。通常设计规范分成概要设计规范和详细设计规范。概要设计规范描述软件的功能模块及其相互关系，说明模块的处理过程和外部行为，同时还应描述数据的逻辑结构。详细设计规范描述每个模块的处理算法及涉及到的全部数据结构。设计规范是程序员进行编程活动的依据。&lt;/p&gt;
&lt;h2 id="3编码与排错工具"&gt;3.编码与排错工具
&lt;/h2&gt;&lt;p&gt;编码工具和排错工具用以辅助程序员进行编码活动。编码工具辅助程序员用某种程序语言编制源程序，并对源程序进行翻译，最终转换成可执行的代码，因此编码工具通常与编码所使用的程序语言密切相关。排错工具用来辅助程序员寻找源程序中错误的性质和原因，并确定其出错的位置。由于源程序一般以正文的形式出现，必须有编辑器将它输入，并进行浏览、编辑和修改。又由于源程序的编写往往不会一次成功，需要不断寻找其中的错误并加以纠正。编码工具和排错工具是编程活动的重要辅助工具，也是最早出现的软件工具。&lt;/p&gt;
&lt;h3 id="1编码工具"&gt;（1）编码工具
&lt;/h3&gt;&lt;p&gt;主要有编辑程序、汇编程序、编译程序和生成程序等。&lt;/p&gt;
&lt;p&gt;编辑程序：编辑程序用以输入源程序，并对其进行增加、删除和修改等操作。除常见的以字符为单位进行编辑的正文编辑程序外，还有面向程序语言语法单位的语法制导编辑程序和混合编辑程序。语法制导编辑程序也称结构化编辑程序，它可根据程序语言的语法规则提供编辑时的语法制导和检查，可以一次扩展或删除一个语法单位，如语句、表达式等，从而确保输入的源程序在语法上是正确的。混合编辑程序兼有正文编辑和语法制导编辑两种方法。&lt;/p&gt;
&lt;p&gt;汇编程序：汇编程序用以将汇编语言书写的程序翻译成等价的机器语言程序。如果汇编程序所生成的机器指令代码是另一种计算机的机器指令，便称这类汇编程序为交叉汇编程序。&lt;/p&gt;
&lt;p&gt;编译程序：编译程序用以将高级程序语言书写的程序翻译成等价的低级程序语言程序。&lt;/p&gt;
&lt;p&gt;生成程序：生成程序通常根据与领域有关的甚高级语言或某种专用语言描述的用户需求，自动生成高级程序语言或低级程序语言描述的程序。例如，词法分析生成程序LEX,它根据正规表达式表示的词法规则，自动生成词法分析程序的代码段，来实现能识别所说明的正规表达式的有限状态自动机。&lt;/p&gt;
&lt;h3 id="2排错工具"&gt;（2）排错工具
&lt;/h3&gt;&lt;p&gt;已有的排错工具主要有源代码排错程序和排错程序生成程序两类。&lt;/p&gt;
&lt;p&gt;源代码排错程序：源代码排错程序用以帮助程序员理解程序的执行状态&amp;rsquo;可通过对程序执行过程中各种状态的判别进行程序错误的识别、定位及改正。&lt;/p&gt;
&lt;h2 id="4软件维护工具"&gt;4.软件维护工具
&lt;/h2&gt;&lt;p&gt;软件维护工具辅助软件维护过程中的活动，辅助维护人员对软件代码及其文档进行各种维护活动。软件维护工具主要有版本控制工具、文档分析工具、开发信息库工具、逆向工程工具和再工程工具等。&lt;/p&gt;
&lt;h3 id="1版本控制工具"&gt;（1）版本控制工具
&lt;/h3&gt;&lt;p&gt;在软件开发和维护过程中一个软件会有多个版本，版本控制工具用来存储、更新、恢复和管理一个软件的多个版本。UNIX的是版本控制工具的典型代表。SCCS能为正文文件的多个版本建立一棵版本树，第一版完整储存文本全文，以后各版只存放它之前版本的不同之处，在任何时刻sees只允许对一个当前版本进行修改和提交。通过版本树维护版本的更新历史，并允许恢复到以前的某个版本。&lt;/p&gt;
&lt;h3 id="2文档分析工具"&gt;（2）文档分析工具
&lt;/h3&gt;&lt;p&gt;文档分析工具用以对软件开发过程中形成的文档进行分析，给出软件维护活动所需的维护信息。例如，基于数据流图的需求文档分析工具可给出对数据流图的某个成分进行维护时的影响范围及被影响范围，以便在该成分修改的同时考虑其影响范围内的其他成分是否也要修改。基于模块结构图的设计文档分析工具可以给出对模块变量进行维护时的影响及被影响范围。针对程序文档的源代码分析工具可给出模块、全局变量、局部变量的定义、引用情况，它还可以进行程序分片。程序分片是把程序中与指定的数据项或数据结构有关的程序代码抽出来，过滤掉与其无关的代码，以便维护人员高效地理解和把握他所关心的部分。文档分析工具还可得到被分析的文档的有关信息，如文档各种成分的个数、定义及引用情况等。&lt;/p&gt;
&lt;h3 id="3开发信息库工具"&gt;（3）开发信息库工具
&lt;/h3&gt;&lt;p&gt;开发信息库工具用来维护软件项目的开发信息，包括对象、模块等。它记录每个对象的修改信息和其他变形；维护对象和与之有关信息之间的关系；包括模块的设计者、新版本中模块的改动及其与错误、测试用例、测试结果之间的联系等；其他必须记录的信息，包括用来生成此软件产品的所有工具的版本信息，所使用的命令语言程序和系统库以及测试用例版本和测试报告。&lt;/p&gt;
&lt;h3 id="4逆向工程工具"&gt;（4）逆向工程工具
&lt;/h3&gt;&lt;p&gt;在软件生存周期中，将某种形式表示的软件转换成更高抽象形式表示的软件的活动称为逆向工程。例如，用反汇编工具将机器语言代码转换成汇编语言代码，用反编译工具将汇编语言代码或机器语言代码转换成某种高级程序语言源程序，之后再将源程序转换成详细设计的某种表示形式，这都属于逆向工程的范畴。逆向工程工具就是辅助软件人员进行这种逆向工程活动的软件工具。若软件缺乏必要的文档，原先的开发人员又已调离，就需使用逆向工程工具来理解原有的软件。&lt;/p&gt;
&lt;h3 id="5再工程工具"&gt;（5）再工程工具
&lt;/h3&gt;&lt;p&gt;再工程工具用来支持重构一个功能和性能更为完善的软件系统。目前的再工程工具主要集中在代码重构、程序结构重构和数据结构重构等方面。&lt;/p&gt;
&lt;p&gt;代码重构工具可把用一种程序语言书写的程序转换成用另一种程序语言书写的或适用于不同硬件平台的程序，例如FORTRAN到C的转换工具。程序结构重构工具接受-个非结构化或结构化程度较低的源程序，构造出行为等价的结构化程序。数据结构重构工具通过对数据描述的分析，重构新的数据结构。&lt;/p&gt;
&lt;h2 id="5软件管理和软件支持工具"&gt;5.软件管理和软件支持工具
&lt;/h2&gt;&lt;p&gt;软件管理过程和软件支持过程往往要涉及到软件生存周期中的多个活动，软件管理和软件支持工具用来辅助管理人员和软件支持人员的管理活动和支持活动，以确保软件高质高效地完成。&lt;/p&gt;
&lt;p&gt;辅助软件管理和软件支持的工具有很多，其中常用的工具有项目管理工具、配置管理工具、软件评价工具等。&lt;/p&gt;
&lt;h3 id="1项目管理工具"&gt;（1）项目管理工具
&lt;/h3&gt;&lt;p&gt;项目管理工具用来辅助软件的项目管理活动。通常项目管理活动包括项目的计划、调度、通信、成本估算、资源分配及质量控制等。一个项目管理工具通常把重点放在某-个或某几个特定的管理环节上，而不提供对管理活动包罗万象的支持。&lt;/p&gt;
&lt;p&gt;例如成本估算工具，�用某种成本估算模型对项目的成本进行估算。它可以通过间接的测量来估算项目的规模大小，并描述总的项目特征，如问题的复杂度、开发组经验和过程成熟度等。然后按一定的估算模型估算出项目的工作量、工期和开发人数等。当项目截止期限变更时，可检测它对整个开发成本的影响。&lt;/p&gt;
&lt;h3 id="2配置管理工具"&gt;（2）配置管理工具
&lt;/h3&gt;&lt;p&gt;配置曾理工具用以辅助完成软件配置项的标识、版本控制、变化控制、审计和状态统计等基本任务，使各配置项的存取、修改和系统生成易于实现，从而简化审计过程，改进状态统计，减少错误，提�系统的质量。&lt;/p&gt;
&lt;h3 id="3软件评价工具"&gt;（3）软件评价工具
&lt;/h3&gt;&lt;p&gt;软件评价工具用以辅助管理人员进行软件质量保证的有关活动。它通常可按某个软件质量模型对被评价的软件进行度量，然后得到相关的软件评价报告。目前许多度量指标还不能定量化，需要通过专家评分，再将得分送给软件评价工具。对一些已经定量化的度量指标则可利用评价工具自动获取。有的评价工具还可分析被评价程序的程序&amp;rsquo;结构，根据某种软件复杂性模型对被评价的程序进行复杂性度量。软件评价工具有助于软件的�量控制，对确，保软件的质量有重要的作用。&lt;/p&gt;
&lt;h3 id="4软件开发工具的评价和选择"&gt;（4）软件开发工具的评价和选择
&lt;/h3&gt;&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></channel></rss>