<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Untitled Publication]]></title><description><![CDATA[Untitled Publication]]></description><link>https://blog.wuzhiguo.tech</link><generator>RSS for Node</generator><lastBuildDate>Mon, 08 Jun 2026 07:38:29 GMT</lastBuildDate><atom:link href="https://blog.wuzhiguo.tech/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[私有云存储的解决方案选型全攻略]]></title><description><![CDATA[选择私有云存储方案时，需要考虑多个因素，包括易用性、功能、安全性、可扩展性、成本、社区支持等。以下是你提到的几个私有云存储方案的简要比较：

Filerun

特点：界面类似Google Drive，支持WebDAV，提供文件同步和分享功能。

优势：用户友好的界面，易于设置和使用。

劣势：功能相比其他一些解决方案可能较少，且为闭源软件。



KodBox

特点：基于Seafile的企业级文件同步和分享解决方案，支持私有部署。

优势：强大的文件同步功能，支持文件版本控制和权限管理。

劣...]]></description><link>https://blog.wuzhiguo.tech/private-cloud-storage-solution-selection-guide</link><guid isPermaLink="true">https://blog.wuzhiguo.tech/private-cloud-storage-solution-selection-guide</guid><category><![CDATA[Private Cloud Storage]]></category><dc:creator><![CDATA[wuzhiguocarter]]></dc:creator><pubDate>Sat, 26 Oct 2024 15:14:02 GMT</pubDate><content:encoded><![CDATA[<p>选择私有云存储方案时，需要考虑多个因素，包括易用性、功能、安全性、可扩展性、成本、社区支持等。以下是你提到的几个私有云存储方案的简要比较：</p>
<ol>
<li><p><strong>Filerun</strong></p>
<ul>
<li><p><strong>特点</strong>：界面类似Google Drive，支持WebDAV，提供文件同步和分享功能。</p>
</li>
<li><p><strong>优势</strong>：用户友好的界面，易于设置和使用。</p>
</li>
<li><p><strong>劣势</strong>：功能相比其他一些解决方案可能较少，且为闭源软件。</p>
</li>
</ul>
</li>
<li><p><strong>KodBox</strong></p>
<ul>
<li><p><strong>特点</strong>：基于Seafile的企业级文件同步和分享解决方案，支持私有部署。</p>
</li>
<li><p><strong>优势</strong>：强大的文件同步功能，支持文件版本控制和权限管理。</p>
</li>
<li><p><strong>劣势</strong>：配置相对复杂，对服务器资源要求较高。</p>
</li>
</ul>
</li>
<li><p><strong>Cloudreve</strong></p>
<ul>
<li><p><strong>特点</strong>：一款基于OneIndex的云盘系统，支持多种存储后端。</p>
</li>
<li><p><strong>优势</strong>：插件系统灵活，支持多种存储服务，界面简洁。</p>
</li>
<li><p><strong>劣势</strong>：相对较新，社区和文档可能不如其他成熟项目丰富。</p>
</li>
</ul>
</li>
<li><p><strong>Pydio</strong></p>
<ul>
<li><p><strong>特点</strong>：开源文件共享解决方案，支持多种存储后端，提供丰富的API。</p>
</li>
<li><p><strong>优势</strong>：高度可定制，支持多种存储后端，适合企业使用。</p>
</li>
<li><p><strong>劣势</strong>：配置和维护可能需要一定的技术知识。</p>
</li>
</ul>
</li>
<li><p><strong>NextCloud</strong></p>
<ul>
<li><p><strong>特点</strong>：非常流行的开源文件同步和分享解决方案，功能丰富。</p>
</li>
<li><p><strong>优势</strong>：活跃的社区，丰富的应用生态，支持多种平台和设备。</p>
</li>
<li><p><strong>劣势</strong>：随着功能的增加，对服务器资源的要求也相对较高。</p>
</li>
</ul>
</li>
</ol>
<h3 id="heading-6ycj5oup5bu66k6u77ya">选择建议：</h3>
<ul>
<li><p><strong>易用性</strong>：如果你希望快速部署并且用户界面友好，<strong>Filerun</strong> 和 <strong>NextCloud</strong> 是不错的选择。</p>
</li>
<li><p><strong>功能丰富</strong>：<strong>NextCloud</strong> 提供了丰富的应用生态，几乎可以满足所有文件存储和分享的需求。</p>
</li>
<li><p><strong>技术背景</strong>：如果你有足够的技术能力进行配置和维护，<strong>Pydio</strong> 和 <strong>KodBox</strong> 提供了更多的定制选项。</p>
</li>
<li><p><strong>成本</strong>：开源解决方案如 <strong>NextCloud</strong>、<strong>Pydio</strong> 和 <strong>Cloudreve</strong> 可以节省成本，但可能需要自行维护硬件或寻找托管服务。</p>
</li>
<li><p><strong>安全性</strong>：所有这些解决方案都提供了基本的安全特性，但<strong>KodBox</strong> 和 <strong>NextCloud</strong> 在企业级安全方面表现更好。</p>
</li>
<li><p><strong>社区支持</strong>：<strong>NextCloud</strong> 拥有最大的社区和最好的支持，对于遇到问题时寻找解决方案非常有帮助。</p>
</li>
</ul>
<p>最终的选择应基于你的具体需求、技术能力、预算和对特定功能的偏好。如果需要进一步的帮助来决定，可以提供更多的信息，例如你的具体需求、用户数量、预算范围等。</p>
<p>私有云存储的商业解决方案和开源解决方案各有其优势和劣势。以下是它们的主要对比：</p>
<h3 id="heading-5zwg5lia6kej5yaz5pa55qgi">商业解决方案</h3>
<p><strong>优势：</strong></p>
<ol>
<li><p><strong>专业支持</strong>：商业解决方案通常提供专业的技术支持和客户服务，这对于企业来说非常重要，尤其是在遇到问题时。</p>
</li>
<li><p><strong>额外功能</strong>：商业产品往往提供一些开源解决方案中没有的高级功能，如更复杂的权限管理、审计日志、数据加密等。</p>
</li>
<li><p><strong>集成服务</strong>：商业解决方案可能提供与其他企业级应用的集成，如ERP、CRM系统等。</p>
</li>
<li><p><strong>安全性</strong>：商业解决方案通常提供更高级别的安全保障，包括合规性认证和数据保护措施。</p>
</li>
<li><p><strong>维护和更新</strong>：商业解决方案提供定期的维护和更新，确保系统的稳定性和安全性。</p>
</li>
<li><p><strong>服务水平协议（SLA）</strong>：商业解决方案通常伴随着服务水平协议，保证服务的可用性和响应时间。</p>
</li>
</ol>
<p><strong>劣势：</strong></p>
<ol>
<li><p><strong>成本</strong>：商业解决方案通常需要支付许可费用，对于预算有限的组织来说可能是一个负担。</p>
</li>
<li><p><strong>灵活性</strong>：虽然商业解决方案提供了额外的功能，但它们可能不如开源解决方案那样灵活和可定制。</p>
</li>
<li><p><strong>依赖性</strong>：使用商业解决方案可能会使组织依赖于特定的供应商，这可能会限制未来的选择和灵活性。</p>
</li>
</ol>
<h3 id="heading-5bya5rqq6kej5yaz5pa55qgi">开源解决方案</h3>
<p><strong>优势：</strong></p>
<ol>
<li><p><strong>成本效益</strong>：开源解决方案通常是免费的，可以节省许可费用。</p>
</li>
<li><p><strong>灵活性和可定制性</strong>：开源解决方案允许用户根据需要修改和定制代码，以满足特定的业务需求。</p>
</li>
<li><p><strong>社区支持</strong>：开源解决方案通常有一个活跃的社区，用户可以从社区中获得帮助和资源。</p>
</li>
<li><p><strong>自主控制</strong>：组织可以完全控制其数据和系统，不受供应商的限制。</p>
</li>
<li><p><strong>透明度</strong>：开源解决方案的代码是公开的，这意味着用户可以审计代码，确保没有安全漏洞。</p>
</li>
</ol>
<p><strong>劣势：</strong></p>
<ol>
<li><p><strong>技术支持</strong>：开源解决方案可能不提供商业级别的技术支持，依赖于社区或第三方服务。</p>
</li>
<li><p><strong>安全性</strong>：虽然开源代码可以审计，但组织需要自己负责安全更新和补丁管理。</p>
</li>
<li><p><strong>资源需求</strong>：定制和维护开源解决方案可能需要更多的内部资源和专业知识。</p>
</li>
<li><p><strong>更新和维护</strong>：开源项目可能没有固定的更新和维护计划，这可能会给组织带来额外的工作。</p>
</li>
<li><p><strong>集成服务</strong>：开源解决方案可能不如商业解决方案那样提供广泛的集成选项。</p>
</li>
</ol>
<p>在选择私有云存储解决方案时，组织需要根据自己的需求、资源、预算和风险承受能力来决定是选择商业解决方案还是开源解决方案。对于需要高度定制和成本敏感的组织，开源解决方案可能是更好的选择。而对于需要高级功能、专业支持和安全性的组织，商业解决方案可能更合适。</p>
<p>在选择私有云存储解决方案时，你可以根据组织的需求、资源、预算和风险承受能力来决定是选择商业解决方案还是开源解决方案。以下是一些常见的商业和开源私有云存储解决方案的选型：</p>
<h3 id="heading-5zwg5lia6kej5yaz5pa55qgi77ya">商业解决方案：</h3>
<ol>
<li><p><strong>Microsoft SharePoint</strong></p>
<ul>
<li>集成了Microsoft 365的协作平台，提供文档管理、企业搜索和业务流程管理。</li>
</ul>
</li>
<li><p><strong>Box</strong></p>
<ul>
<li>提供文件同步、共享、协作和高级安全功能，适合企业使用。</li>
</ul>
</li>
<li><p><strong>Dropbox Business</strong></p>
<ul>
<li>提供文件同步和分享服务，适合小型和中型企业，有企业级的安全和合规功能。</li>
</ul>
</li>
<li><p><strong>Google Workspace (formerly G Suite)</strong></p>
<ul>
<li>包括Google Drive，提供文件存储、同步和协作工具，以及Gmail、Google Docs等其他Google服务。</li>
</ul>
</li>
<li><p><strong>IBM Cloud Object Storage</strong></p>
<ul>
<li>提供可扩展的云存储服务，适合需要大量数据存储和分析的企业。</li>
</ul>
</li>
<li><p><strong>Amazon WorkSpaces</strong></p>
<ul>
<li>提供云基础的虚拟桌面，集成了Amazon Drive进行文件存储。</li>
</ul>
</li>
<li><p><strong>Citrix Content Collaboration</strong></p>
<ul>
<li>提供文件同步和共享服务，以及与Citrix其他产品的集成。</li>
</ul>
</li>
<li><p><strong>Syncplicity by Axway</strong></p>
<ul>
<li>提供企业级文件同步和共享服务，具有高级安全和合规功能。</li>
</ul>
</li>
<li><p><strong>SmartFile</strong></p>
<ul>
<li>提供文件同步、共享和自动化处理功能，适合需要文件管理自动化的企业。</li>
</ul>
</li>
<li><p><strong>NetApp Private Storage (NPS)</strong></p>
<ul>
<li>提供企业级的文件和对象存储解决方案，具有高级数据管理功能。</li>
</ul>
</li>
</ol>
<h3 id="heading-5bya5rqq6kej5yaz5pa55qgi77ya">开源解决方案：</h3>
<ol>
<li><p><strong>Nextcloud</strong></p>
<ul>
<li>提供文件同步和协作功能，有丰富的应用生态系统和社区支持。</li>
</ul>
</li>
<li><p><strong>ownCloud</strong></p>
<ul>
<li>类似于Nextcloud，提供文件同步和分享功能，适合企业部署。</li>
</ul>
</li>
<li><p><strong>Seafile</strong></p>
<ul>
<li>侧重于文件同步和版本控制，适合需要文件历史和版本恢复的企业。</li>
</ul>
</li>
<li><p><strong>Pydio</strong></p>
<ul>
<li>提供文件共享和同步平台，具有丰富的API和插件系统。</li>
</ul>
</li>
<li><p><strong>Docker Registry</strong></p>
<ul>
<li>虽然主要用于容器镜像存储，但也可以用来作为私有云存储解决方案。</li>
</ul>
</li>
<li><p><strong>GitLab</strong></p>
<ul>
<li>虽然主要是代码仓库管理系统，但也可以用来存储代码和其他类型的文件。</li>
</ul>
</li>
<li><p><strong>MinIO</strong></p>
<ul>
<li>提供高性能的的对象存储服务，兼容Amazon S3 API。</li>
</ul>
</li>
<li><p><strong>OpenMedia Vault</strong></p>
<ul>
<li>是一个基于Debian的发行版，专注于网络附加存储(NAS)和私有云存储。</li>
</ul>
</li>
<li><p><strong>Samba</strong></p>
<ul>
<li>提供文件和打印服务的实现，允许你访问Windows共享文件。</li>
</ul>
</li>
<li><p><strong>Ceph</strong></p>
<ul>
<li>是一个分布式存储系统，提供高性能、可靠性和可扩展性。</li>
</ul>
</li>
</ol>
<p>在选择解决方案时，考虑以下因素：</p>
<ul>
<li><p><strong>需求</strong>：你的组织需要哪些功能，如文件同步、协作、版本控制、安全性等。</p>
</li>
<li><p><strong>成本</strong>：你的预算是多少，是否需要考虑长期的维护和支持成本。</p>
</li>
<li><p><strong>维护</strong>：你是否有足够的内部资源来维护和更新系统。</p>
</li>
<li><p><strong>集成</strong>：解决方案是否需要与其他企业应用集成。</p>
</li>
<li><p><strong>合规性</strong>：解决方案是否符合你的行业合规性要求。</p>
</li>
</ul>
<p>根据这些因素，你可以决定哪种类型的解决方案最适合你的组织。</p>
]]></content:encoded></item><item><title><![CDATA[最佳实践：如何工程化你的c++项目]]></title><description><![CDATA[工程化一个C++项目涉及许多方面，包括项目结构、构建系统、依赖管理、代码风格、测试、CI/CD（持续集成/持续部署）等。以下是一些最佳实践，帮助你工程化你的C++项目：
一、最佳实践参考规范
1. 组织项目结构

清晰的目录结构：为源代码、头文件、测试、文档、和构建文件分别创建目录。例如：
  /project-root
  ├── src/          # 源代码
  ├── include/      # 头文件
  ├── tests/        # 测试代码
  ├── doc...]]></description><link>https://blog.wuzhiguo.tech/engineering-your-cpp-projects</link><guid isPermaLink="true">https://blog.wuzhiguo.tech/engineering-your-cpp-projects</guid><category><![CDATA[C++]]></category><category><![CDATA[Software Engineering]]></category><category><![CDATA[project management]]></category><dc:creator><![CDATA[wuzhiguocarter]]></dc:creator><pubDate>Fri, 30 Aug 2024 13:47:21 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1725025621067/9825fd7d-6769-4bdf-b4d4-49fb533cdd1b.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>工程化一个C++项目涉及许多方面，包括项目结构、构建系统、依赖管理、代码风格、测试、CI/CD（持续集成/持续部署）等。以下是一些最佳实践，帮助你工程化你的C++项目：</p>
<h1 id="heading-5lia44cb5pya5l2z5a6e6le15yc6icd6kee6iyd">一、最佳实践参考规范</h1>
<h3 id="heading-1">1. 组织项目结构</h3>
<ul>
<li><p><strong>清晰的目录结构</strong>：为源代码、头文件、测试、文档、和构建文件分别创建目录。例如：</p>
<pre><code class="lang-plaintext">  /project-root
  ├── src/          # 源代码
  ├── include/      # 头文件
  ├── tests/        # 测试代码
  ├── docs/         # 文档
  ├── CMakeLists.txt # CMake构建文件
  └── README.md     # 项目说明
</code></pre>
</li>
<li><p><strong>分层架构</strong>：将项目分成多个层次（如应用层、服务层、数据层），以便于维护和扩展。</p>
</li>
</ul>
<h3 id="heading-2">2. 使用现代化的构建系统</h3>
<ul>
<li><p><strong>CMake</strong>：这是C++社区最流行的构建系统。它支持跨平台开发，易于集成外部库，且有强大的工具链支持。</p>
</li>
<li><p><strong>Conan</strong> 或 <strong>vcpkg</strong>：用于包管理和依赖管理，确保开发环境的一致性。</p>
</li>
<li><p><strong>Ninja</strong>：可以作为CMake的后端构建工具，提供更快的增量构建速度。</p>
</li>
</ul>
<h3 id="heading-3">3. 采用一致的编码规范</h3>
<ul>
<li><p><strong>使用代码格式化工具</strong>：如<code>clang-format</code>来自动化代码格式化，确保所有开发者遵循相同的代码风格。</p>
</li>
<li><p><strong>Lint工具</strong>：如<code>clang-tidy</code>或<code>cppcheck</code>，帮助识别潜在的错误和改进代码质量。</p>
</li>
</ul>
<h3 id="heading-4">4. 进行全面的单元测试和集成测试</h3>
<ul>
<li><p><strong>测试框架</strong>：使用Google Test（gtest）、Catch2、或 Boost.Test等来编写和运行单元测试。</p>
</li>
<li><p><strong>测试覆盖率工具</strong>：如<code>gcov</code>、<code>lcov</code>、<code>llvm-cov</code>等，用来度量代码的测试覆盖率。</p>
</li>
<li><p><strong>持续集成（CI）</strong>：使用GitHub Actions、GitLab CI、Jenkins等工具，自动化测试执行。</p>
</li>
</ul>
<h3 id="heading-5">5. 集成静态和动态分析</h3>
<ul>
<li><p><strong>静态分析工具</strong>：如<code>clang-analyzer</code>、<code>cppcheck</code>，用于检测代码中的潜在问题，如内存泄漏、未初始化的变量等。</p>
</li>
<li><p><strong>动态分析工具</strong>：如Valgrind或AddressSanitizer，运行时检查代码，检测内存错误、线程竞争等问题。</p>
</li>
</ul>
<h3 id="heading-6">6. 管理依赖和库</h3>
<ul>
<li><p><strong>使用包管理器</strong>：如Conan或vcpkg来管理第三方依赖库，这样可以减少配置和安装外部库的复杂性。</p>
</li>
<li><p><strong>模块化设计</strong>：避免单体项目，把代码组织成多个模块，每个模块专注于一个特定的功能。</p>
</li>
</ul>
<h3 id="heading-7-cicd">7. 实现持续集成和持续部署（CI/CD）</h3>
<ul>
<li><p><strong>自动化构建和测试</strong>：在每次提交或PR时，使用CI工具自动构建和测试项目。</p>
</li>
<li><p><strong>自动发布</strong>：集成CD流程，例如自动发布到包管理器或创建二进制发行版。</p>
</li>
</ul>
<h3 id="heading-8">8. 文档化</h3>
<ul>
<li><p><strong>自述文件 (README)</strong>：提供项目的快速介绍、构建步骤、依赖关系和使用方法。</p>
</li>
<li><p><strong>API文档</strong>：使用Doxygen或Sphinx等工具为代码生成文档。</p>
</li>
<li><p><strong>代码注释</strong>：保持代码清晰和注释准确，以帮助团队成员理解代码。</p>
</li>
</ul>
<h3 id="heading-9">9. 提高代码的可读性和可维护性</h3>
<ul>
<li><p><strong>代码复审（Code Review）</strong>：在合并代码之前，进行代码审查，确保代码质量和符合团队的标准。</p>
</li>
<li><p><strong>版本控制最佳实践</strong>：如合理使用分支、遵循规范化的提交信息、及时清理无用分支等。</p>
</li>
</ul>
<h3 id="heading-10">10. 优化构建和开发环境</h3>
<ul>
<li><p><strong>利用Dev Containers和Docker</strong>：使用Dev Containers或Docker创建一致的开发环境，确保开发人员和CI环境的一致性。</p>
</li>
<li><p><strong>支持多编译器和多平台</strong>：确保代码在GCC、Clang、MSVC等多个编译器下构建和运行良好。</p>
</li>
</ul>
<h3 id="heading-57ut6k66">结论</h3>
<p>通过遵循上述最佳实践，你可以显著提高C++项目的可维护性、可扩展性和团队协作效率。每个团队可以根据自己的需求和实际情况进行灵活调整，但核心原则是保持代码清晰、自动化构建和测试、持续改进代码质量。</p>
<h1 id="heading-5lqm44cb5pya5l2z5a6e6le15yc6icd6ag555uu">二、最佳实践参考项目</h1>
<p>以下是5个符合上述最佳实践原则的著名开源C++项目，这些项目在代码组织、构建系统、测试、文档和CI/CD等方面都表现出色：</p>
<h3 id="heading-1-llvm-low-level-virtual-machine">1. <strong>LLVM (Low-Level Virtual Machine)</strong></h3>
<ul>
<li><p><strong>简介</strong>: LLVM 是一个模块化和可重用的编译器和工具链技术的集合，支持多种编程语言。</p>
</li>
<li><p><strong>构建系统</strong>: 使用CMake作为主要构建系统，支持多平台编译（如Linux、macOS、Windows）。</p>
</li>
<li><p><strong>代码风格</strong>: 使用<code>clang-format</code>来确保一致的代码风格。</p>
</li>
<li><p><strong>测试</strong>: 使用LLVM自己的测试框架<code>lit</code>和<code>FileCheck</code>来进行单元测试、集成测试和回归测试。</p>
</li>
<li><p><strong>CI/CD</strong>: 使用GitHub Actions和其他CI系统（如Buildbot）来自动化构建、测试和发布。</p>
</li>
<li><p><strong>链接</strong>: <a target="_blank" href="https://github.com/llvm/llvm-project">LLVM GitHub</a></p>
</li>
</ul>
<h3 id="heading-2-google-test-gtest">2. <strong>Google Test (gtest)</strong></h3>
<ul>
<li><p><strong>简介</strong>: Google Test是一个流行的C++测试框架，用于编写和执行单元测试。</p>
</li>
<li><p><strong>构建系统</strong>: 使用CMake来管理项目构建，支持与其他项目的无缝集成。</p>
</li>
<li><p><strong>代码风格</strong>: 遵循Google C++风格指南，代码结构清晰，文档丰富。</p>
</li>
<li><p><strong>测试</strong>: Google Test本身用于测试其框架，并且有高测试覆盖率。</p>
</li>
<li><p><strong>CI/CD</strong>: 集成了GitHub Actions来执行持续集成和自动化测试。</p>
</li>
<li><p><strong>链接</strong>: <a target="_blank" href="https://github.com/google/googletest">Google Test GitHub</a></p>
</li>
</ul>
<h3 id="heading-3-qt-framework">3. <strong>Qt Framework</strong></h3>
<ul>
<li><p><strong>简介</strong>: Qt是一个跨平台的C++ GUI应用程序框架，广泛用于桌面和移动应用开发。</p>
</li>
<li><p><strong>构建系统</strong>: 使用<code>qmake</code>、CMake和<code>qbs</code>等构建系统，支持跨平台编译。</p>
</li>
<li><p><strong>代码风格</strong>: 遵循Qt风格指南，有一致的编码风格和命名规范。</p>
</li>
<li><p><strong>测试</strong>: 使用QTest库进行单元测试和集成测试，保证高质量的代码。</p>
</li>
<li><p><strong>CI/CD</strong>: 具有完整的CI/CD流水线，通过CI系统（如GitLab CI）进行持续集成和部署。</p>
</li>
<li><p><strong>链接</strong>: <a target="_blank" href="https://github.com/qt/qtbase">Qt GitHub</a></p>
</li>
</ul>
<h3 id="heading-4-apache-thrift">4. <strong>Apache Thrift</strong></h3>
<ul>
<li><p><strong>简介</strong>: Apache Thrift 是一个可伸缩的跨语言服务开发框架，允许定义和创建服务，并以多种编程语言来实现。</p>
</li>
<li><p><strong>构建系统</strong>: 使用CMake作为构建系统，支持多种编译器和平台。</p>
</li>
<li><p><strong>代码风格</strong>: 项目遵循严格的代码风格指南，并通过Lint工具确保代码质量。</p>
</li>
<li><p><strong>测试</strong>: 包含大量单元测试和集成测试，保证代码的可靠性和稳定性。</p>
</li>
<li><p><strong>CI/CD</strong>: 使用GitHub Actions等工具实现CI/CD，自动化构建和测试。</p>
</li>
<li><p><strong>链接</strong>: <a target="_blank" href="https://github.com/apache/thrift">Apache Thrift GitHub</a></p>
</li>
</ul>
<h3 id="heading-5-google-chromium">5. <strong>Google Chromium</strong></h3>
<ul>
<li><p><strong>简介</strong>: Chromium 是开源的Web浏览器项目，Google Chrome的基础。它复杂而庞大，但在C++项目工程化方面表现出色。</p>
</li>
<li><p><strong>构建系统</strong>: 使用<code>GN</code>（Generate Ninja）和<code>Ninja</code>构建系统，构建速度快，支持增量构建。</p>
</li>
<li><p><strong>代码风格</strong>: 遵循Google C++风格指南，使用<code>clang-format</code>和<code>clang-tidy</code>进行代码格式化和Lint。</p>
</li>
<li><p><strong>测试</strong>: 包括广泛的单元测试、集成测试、UI测试和性能测试，测试覆盖率高。</p>
</li>
<li><p><strong>CI/CD</strong>: 使用专有的CI/CD流水线，包括多个平台上的自动化构建和测试。</p>
</li>
<li><p><strong>链接</strong>: <a target="_blank" href="https://github.com/chromium/chromium">Chromium GitHub</a></p>
</li>
</ul>
<p>这些项目都展示了如何通过良好的项目组织、构建系统、测试、CI/CD和代码质量管理来实现C++项目的工程化。如果你有兴趣深入了解它们的具体实践，可以参考它们的源代码和文档。</p>
<h3 id="heading-6-opencv-open-source-computer-vision-library">6. <strong>OpenCV (Open Source Computer Vision Library)</strong></h3>
<ul>
<li><p><strong>简介</strong>: OpenCV 是一个开源的计算机视觉和机器学习软件库，广泛用于实时计算机视觉应用。</p>
</li>
<li><p><strong>构建系统</strong>: 使用CMake，支持多平台（Windows、Linux、macOS、Android等）编译。</p>
</li>
<li><p><strong>代码风格</strong>: 遵循一致的编码风格和格式化标准。</p>
</li>
<li><p><strong>测试</strong>: 使用Google Test编写单元测试，提供全面的测试覆盖。</p>
</li>
<li><p><strong>CI/CD</strong>: 使用GitHub Actions进行持续集成和自动化测试。</p>
</li>
<li><p><strong>链接</strong>: <a target="_blank" href="https://github.com/opencv/opencv">OpenCV GitHub</a></p>
</li>
</ul>
<h3 id="heading-7-boost-c-libraries">7. <strong>Boost C++ Libraries</strong></h3>
<ul>
<li><p><strong>简介</strong>: Boost 是一组开源的C++库，提供广泛的功能扩展，如智能指针、线程、安全数据结构等。</p>
</li>
<li><p><strong>构建系统</strong>: <a target="_blank" href="http://使用Boost.Build">使用Boost.Build</a>和CMake支持，允许灵活配置和高效构建。</p>
</li>
<li><p><strong>代码风格</strong>: 遵循Boost代码规范和格式化标准。</p>
</li>
<li><p><strong>测试</strong>: 包含全面的单元测试和回归测试，以保证库的稳定性。</p>
</li>
<li><p><strong>CI/CD</strong>: 使用CI工具（如Travis CI）进行持续集成和自动化测试。</p>
</li>
<li><p><strong>链接</strong>: <a target="_blank" href="https://github.com/boostorg">Boost GitHub</a></p>
</li>
</ul>
<h3 id="heading-8-poco-c-libraries">8. <strong>POCO C++ Libraries</strong></h3>
<ul>
<li><p><strong>简介</strong>: POCO（Portable Components）是一组用于网络编程、并发、数据库访问等的轻量级C++库。</p>
</li>
<li><p><strong>构建系统</strong>: 使用CMake构建系统，支持多平台开发。</p>
</li>
<li><p><strong>代码风格</strong>: 遵循一致的编码规范，代码清晰易读。</p>
</li>
<li><p><strong>测试</strong>: 提供丰富的测试集，涵盖单元测试和集成测试。</p>
</li>
<li><p><strong>CI/CD</strong>: 使用GitHub Actions等工具实现自动化构建和测试。</p>
</li>
<li><p><strong>链接</strong>: <a target="_blank" href="https://github.com/pocoproject/poco">POCO GitHub</a></p>
</li>
</ul>
<h3 id="heading-9-caffe">9. <strong>Caffe</strong></h3>
<ul>
<li><p><strong>简介</strong>: Caffe 是一个深度学习框架，专为速度和模块化设计。</p>
</li>
<li><p><strong>构建系统</strong>: 使用CMake和Makefile，支持多种硬件平台（如CPU、GPU）的高效构建。</p>
</li>
<li><p><strong>代码风格</strong>: 遵循Google C++风格指南，代码组织清晰。</p>
</li>
<li><p><strong>测试</strong>: 使用Google Test进行测试，覆盖关键组件。</p>
</li>
<li><p><strong>CI/CD</strong>: 使用GitHub Actions进行持续集成和自动化测试。</p>
</li>
<li><p><strong>链接</strong>: <a target="_blank" href="https://github.com/BVLC/caffe">Caffe GitHub</a></p>
</li>
</ul>
<h3 id="heading-10-grpc">10. <strong>gRPC</strong></h3>
<ul>
<li><p><strong>简介</strong>: gRPC 是一个高性能、通用的远程过程调用 (RPC) 框架，支持多种编程语言。</p>
</li>
<li><p><strong>构建系统</strong>: 使用Bazel和CMake作为构建系统，支持多语言和跨平台构建。</p>
</li>
<li><p><strong>代码风格</strong>: 遵循Google的编码风格指南，使用<code>clang-format</code>来保持代码一致性。</p>
</li>
<li><p><strong>测试</strong>: 使用Google Test进行单元测试和集成测试。</p>
</li>
<li><p><strong>CI/CD</strong>: 使用Kokoro和GitHub Actions进行CI/CD流水线管理。</p>
</li>
<li><p><strong>链接</strong>: <a target="_blank" href="https://github.com/grpc/grpc">gRPC GitHub</a></p>
</li>
</ul>
<h3 id="heading-11-redis-redis">11. <strong>Redis (redis++)</strong></h3>
<ul>
<li><p><strong>简介</strong>: <code>redis++</code> 是Redis的一个C++客户端库，提供简单易用的接口来与Redis交互。</p>
</li>
<li><p><strong>构建系统</strong>: 使用CMake构建系统，支持跨平台编译。</p>
</li>
<li><p><strong>代码风格</strong>: 遵循现代C++编码风格，代码简洁明了。</p>
</li>
<li><p><strong>测试</strong>: 使用Google Test进行单元测试，覆盖率高。</p>
</li>
<li><p><strong>CI/CD</strong>: 使用GitHub Actions实现持续集成和自动化测试。</p>
</li>
<li><p><strong>链接</strong>: <a target="_blank" href="https://github.com/sewenew/redis-plus-plus">redis++ GitHub</a></p>
</li>
</ul>
<h3 id="heading-12-nlohmannjson">12. <strong>nlohmann/json</strong></h3>
<ul>
<li><p><strong>简介</strong>: <code>nlohmann/json</code> 是一个非常流行的C++ JSON库，使用现代C++特性实现。</p>
</li>
<li><p><strong>构建系统</strong>: 提供CMake支持，易于集成到其他C++项目中。</p>
</li>
<li><p><strong>代码风格</strong>: 遵循C++11/14/17标准，保持代码简洁和现代化。</p>
</li>
<li><p><strong>测试</strong>: 使用Catch2进行单元测试，测试覆盖率高。</p>
</li>
<li><p><strong>CI/CD</strong>: 使用GitHub Actions实现持续集成和自动化测试。</p>
</li>
<li><p><strong>链接</strong>: <a target="_blank" href="https://github.com/nlohmann/json">nlohmann/json GitHub</a></p>
</li>
</ul>
<h3 id="heading-13-apache-kafka-c-client-confluent-kafka-python">13. <strong>Apache Kafka C++ Client (confluent-kafka-python)</strong></h3>
<ul>
<li><p><strong>简介</strong>: <code>confluent-kafka-python</code> 是Kafka的C++客户端实现，支持高效的数据流传输。</p>
</li>
<li><p><strong>构建系统</strong>: 使用CMake和Conan进行依赖管理和构建。</p>
</li>
<li><p><strong>代码风格</strong>: 遵循良好的编码实践和标准，确保代码质量。</p>
</li>
<li><p><strong>测试</strong>: 使用Google Test和其他工具进行单元和集成测试。</p>
</li>
<li><p><strong>CI/CD</strong>: 使用Travis CI和GitHub Actions进行持续集成和测试。</p>
</li>
<li><p><strong>链接</strong>: <a target="_blank" href="https://github.com/confluentinc/confluent-kafka-python">confluent-kafka-python GitHub</a></p>
</li>
</ul>
<h3 id="heading-14-fmt-formatting-library">14. <strong>fmt (Formatting Library)</strong></h3>
<ul>
<li><p><strong>简介</strong>: <code>fmt</code> 是一个开源的格式化库，类似于Python的<code>str.format()</code>，但适用于C++。</p>
</li>
<li><p><strong>构建系统</strong>: 使用CMake构建系统，易于集成和扩展。</p>
</li>
<li><p><strong>代码风格</strong>: 遵循现代C++编码风格，代码清晰简洁。</p>
</li>
<li><p><strong>测试</strong>: 使用Google Test进行单元测试，确保功能的正确性和稳定性。</p>
</li>
<li><p><strong>CI/CD</strong>: 使用GitHub Actions进行持续集成和自动化测试。</p>
</li>
<li><p><strong>链接</strong>: <a target="_blank" href="https://github.com/fmtlib/fmt">fmt GitHub</a></p>
</li>
</ul>
<h3 id="heading-15-eigen">15. <strong>Eigen</strong></h3>
<ul>
<li><p><strong>简介</strong>: Eigen 是一个高效的C++数学库，广泛用于线性代数、矩阵操作、几何变换等。</p>
</li>
<li><p><strong>构建系统</strong>: 使用CMake构建系统，支持高效的矩阵运算和科学计算。</p>
</li>
<li><p><strong>代码风格</strong>: 遵循严格的代码风格指南，代码清晰易读。</p>
</li>
<li><p><strong>测试</strong>: 包含广泛的单元测试和性能测试，确保数学计算的精度和速度。</p>
</li>
<li><p><strong>CI/CD</strong>: 使用GitHub Actions和其他工具进行持续集成和自动化测试。</p>
</li>
<li><p><strong>链接</strong>: <a target="_blank" href="https://gitlab.com/libeigen/eigen">Eigen GitHub</a></p>
</li>
</ul>
<h3 id="heading-16-opensubdiv">16. <strong>OpenSubdiv</strong></h3>
<ul>
<li><p><strong>简介</strong>: OpenSubdiv 是一个开源的库，用于几何细分和多分辨率建模，广泛用于图形和动画。</p>
</li>
<li><p><strong>构建系统</strong>: 使用CMake构建系统，支持多平台编译和硬件加速。</p>
</li>
<li><p><strong>代码风格</strong>: 遵循严格的代码风格指南，确保代码一致性和可读性。</p>
</li>
<li><p><strong>测试</strong>: 包含单元测试和性能测试，确保库的正确性和高效性。</p>
</li>
<li><p><strong>CI/CD</strong>: 使用GitHub Actions进行持续集成和自动化测试。</p>
</li>
<li><p><strong>链接</strong>: <a target="_blank" href="https://github.com/PixarAnimationStudios/OpenSubdiv">OpenSubdiv GitHub</a></p>
</li>
</ul>
<h3 id="heading-17-tesseract-ocr">17. <strong>Tesseract OCR</strong></h3>
<ul>
<li><p><strong>简介</strong>: Tesseract 是一个广泛使用的开源光学字符识别（OCR）引擎，支持多语言。</p>
</li>
<li><p><strong>构建系统</strong>: 使用CMake和Autotools，支持跨平台编译。</p>
</li>
<li><p><strong>代码风格</strong>: 遵循严格的编码规范，代码结构清晰。</p>
</li>
<li><p><strong>测试</strong>: 包含广泛的单元测试和集成测试，确保OCR的准确性。</p>
</li>
<li><p><strong>CI/CD</strong>: 使用GitHub Actions进行CI/CD，自动化构建和测试。</p>
</li>
<li><p><strong>链接</strong>: <a target="_blank" href="https://github.com/tesseract-ocr/tesseract">Tesseract GitHub</a></p>
</li>
</ul>
<p>这些项目在实践中应用了各种C++项目工程化的最佳实践，值得学习和借鉴。它们涵盖了不同领域和用途，提供了多样化的参考范例。</p>
]]></content:encoded></item><item><title><![CDATA[最佳实践：如何工程化你的Python项目]]></title><description><![CDATA[在管理Python工程项目时，采用最佳实践能够提高代码质量、可维护性和协作效率。以下是一些推荐的Python工程项目管理最佳实践：
一、最佳实践参考规范
1. 项目结构
一个清晰的项目结构有助于组织代码和文件，使项目易于理解和导航。通常的项目结构如下：
project-name/
│
├── src/                # 源代码目录
│   └── package_name/   # 项目主包
│       ├── __init__.py
│       ├── module1....]]></description><link>https://blog.wuzhiguo.tech/engineering-your-python-project</link><guid isPermaLink="true">https://blog.wuzhiguo.tech/engineering-your-python-project</guid><category><![CDATA[Python]]></category><category><![CDATA[Software Engineering]]></category><dc:creator><![CDATA[wuzhiguocarter]]></dc:creator><pubDate>Fri, 30 Aug 2024 13:34:56 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1725025023443/58422e3a-1abb-4e47-8bd5-e109db93db3d.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>在管理Python工程项目时，采用最佳实践能够提高代码质量、可维护性和协作效率。以下是一些推荐的Python工程项目管理最佳实践：</p>
<h1 id="heading-5lia44cb5pya5l2z5a6e6le15yc6icd6kee6iyd">一、最佳实践参考规范</h1>
<h3 id="heading-1">1. 项目结构</h3>
<p>一个清晰的项目结构有助于组织代码和文件，使项目易于理解和导航。通常的项目结构如下：</p>
<pre><code class="lang-plaintext">project-name/
│
├── src/                # 源代码目录
│   └── package_name/   # 项目主包
│       ├── __init__.py
│       ├── module1.py
│       └── module2.py
│
├── tests/              # 测试代码目录
│   ├── __init__.py
│   ├── test_module1.py
│   └── test_module2.py
│
├── docs/               # 文档目录
│
├── scripts/            # 脚本和工具
│
├── .gitignore          # Git忽略文件
├── README.md           # 项目说明文档
├── requirements.txt    # 项目依赖列表
├── setup.py            # 安装和打包脚本
├── pyproject.toml      # 项目配置文件（PEP 518）
└── setup.cfg           # 配置文件
</code></pre>
<h3 id="heading-2">2. 虚拟环境管理</h3>
<p>使用虚拟环境（如 <code>venv</code> 或 <code>virtualenv</code>）来隔离项目的依赖，确保不同项目的依赖不会发生冲突。创建和激活虚拟环境的基本命令如下：</p>
<pre><code class="lang-bash">python -m venv env
<span class="hljs-built_in">source</span> env/bin/activate   <span class="hljs-comment"># Unix/macOS</span>
env\Scripts\activate      <span class="hljs-comment"># Windows</span>
</code></pre>
<h3 id="heading-3">3. 依赖管理</h3>
<p>使用 <code>requirements.txt</code> 或 <code>pyproject.toml</code> 和 <code>Pipfile</code> 等文件来管理项目依赖，并使用 <code>pip</code> 或 <code>poetry</code> 进行安装。通过 <code>pip freeze</code> 来生成依赖文件：</p>
<pre><code class="lang-bash">pip freeze &gt; requirements.txt
</code></pre>
<p><code>poetry</code> 提供更现代化的依赖管理和版本控制工具，推荐用于更复杂的项目：</p>
<pre><code class="lang-bash">poetry init
poetry add package_name
</code></pre>
<h3 id="heading-4">4. 代码风格和静态检查</h3>
<p>遵循PEP 8风格指南，确保代码的一致性和可读性。使用工具如 <code>flake8</code>、<code>black</code>、<code>isort</code>、<code>pylint</code> 等来自动检查和格式化代码。</p>
<pre><code class="lang-bash">pip install flake8 black isort pylint
flake8 .  <span class="hljs-comment"># 检查代码风格</span>
black .   <span class="hljs-comment"># 自动格式化代码</span>
isort .   <span class="hljs-comment"># 自动整理导入</span>
</code></pre>
<h3 id="heading-5">5. 版本控制</h3>
<p>使用 Git 进行版本控制，并遵循 Git 分支模型（如 Git Flow 或 GitHub Flow）。确保 <code>.gitignore</code> 文件正确配置，避免将不必要的文件提交到版本库。</p>
<h3 id="heading-6">6. 单元测试和持续集成</h3>
<p>编写单元测试并使用 <code>pytest</code> 等框架来自动化测试。确保每次代码变更都通过所有测试。可以集成CI工具（如 GitHub Actions、Travis CI 或 CircleCI）来自动运行测试和代码检查。</p>
<pre><code class="lang-bash">pip install pytest
pytest
</code></pre>
<h3 id="heading-7">7. 文档和注释</h3>
<p>编写清晰的文档和注释，帮助开发者理解代码的功能和设计。使用工具如 <code>Sphinx</code> 生成API文档，并确保 <a target="_blank" href="http://README.md"><code>README.md</code></a> 文件包含项目的基本信息和使用方法。</p>
<h3 id="heading-8">8. 代码质量和性能分析</h3>
<p>使用 <code>mypy</code> 等工具进行静态类型检查，提高代码的健壮性。使用 <code>cProfile</code>、<code>line_profiler</code> 等工具分析和优化代码性能。</p>
<pre><code class="lang-bash">pip install mypy
mypy src/
</code></pre>
<h3 id="heading-9">9. 配置管理和环境变量</h3>
<p>将配置文件和敏感信息（如API密钥）存储在环境变量或 <code>.env</code> 文件中。使用 <code>python-dotenv</code> 等库来管理环境配置。</p>
<h3 id="heading-10">10. 打包和发布</h3>
<p>使用 <code>setuptools</code>、<code>poetry</code> 或 <code>flit</code> 等工具来打包和发布Python包。遵循语义化版本控制（SemVer）原则。</p>
<h3 id="heading-11-docker">11. Docker 和容器化</h3>
<p>为项目创建 <code>Dockerfile</code> 和 <code>docker-compose.yml</code> 文件，确保应用程序在任何环境中都可以一致地运行。</p>
<h3 id="heading-12">12. 安全和依赖审计</h3>
<p>定期使用工具如 <code>bandit</code> 和 <code>safety</code> 来检查代码中的安全漏洞和不安全的依赖。</p>
<pre><code class="lang-bash">pip install bandit safety
bandit -r src/
safety check
</code></pre>
<h3 id="heading-5oc757ut">总结</h3>
<p>Python工程项目的管理需要良好的组织结构、依赖管理、代码风格、测试、文档和安全实践等方面的配合。这些最佳实践有助于提高开发效率、代码质量和团队协作能力。</p>
<h1 id="heading-5lqm44cb5pya5l2z5a6e6le15yc6icd6ag555uu5qgi5l6l">二、最佳实践参考项目案例</h1>
<p>以下是一些遵循最佳实践的、有影响力且权威的Python开源项目。这些项目在社区中具有良好的声誉，代码质量高，结构清晰，并且注重测试、文档和持续集成等方面的管理：</p>
<h3 id="heading-1-django">1. <strong>Django</strong></h3>
<ul>
<li><p><strong>GitHub Repo</strong>: <a target="_blank" href="https://github.com/django/django">django/django</a></p>
</li>
<li><p><strong>描述</strong>: Django 是一个高级 Python Web 框架，专注于开发速度、简洁和可扩展性。</p>
</li>
<li><p><strong>最佳实践</strong>:</p>
<ul>
<li><p>遵循 PEP 8 代码风格。</p>
</li>
<li><p>使用 <code>tox</code> 和 <code>pytest</code> 进行多版本测试。</p>
</li>
<li><p>强调文档，拥有全面的<a target="_blank" href="https://docs.djangoproject.com/">官方文档</a>。</p>
</li>
<li><p>使用 <code>sphinx</code> 生成文档。</p>
</li>
<li><p>注重安全实践，有专门的<a target="_blank" href="https://docs.djangoproject.com/en/stable/topics/security/">安全页面</a>。</p>
</li>
</ul>
</li>
</ul>
<h3 id="heading-2-flask">2. <strong>Flask</strong></h3>
<ul>
<li><p><strong>GitHub Repo</strong>: <a target="_blank" href="https://github.com/pallets/flask">pallets/flask</a></p>
</li>
<li><p><strong>描述</strong>: Flask 是一个轻量级 WSGI Web 应用框架，广泛用于构建简单的应用程序和微服务。</p>
</li>
<li><p><strong>最佳实践</strong>:</p>
<ul>
<li><p>使用 <code>tox</code> 和 <code>pytest</code> 进行自动化测试。</p>
</li>
<li><p>完整的<a target="_blank" href="https://flask.palletsprojects.com/">开发者文档</a>。</p>
</li>
<li><p>遵循模块化项目结构，使用蓝图（Blueprint）实现模块化路由。</p>
</li>
<li><p>注重代码风格和一致性。</p>
</li>
</ul>
</li>
</ul>
<h3 id="heading-3-requests">3. <strong>Requests</strong></h3>
<ul>
<li><p><strong>GitHub Repo</strong>: <a target="_blank" href="https://github.com/psf/requests">psf/requests</a></p>
</li>
<li><p><strong>描述</strong>: Requests 是一个简单易用的 HTTP 库，是 Python 中最流行的库之一。</p>
</li>
<li><p><strong>最佳实践</strong>:</p>
<ul>
<li><p>清晰的项目结构和模块划分。</p>
</li>
<li><p>完整的单元测试覆盖率。</p>
</li>
<li><p>遵循语义版本控制 (SemVer) 原则。</p>
</li>
<li><p>文档全面，包含用例、教程和API参考。</p>
</li>
</ul>
</li>
</ul>
<h3 id="heading-4-pandas">4. <strong>Pandas</strong></h3>
<ul>
<li><p><strong>GitHub Repo</strong>: <a target="_blank" href="https://github.com/pandas-dev/pandas">pandas-dev/pandas</a></p>
</li>
<li><p><strong>描述</strong>: Pandas 是一个强大的数据分析和数据处理库，广泛应用于数据科学和机器学习。</p>
</li>
<li><p><strong>最佳实践</strong>:</p>
<ul>
<li><p>使用 <code>pytest</code> 进行测试，拥有极高的测试覆盖率。</p>
</li>
<li><p>使用 <code>flake8</code> 和 <code>black</code> 等工具来检查代码质量。</p>
</li>
<li><p>自动化的持续集成（CI），使用 GitHub Actions。</p>
</li>
<li><p>详细的<a target="_blank" href="https://pandas.pydata.org/docs/">文档</a>和 API 参考。</p>
</li>
</ul>
</li>
</ul>
<h3 id="heading-5-celery">5. <strong>Celery</strong></h3>
<ul>
<li><p><strong>GitHub Repo</strong>: <a target="_blank" href="https://github.com/celery/celery">celery/celery</a></p>
</li>
<li><p><strong>描述</strong>: Celery 是一个简单灵活、可靠且维护良好的分布式任务队列系统。</p>
</li>
<li><p><strong>最佳实践</strong>:</p>
<ul>
<li><p>使用 <code>tox</code> 和 <code>pytest</code> 进行自动化测试。</p>
</li>
<li><p>完整的开发者和用户文档。</p>
</li>
<li><p>支持各种消息传递后端和任务序列化格式，具有较好的模块化设计。</p>
</li>
</ul>
</li>
</ul>
<h3 id="heading-6-fastapi">6. <strong>FastAPI</strong></h3>
<ul>
<li><p><strong>GitHub Repo</strong>: <a target="_blank" href="https://github.com/tiangolo/fastapi">tiangolo/fastapi</a></p>
</li>
<li><p><strong>描述</strong>: FastAPI 是一个现代的、快速的 Web 框架，基于标准的 Python 类型提示。</p>
</li>
<li><p><strong>最佳实践</strong>:</p>
<ul>
<li><p>强调类型检查和自动文档生成。</p>
</li>
<li><p>使用 <code>pytest</code> 进行测试，并集成了测试客户端。</p>
</li>
<li><p>拥有广泛的<a target="_blank" href="https://fastapi.tiangolo.com/">文档</a>和教程。</p>
</li>
<li><p>注重代码质量和可读性，提供优秀的开发者体验。</p>
</li>
</ul>
</li>
</ul>
<h3 id="heading-7-tensorflow">7. <strong>TensorFlow</strong></h3>
<ul>
<li><p><strong>GitHub Repo</strong>: <a target="_blank" href="https://github.com/tensorflow/tensorflow">tensorflow/tensorflow</a></p>
</li>
<li><p><strong>描述</strong>: TensorFlow 是一个用于机器学习的开源库，广泛用于深度学习和神经网络。</p>
</li>
<li><p><strong>最佳实践</strong>:</p>
<ul>
<li><p>拥有模块化的代码结构，适合扩展和贡献。</p>
</li>
<li><p>使用 Bazel 构建系统和 <code>pytest</code> 进行测试。</p>
</li>
<li><p>完整的 CI/CD 流水线。</p>
</li>
<li><p>广泛的社区支持和详细的<a target="_blank" href="https://www.tensorflow.org/learn">文档</a>。</p>
</li>
</ul>
</li>
</ul>
<h3 id="heading-8-scrapy">8. <strong>Scrapy</strong></h3>
<ul>
<li><p><strong>GitHub Repo</strong>: <a target="_blank" href="https://github.com/scrapy/scrapy">scrapy/scrapy</a></p>
</li>
<li><p><strong>描述</strong>: Scrapy 是一个快速、高效、功能强大的 Web 抓取框架。</p>
</li>
<li><p><strong>最佳实践</strong>:</p>
<ul>
<li><p>良好的项目结构，代码模块化清晰。</p>
</li>
<li><p>使用 <code>pytest</code> 进行测试，并有相应的 CI 集成。</p>
</li>
<li><p>详细的<a target="_blank" href="https://docs.scrapy.org/">文档</a>和API参考。</p>
</li>
<li><p>注重代码风格和一致性。</p>
</li>
</ul>
</li>
</ul>
<h3 id="heading-9-sqlalchemy">9. <strong>SQLAlchemy</strong></h3>
<ul>
<li><p><strong>GitHub Repo</strong>: <a target="_blank" href="https://github.com/sqlalchemy/sqlalchemy">sqlalchemy/sqlalchemy</a></p>
</li>
<li><p><strong>描述</strong>: SQLAlchemy 是一个Python SQL 工具包和对象关系映射（ORM）库。</p>
</li>
<li><p><strong>最佳实践</strong>:</p>
<ul>
<li><p>使用 <code>tox</code> 和 <code>pytest</code> 进行多数据库、多版本测试。</p>
</li>
<li><p>遵循模块化设计，易于扩展和维护。</p>
</li>
<li><p>完整的<a target="_blank" href="https://docs.sqlalchemy.org/">文档</a>和教程，包含示例代码。</p>
</li>
</ul>
</li>
</ul>
<h3 id="heading-10-pipenv">10. <strong>Pipenv</strong></h3>
<ul>
<li><p><strong>GitHub Repo</strong>: <a target="_blank" href="https://github.com/pypa/pipenv">pypa/pipenv</a></p>
</li>
<li><p><strong>描述</strong>: Pipenv 是一种用于 Python 项目依赖管理的工具，旨在为 Python 提供最佳的包管理体验。</p>
</li>
<li><p><strong>最佳实践</strong>:</p>
<ul>
<li><p>清晰的项目结构和依赖管理。</p>
</li>
<li><p>完整的测试覆盖率和自动化测试。</p>
</li>
<li><p>良好的文档支持，注重用户体验。</p>
</li>
</ul>
</li>
</ul>
<p>这些项目不仅在代码风格、结构和测试覆盖率上体现了最佳实践，而且其文档、持续集成和社区支持也使其成为优秀的学习范例。</p>
]]></content:encoded></item><item><title><![CDATA[Google Test：从入门到高手]]></title><description><![CDATA[Google Test（简称GTest）是一个由Google开发的C++测试框架，广泛用于单元测试。以下是从入门到高手的学习路径，涵盖基本使用到高级技巧。
一、入门阶段

安装与配置

安装Google Test库。

在CMake项目中集成Google Test，简单配置编译环境。

使用find_package(GTest)或手动编译Google Test源码。



编写简单测试

测试案例：使用TEST宏编写简单的测试案例。

断言（Assertions）：学习EXPECT_EQ、ASS...]]></description><link>https://blog.wuzhiguo.tech/google-test</link><guid isPermaLink="true">https://blog.wuzhiguo.tech/google-test</guid><category><![CDATA[UnitTest]]></category><category><![CDATA[google test]]></category><category><![CDATA[C++]]></category><dc:creator><![CDATA[wuzhiguocarter]]></dc:creator><pubDate>Sun, 25 Aug 2024 16:00:06 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1724498290791/ffe6d3f2-ee4f-4fe4-8de9-f1ea96761de5.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Google Test（简称GTest）是一个由Google开发的C++测试框架，广泛用于单元测试。以下是从入门到高手的学习路径，涵盖基本使用到高级技巧。</p>
<h3 id="heading-5lia44cb5ywl6zeo6zi25q61">一、入门阶段</h3>
<ol>
<li><p><strong>安装与配置</strong></p>
<ul>
<li><p>安装Google Test库。</p>
</li>
<li><p>在CMake项目中集成Google Test，简单配置编译环境。</p>
</li>
<li><p>使用<code>find_package(GTest)</code>或手动编译Google Test源码。</p>
</li>
</ul>
</li>
<li><p><strong>编写简单测试</strong></p>
<ul>
<li><p><strong>测试案例</strong>：使用<code>TEST</code>宏编写简单的测试案例。</p>
</li>
<li><p><strong>断言（Assertions）</strong>：学习<code>EXPECT_EQ</code>、<code>ASSERT_TRUE</code>等常用断言，了解断言失败的影响。</p>
</li>
<li><p><strong>测试套件（Test Suite）</strong>：将多个相关测试案例组织在一起。</p>
</li>
</ul>
</li>
<li><p><strong>运行测试</strong></p>
<ul>
<li><p>使用<code>RUN_ALL_TESTS()</code>运行所有测试案例。</p>
</li>
<li><p>学习如何通过命令行参数控制测试运行，例如运行特定测试、设置输出格式等。</p>
</li>
</ul>
</li>
</ol>
<h3 id="heading-5lqm44cb6lb6zi26zi25q61">二、进阶阶段</h3>
<ol>
<li><p><strong>参数化测试</strong></p>
<ul>
<li><p>学习如何编写参数化测试，使用<code>INSTANTIATE_TEST_SUITE_P</code>生成多组测试数据。</p>
</li>
<li><p>处理多个测试用例共用的逻辑。</p>
</li>
</ul>
</li>
<li><p><strong>Fixture（测试夹具）</strong></p>
<ul>
<li><p>通过继承<code>::testing::Test</code>类创建测试夹具（Test Fixtures），实现测试环境的初始化与清理。</p>
</li>
<li><p>掌握<code>SetUp()</code>和<code>TearDown()</code>函数的使用，便于在多个测试案例之间共享状态。</p>
</li>
</ul>
</li>
<li><p><strong>测试事件监听器</strong></p>
<ul>
<li><p>编写自定义的事件监听器，实现测试运行过程中自定义行为，如自定义日志输出、统计测试执行时间等。</p>
</li>
<li><p>学习<code>TestEventListener</code>接口的相关函数，如<code>OnTestStart</code>、<code>OnTestEnd</code>等。</p>
</li>
</ul>
</li>
<li><p><strong>自定义断言</strong></p>
<ul>
<li><p>在标准断言不满足需求时，编写自定义断言函数，并返回友好的错误信息。</p>
</li>
<li><p>掌握<code>ASSERT_PRED1</code>、<code>ASSERT_PRED2</code>等高级宏的使用。</p>
</li>
</ul>
</li>
<li><p><strong>异常测试</strong></p>
<ul>
<li><p>使用<code>ASSERT_THROW</code>、<code>EXPECT_THROW</code>等宏测试异常抛出。</p>
</li>
<li><p>处理异常的捕获与测试逻辑。</p>
</li>
</ul>
</li>
</ol>
<h3 id="heading-5lij44cb6auy57qn6zi25q61">三、高级阶段</h3>
<ol>
<li><p><strong>与Mock结合</strong></p>
<ul>
<li><p>学习Google Mock的基本使用，包括<code>MOCK_METHOD</code>宏来模拟类的行为。</p>
</li>
<li><p>编写模拟类与方法，用于测试依赖关系复杂的代码。</p>
</li>
<li><p>掌握<code>EXPECT_CALL</code>、<code>WillOnce</code>等Mock行为的匹配与控制。</p>
</li>
</ul>
</li>
<li><p><strong>性能测试</strong></p>
<ul>
<li><p>尽管GTest主要用于功能测试，仍可以通过自定义事件监听器或辅助工具结合性能测试。</p>
</li>
<li><p>使用高精度计时器测量单元测试的执行时间。</p>
</li>
</ul>
</li>
<li><p><strong>代码覆盖率</strong></p>
<ul>
<li>结合GTest与工具（如LCOV、gcov）生成代码覆盖率报告，确保测试用例覆盖了代码的关键路径。</li>
</ul>
</li>
<li><p><strong>持续集成与GTest</strong></p>
<ul>
<li><p>将GTest集成到持续集成（CI）管道中，结合Jenkins、GitHub Actions等自动化工具执行测试。</p>
</li>
<li><p>学习如何在CI中解析测试结果并生成报告。</p>
</li>
</ul>
</li>
<li><p><strong>测试策略与优化</strong></p>
<ul>
<li><p>探讨单元测试的设计策略，如何编写高效、可维护的测试案例。</p>
</li>
<li><p>优化测试运行时间，避免冗长的测试影响开发效率。</p>
</li>
</ul>
</li>
</ol>
<h3 id="heading-5yc6icd6lwe5paz">参考资料</h3>
<ul>
<li><p><a target="_blank" href="https://google.github.io/googletest/">Google Test 官方文档</a></p>
</li>
<li><p>《Google Test 实战：C++单元测试详解》</p>
</li>
</ul>
<p>通过掌握上述内容，您可以从GTest的新手逐步成长为高手，并将其应用于复杂项目的测试中。</p>
]]></content:encoded></item><item><title><![CDATA[Google Benchmark: 从入门到高手]]></title><description><![CDATA[Google Benchmark 是一个用于 C++ 的微基准测试库，帮助开发者测量代码片段的性能。通过这个库，您可以分析代码在不同输入、数据规模和系统配置下的表现。
一、入门使用
安装
您可以通过包管理器或从源代码构建安装 Google Benchmark：

使用 vcpkg 安装：
 vcpkg install benchmark


从源码构建：
 git clone https://github.com/google/benchmark.git
 cd benchmark
 cmake...]]></description><link>https://blog.wuzhiguo.tech/google-benchmark</link><guid isPermaLink="true">https://blog.wuzhiguo.tech/google-benchmark</guid><category><![CDATA[google benchmark]]></category><category><![CDATA[基准测试]]></category><category><![CDATA[性能测试]]></category><category><![CDATA[Benchmark]]></category><category><![CDATA[C++]]></category><dc:creator><![CDATA[wuzhiguocarter]]></dc:creator><pubDate>Sat, 24 Aug 2024 07:26:26 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1724497867590/65bba178-36cb-41aa-9c38-464bbd1b25b5.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Google Benchmark 是一个用于 C++ 的微基准测试库，帮助开发者测量代码片段的性能。通过这个库，您可以分析代码在不同输入、数据规模和系统配置下的表现。</p>
<h1 id="heading-5lia44cb5ywl6zeo5l255so">一、入门使用</h1>
<h3 id="heading-5a6j6kof">安装</h3>
<p>您可以通过包管理器或从源代码构建安装 Google Benchmark：</p>
<ol>
<li><p><strong>使用</strong> <code>vcpkg</code> 安装：</p>
<pre><code class="lang-sh"> vcpkg install benchmark
</code></pre>
</li>
<li><p><strong>从源码构建</strong>：</p>
<pre><code class="lang-sh"> git <span class="hljs-built_in">clone</span> https://github.com/google/benchmark.git
 <span class="hljs-built_in">cd</span> benchmark
 cmake -E make_directory <span class="hljs-string">"build"</span>
 cmake -E <span class="hljs-built_in">chdir</span> <span class="hljs-string">"build"</span> cmake ..
 cmake --build <span class="hljs-string">"build"</span> --config Release
 sudo cmake --build <span class="hljs-string">"build"</span> --config Release --target install
</code></pre>
</li>
</ol>
<h3 id="heading-5z65pys5l255so">基本使用</h3>
<ol>
<li><p><strong>包含头文件</strong>：</p>
<pre><code class="lang-cpp"> <span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;benchmark/benchmark.h&gt;</span></span>
</code></pre>
</li>
<li><p><strong>定义基准测试函数</strong>：</p>
<pre><code class="lang-cpp"> <span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">BM_Function</span><span class="hljs-params">(benchmark::State&amp; state)</span> </span>{
     <span class="hljs-keyword">for</span> (<span class="hljs-keyword">auto</span> _ : state) {
         <span class="hljs-comment">// 在此处放置您要基准测试的代码</span>
     }
 }
 BENCHMARK(BM_Function);
</code></pre>
<p> 在 <code>for (auto _ : state)</code> 循环中，基准测试函数会多次运行，以获取可靠的测量值。</p>
</li>
<li><p><strong>运行基准测试</strong>： 在主函数中使用 <code>BENCHMARK_MAIN();</code> 宏来运行所有定义的基准测试。</p>
<pre><code class="lang-cpp"> BENCHMARK_MAIN();
</code></pre>
</li>
</ol>
<h3 id="heading-6ieq5a6a5lmj5z65yeg5rwl6kv">自定义基准测试</h3>
<ol>
<li><p><strong>传递参数</strong>： 您可以使用 <code>Args</code> 或 <code>Range</code> 方法传递不同的参数，测试不同的输入规模或条件。</p>
<pre><code class="lang-cpp"> BENCHMARK(BM_Function)-&gt;Arg(<span class="hljs-number">8</span>)-&gt;Arg(<span class="hljs-number">16</span>);
 BENCHMARK(BM_Function)-&gt;Range(<span class="hljs-number">8</span>, <span class="hljs-number">8</span>&lt;&lt;<span class="hljs-number">10</span>);
</code></pre>
</li>
<li><p><strong>设置时间单位</strong>： 默认情况下，Google Benchmark 使用 <code>ns</code> 作为时间单位。您可以通过 <code>Unit</code> 方法更改为其他单位，例如 <code>ms</code>。</p>
<pre><code class="lang-cpp"> BENCHMARK(BM_Function)-&gt;Unit(benchmark::kMillisecond);
</code></pre>
</li>
<li><p><strong>多线程测试</strong>： 使用 <code>Threads</code> 方法指定线程数量，以测试多线程环境下的性能。</p>
<pre><code class="lang-cpp"> BENCHMARK(BM_Function)-&gt;Threads(<span class="hljs-number">2</span>);
</code></pre>
</li>
<li><p><strong>报告内存使用</strong>： 使用 <code>MeasureProcessMemory</code> 方法可以报告基准测试过程中内存的使用情况。</p>
<pre><code class="lang-cpp"> BENCHMARK(BM_Function)-&gt;MeasureProcessMemory();
</code></pre>
</li>
</ol>
<h3 id="heading-6lq6kgm5lio6l6t5ye6">运行与输出</h3>
<p>编译并运行基准测试代码，Google Benchmark 将自动处理计时和结果报告。输出结果包括基准测试名称、迭代次数和每次迭代的时间（例如 <code>ns/op</code>，<code>us/op</code>）。</p>
<h3 id="heading-56s65l6l">示例</h3>
<p>以下是一个简单的示例，测量创建一个空 <code>std::string</code> 对象所需的时间：</p>
<pre><code class="lang-cpp"><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;benchmark/benchmark.h&gt;</span></span>

<span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">BM_StringCreation</span><span class="hljs-params">(benchmark::State&amp; state)</span> </span>{
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">auto</span> _ : state) {
        <span class="hljs-built_in">std</span>::<span class="hljs-built_in">string</span> empty_string;
    }
}
BENCHMARK(BM_StringCreation);

BENCHMARK_MAIN();
</code></pre>
<p>在这个例子中，<code>BM_StringCreation</code> 测量了创建空字符串的时间。您可以通过 <code>BENCHMARK_MAIN()</code> 来运行这个基准测试。</p>
<h1 id="heading-5lqm44cb6lb6zi25l255so">二、进阶使用</h1>
<h2 id="heading-caes">基准测试的caes如何注入？</h2>
<p>在 Google Benchmark 中，您可以通过多种方式将测试用例（cases）注入到基准测试函数中，以测试代码在不同条件下的性能。这些用例通常是通过函数参数或通过 Google Benchmark 提供的专用 API 注入的。以下是几种常见的方法：</p>
<h3 id="heading-1-args">1. 使用 <code>Args</code> 注入单个参数</h3>
<p>如果您的基准测试需要单个参数，您可以使用 <code>Args</code> 方法为每个用例注入不同的值：</p>
<pre><code class="lang-cpp"><span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">BM_Function</span><span class="hljs-params">(benchmark::State&amp; state)</span> </span>{
    <span class="hljs-keyword">int</span> param = state.range(<span class="hljs-number">0</span>);  <span class="hljs-comment">// 读取参数</span>
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">auto</span> _ : state) {
        <span class="hljs-comment">// 使用参数 param 进行基准测试</span>
    }
}
BENCHMARK(BM_Function)-&gt;Arg(<span class="hljs-number">1</span>)-&gt;Arg(<span class="hljs-number">2</span>)-&gt;Arg(<span class="hljs-number">3</span>);
</code></pre>
<p>在这个例子中，<code>BM_Function</code> 函数会分别使用 1、2、3 作为参数进行测试。</p>
<h3 id="heading-2-range-ranges">2. 使用 <code>Range</code> 或 <code>Ranges</code> 注入一系列参数</h3>
<p><code>Range</code> 允许您为一个参数指定范围，而 <code>Ranges</code> 允许您为多个参数指定范围。Google Benchmark 会自动生成参数组合并运行测试。</p>
<pre><code class="lang-cpp"><span class="hljs-comment">// 使用单个参数范围</span>
BENCHMARK(BM_Function)-&gt;Range(<span class="hljs-number">8</span>, <span class="hljs-number">8</span>&lt;&lt;<span class="hljs-number">10</span>);

<span class="hljs-comment">// 使用多个参数范围</span>
BENCHMARK(BM_Function)-&gt;Ranges({{<span class="hljs-number">8</span>, <span class="hljs-number">8</span>&lt;&lt;<span class="hljs-number">10</span>}, {<span class="hljs-number">1</span>, <span class="hljs-number">4</span>}});
</code></pre>
<p>在这段代码中，第一个 <code>Range</code> 测试了 8 到 8&lt;&lt;10 范围内的参数。第二个 <code>Ranges</code> 测试了两个参数的所有组合。</p>
<h3 id="heading-3-argsproduct">3. 使用 <code>ArgsProduct</code> 注入参数的笛卡尔积</h3>
<p><code>ArgsProduct</code> 可以生成多个参数的笛卡尔积，以覆盖所有可能的参数组合。</p>
<pre><code class="lang-cpp"><span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">BM_Function</span><span class="hljs-params">(benchmark::State&amp; state)</span> </span>{
    <span class="hljs-keyword">int</span> param1 = state.range(<span class="hljs-number">0</span>);
    <span class="hljs-keyword">int</span> param2 = state.range(<span class="hljs-number">1</span>);
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">auto</span> _ : state) {
        <span class="hljs-comment">// 使用 param1 和 param2 进行基准测试</span>
    }
}

BENCHMARK(BM_Function)-&gt;ArgsProduct({{<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>}, {<span class="hljs-number">4</span>, <span class="hljs-number">5</span>}});
</code></pre>
<p>在这个例子中，<code>BM_Function</code> 将被分别调用 6 次，每次组合来自 <code>param1</code> 的 [1, 2, 3] 和 <code>param2</code> 的 [4, 5]。</p>
<h3 id="heading-4-complexity">4. 使用 <code>Complexity</code> 注入动态生成的测试用例</h3>
<p>如果您的测试用例生成逻辑更为复杂，可以通过动态生成测试用例的方式注入：</p>
<pre><code class="lang-cpp"><span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">BM_Function</span><span class="hljs-params">(benchmark::State&amp; state)</span> </span>{
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">auto</span> _ : state) {
        <span class="hljs-comment">// 根据输入动态生成测试用例</span>
        <span class="hljs-function"><span class="hljs-built_in">std</span>::<span class="hljs-built_in">vector</span>&lt;<span class="hljs-keyword">int</span>&gt; <span class="hljs-title">data</span><span class="hljs-params">(state.range(<span class="hljs-number">0</span>), <span class="hljs-number">42</span>)</span></span>;
        <span class="hljs-comment">// 测试逻辑</span>
    }
}

BENCHMARK(BM_Function)-&gt;RangeMultiplier(<span class="hljs-number">2</span>)-&gt;Range(<span class="hljs-number">8</span>, <span class="hljs-number">8</span>&lt;&lt;<span class="hljs-number">10</span>)-&gt;Complexity();
</code></pre>
<p>在这个例子中，<code>BM_Function</code> 会基于输入动态生成一个大小为 <code>state.range(0)</code> 的向量进行测试。</p>
<h3 id="heading-5-fixture">5. 使用 <code>Fixture</code> 为复杂的测试用例设置</h3>
<p>对于更复杂的设置，您可以使用 <code>BenchmarkFixture</code> 类，允许在每次测试之前设置和清理数据。</p>
<pre><code class="lang-cpp"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyBenchmark</span> :</span> <span class="hljs-keyword">public</span> benchmark::Fixture {
<span class="hljs-keyword">public</span>:
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">SetUp</span><span class="hljs-params">(<span class="hljs-keyword">const</span> ::benchmark::State&amp; state)</span> <span class="hljs-keyword">override</span> </span>{
        <span class="hljs-comment">// 设置代码</span>
    }

    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">TearDown</span><span class="hljs-params">(<span class="hljs-keyword">const</span> ::benchmark::State&amp; state)</span> <span class="hljs-keyword">override</span> </span>{
        <span class="hljs-comment">// 清理代码</span>
    }
};

BENCHMARK_DEFINE_F(MyBenchmark, BM_Test)(benchmark::State&amp; state) {
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">auto</span> _ : state) {
        <span class="hljs-comment">// 基准测试逻辑</span>
    }
}

BENCHMARK_REGISTER_F(MyBenchmark, BM_Test)-&gt;Args({<span class="hljs-number">8</span>});
</code></pre>
<p>这个例子中，<code>SetUp</code> 和 <code>TearDown</code> 会在每次基准测试前后被调用，从而可以设置和清理测试用例。</p>
<h3 id="heading-5oc757ut">总结</h3>
<p>通过这些方法，您可以灵活地将不同的测试用例注入到 Google Benchmark 的基准测试函数中，以测试不同的输入、配置和场景下代码的性能。</p>
<h1 id="heading-6zme5b2v">附录</h1>
<p><a target="_blank" href="https://github.com/google/benchmark/blob/main/docs/user_guide.md">benchmark user guide</a></p>
]]></content:encoded></item><item><title><![CDATA[Kubernetes（K8s）入门指南]]></title><description><![CDATA[Kubernetes（K8s）是现代容器化应用管理的核心技术，广泛应用于自动化部署、扩展和管理容器化应用程序。无论你是初学者还是有经验的开发者，本指南将带你深入了解 Kubernetes 的基本操作、架构设计以及如何在 Kubernetes 上部署各种常见的应用和服务。通过本文，你将掌握 Kubernetes 的核心概念和实用技巧，轻松应对复杂的容器编排任务。准备好开始你的 Kubernetes 之旅了吗？让我们一同探索这个强大的开源平台吧！
一、Kubernetes使用简介
Kubernete...]]></description><link>https://blog.wuzhiguo.tech/introduction-to-kubernetes</link><guid isPermaLink="true">https://blog.wuzhiguo.tech/introduction-to-kubernetes</guid><category><![CDATA[容器编排]]></category><category><![CDATA[自动化部署]]></category><category><![CDATA[集群管理]]></category><category><![CDATA[高可用性]]></category><category><![CDATA[Kubernetes]]></category><category><![CDATA[container orchestration]]></category><category><![CDATA[Automated deployment]]></category><category><![CDATA[cluster management ]]></category><category><![CDATA[#HighAvailability ]]></category><dc:creator><![CDATA[wuzhiguocarter]]></dc:creator><pubDate>Wed, 07 Aug 2024 15:03:15 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1724484096020/799cd977-e39b-4201-9d3c-22e95c663f65.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Kubernetes（K8s）是现代容器化应用管理的核心技术，广泛应用于自动化部署、扩展和管理容器化应用程序。无论你是初学者还是有经验的开发者，本指南将带你深入了解 Kubernetes 的基本操作、架构设计以及如何在 Kubernetes 上部署各种常见的应用和服务。通过本文，你将掌握 Kubernetes 的核心概念和实用技巧，轻松应对复杂的容器编排任务。准备好开始你的 Kubernetes 之旅了吗？让我们一同探索这个强大的开源平台吧！</p>
<h1 id="heading-kubernetes">一、Kubernetes使用简介</h1>
<p>Kubernetes（K8s）是一个开源的容器编排平台，用于自动化容器化应用的部署、扩展和管理。以下是 Kubernetes 常用命令和操作的简要介绍（tldr）：</p>
<h3 id="heading-1">1. 安装和配置</h3>
<p><strong>安装 kubectl</strong>（Kubernetes 命令行工具）：</p>
<ul>
<li><p><strong>Linux</strong>：</p>
<pre><code class="lang-bash">  curl -LO <span class="hljs-string">"https://dl.k8s.io/release/<span class="hljs-subst">$(curl -s https://dl.k8s.io/release/stable.txt)</span>/bin/linux/amd64/kubectl"</span>
  sudo chmod +x ./kubectl
  sudo mv ./kubectl /usr/<span class="hljs-built_in">local</span>/bin/kubectl
</code></pre>
</li>
<li><p><strong>macOS</strong>：</p>
<pre><code class="lang-bash">  brew install kubectl
</code></pre>
</li>
<li><p><strong>Windows</strong>：</p>
<p>  下载 <a target="_blank" href="https://kubernetes.io/docs/tasks/tools/install-kubectl-windows/">kubectl.exe</a> 并添加到系统 PATH。</p>
</li>
</ul>
<p><strong>配置 kubectl 访问 Kubernetes 集群</strong>：</p>
<pre><code class="lang-bash">kubectl config use-context &lt;context-name&gt;
</code></pre>
<h3 id="heading-2">2. 集群状态</h3>
<p><strong>查看集群信息</strong>：</p>
<pre><code class="lang-bash">kubectl cluster-info
</code></pre>
<p><strong>查看节点</strong>：</p>
<pre><code class="lang-bash">kubectl get nodes
</code></pre>
<p><strong>查看节点详细信息</strong>：</p>
<pre><code class="lang-bash">kubectl describe node &lt;node-name&gt;
</code></pre>
<h3 id="heading-3">3. 命名空间</h3>
<p><strong>列出所有命名空间</strong>：</p>
<pre><code class="lang-bash">kubectl get namespaces
</code></pre>
<p><strong>创建命名空间</strong>：</p>
<pre><code class="lang-bash">kubectl create namespace &lt;namespace-name&gt;
</code></pre>
<p><strong>删除命名空间</strong>：</p>
<pre><code class="lang-bash">kubectl delete namespace &lt;namespace-name&gt;
</code></pre>
<h3 id="heading-4-pod">4. Pod 管理</h3>
<p><strong>列出所有 Pods</strong>：</p>
<pre><code class="lang-bash">kubectl get pods
</code></pre>
<p><strong>查看 Pod 详细信息</strong>：</p>
<pre><code class="lang-bash">kubectl describe pod &lt;pod-name&gt;
</code></pre>
<p><strong>查看 Pod 日志</strong>：</p>
<pre><code class="lang-bash">kubectl logs &lt;pod-name&gt;
</code></pre>
<p><strong>删除 Pod</strong>：</p>
<pre><code class="lang-bash">kubectl delete pod &lt;pod-name&gt;
</code></pre>
<p><strong>创建 Pod</strong>（使用 YAML 文件）：</p>
<pre><code class="lang-bash">kubectl apply -f &lt;pod-definition-file&gt;.yaml
</code></pre>
<h3 id="heading-5">5. 部署管理</h3>
<p><strong>列出所有 Deployments</strong>：</p>
<pre><code class="lang-bash">kubectl get deployments
</code></pre>
<p><strong>查看 Deployment 详细信息</strong>：</p>
<pre><code class="lang-bash">kubectl describe deployment &lt;deployment-name&gt;
</code></pre>
<p><strong>创建 Deployment</strong>（使用 YAML 文件）：</p>
<pre><code class="lang-bash">kubectl apply -f &lt;deployment-definition-file&gt;.yaml
</code></pre>
<p><strong>更新 Deployment</strong>（滚动更新）：</p>
<pre><code class="lang-bash">kubectl <span class="hljs-built_in">set</span> image deployment/&lt;deployment-name&gt; &lt;container-name&gt;=&lt;image&gt;:&lt;tag&gt;
</code></pre>
<p><strong>删除 Deployment</strong>：</p>
<pre><code class="lang-bash">kubectl delete deployment &lt;deployment-name&gt;
</code></pre>
<h3 id="heading-6">6. 服务管理</h3>
<p><strong>列出所有 Services</strong>：</p>
<pre><code class="lang-bash">kubectl get services
</code></pre>
<p><strong>查看 Service 详细信息</strong>：</p>
<pre><code class="lang-bash">kubectl describe service &lt;service-name&gt;
</code></pre>
<p><strong>创建 Service</strong>（使用 YAML 文件）：</p>
<pre><code class="lang-bash">kubectl apply -f &lt;service-definition-file&gt;.yaml
</code></pre>
<p><strong>删除 Service</strong>：</p>
<pre><code class="lang-bash">kubectl delete service &lt;service-name&gt;
</code></pre>
<h3 id="heading-7">7. 配置和密钥管理</h3>
<p><strong>列出 ConfigMaps</strong>：</p>
<pre><code class="lang-bash">kubectl get configmaps
</code></pre>
<p><strong>查看 ConfigMap 详细信息</strong>：</p>
<pre><code class="lang-bash">kubectl describe configmap &lt;configmap-name&gt;
</code></pre>
<p><strong>创建 ConfigMap</strong>（使用 YAML 文件）：</p>
<pre><code class="lang-bash">kubectl apply -f &lt;configmap-definition-file&gt;.yaml
</code></pre>
<p><strong>删除 ConfigMap</strong>：</p>
<pre><code class="lang-bash">kubectl delete configmap &lt;configmap-name&gt;
</code></pre>
<p><strong>列出 Secrets</strong>：</p>
<pre><code class="lang-bash">kubectl get secrets
</code></pre>
<p><strong>查看 Secret 详细信息</strong>：</p>
<pre><code class="lang-bash">kubectl describe secret &lt;secret-name&gt;
</code></pre>
<p><strong>创建 Secret</strong>（使用 YAML 文件）：</p>
<pre><code class="lang-bash">kubectl apply -f &lt;secret-definition-file&gt;.yaml
</code></pre>
<p><strong>删除 Secret</strong>：</p>
<pre><code class="lang-bash">kubectl delete secret &lt;secret-name&gt;
</code></pre>
<h3 id="heading-8">8. 卷管理</h3>
<p><strong>列出 Persistent Volumes (PV)</strong>：</p>
<pre><code class="lang-bash">kubectl get pv
</code></pre>
<p><strong>查看 PV 详细信息</strong>：</p>
<pre><code class="lang-bash">kubectl describe pv &lt;pv-name&gt;
</code></pre>
<p><strong>列出 Persistent Volume Claims (PVC)</strong>：</p>
<pre><code class="lang-bash">kubectl get pvc
</code></pre>
<p><strong>查看 PVC 详细信息</strong>：</p>
<pre><code class="lang-bash">kubectl describe pvc &lt;pvc-name&gt;
</code></pre>
<p><strong>创建 PV/PVC</strong>（使用 YAML 文件）：</p>
<pre><code class="lang-bash">kubectl apply -f &lt;pv-or-pvc-definition-file&gt;.yaml
</code></pre>
<p><strong>删除 PV/PVC</strong>：</p>
<pre><code class="lang-bash">kubectl delete pv &lt;pv-name&gt;
kubectl delete pvc &lt;pvc-name&gt;
</code></pre>
<h3 id="heading-9">9. 诊断和故障排除</h3>
<p><strong>查看集群事件</strong>：</p>
<pre><code class="lang-bash">kubectl get events
</code></pre>
<p><strong>查看集群的 API 资源</strong>：</p>
<pre><code class="lang-bash">kubectl api-resources
</code></pre>
<p><strong>查看资源的详细描述</strong>：</p>
<pre><code class="lang-bash">kubectl describe &lt;resource-type&gt; &lt;resource-name&gt;
</code></pre>
<p><strong>调试 Pod</strong>（进入 Pod 中的容器）：</p>
<pre><code class="lang-bash">kubectl <span class="hljs-built_in">exec</span> -it &lt;pod-name&gt; -- /bin/bash
</code></pre>
<p>这些基本命令和操作可以帮助你管理 Kubernetes 集群、部署和维护应用程序。</p>
<h1 id="heading-kubernetes-1">二、Kubernetes架构设计</h1>
<p>Kubernetes 的架构设计是一个复杂的系统，涉及多个组件和概念。以下是 Kubernetes 架构的简要介绍（tldr）：</p>
<h3 id="heading-1-1">1. 核心组件</h3>
<p><strong>1.1 控制平面（Control Plane）</strong></p>
<ul>
<li><p><strong>Kubernetes API Server</strong>：负责处理 API 请求并与集群的其他组件进行通信。它是集群的中心控制点。</p>
<pre><code class="lang-plaintext">  API Server -&gt; etcd
</code></pre>
</li>
<li><p><strong>etcd</strong>：一个分布式键值存储，用于保存集群的配置数据和状态信息。它是 Kubernetes 的主要存储系统。</p>
<pre><code class="lang-plaintext">  API Server -&gt; etcd
</code></pre>
</li>
<li><p><strong>Controller Manager</strong>：运行集群中的控制器（如副本控制器、部署控制器等），负责维持集群的期望状态。</p>
<pre><code class="lang-plaintext">  Controller Manager -&gt; API Server
</code></pre>
</li>
<li><p><strong>Scheduler</strong>：负责将 Pods 调度到集群中的节点上。它根据资源需求、策略和其他约束来决定将 Pod 放在哪个节点上。</p>
<pre><code class="lang-plaintext">  Scheduler -&gt; API Server
</code></pre>
</li>
</ul>
<p><strong>1.2 节点（Node）</strong></p>
<ul>
<li><p><strong>Kubelet</strong>：在每个节点上运行，负责管理和确保容器的运行状态，负责与 API Server 通信，并执行容器的生命周期管理。</p>
<pre><code class="lang-plaintext">  Kubelet -&gt; API Server
</code></pre>
</li>
<li><p><strong>Kube-Proxy</strong>：负责维护网络规则，以便服务能够访问 Pod，并处理服务发现和负载均衡。</p>
<pre><code class="lang-plaintext">  Kube-Proxy -&gt; API Server
</code></pre>
</li>
<li><p><strong>Container Runtime</strong>：负责实际的容器运行和管理（如 Docker、containerd、CRI-O）。</p>
<pre><code class="lang-plaintext">  Container Runtime -&gt; Kubelet
</code></pre>
</li>
</ul>
<h3 id="heading-2-1">2. 核心概念</h3>
<p><strong>2.1 Pods</strong>：Kubernetes 中最小的可调度单元，可以包含一个或多个容器，这些容器共享网络、存储和配置。</p>
<p><strong>2.2 Deployments</strong>：定义和管理 Pods 的副本，确保 Pods 的数量和状态符合期望。</p>
<p><strong>2.3 Services</strong>：定义一组 Pods 的访问策略，提供负载均衡和服务发现功能。</p>
<p><strong>2.4 ConfigMaps 和 Secrets</strong>：分别用于管理配置数据和敏感数据。</p>
<p><strong>2.5 Volumes</strong>：持久存储，支持数据在 Pod 之间的共享和持久化。</p>
<p><strong>2.6 Namespaces</strong>：用于在同一集群中划分逻辑隔离的空间，支持资源的组织和管理。</p>
<h3 id="heading-3-1">3. 数据流和操作</h3>
<ul>
<li><p><strong>API 请求</strong>：用户通过 <code>kubectl</code> 或其他工具发起请求，API Server 处理这些请求并更新 etcd 中的状态信息。</p>
</li>
<li><p><strong>控制循环</strong>：控制器和调度器持续监控 API Server 中的状态，与期望状态进行对比，进行调整和更新。</p>
</li>
<li><p><strong>容器调度</strong>：Scheduler 根据集群状态和资源需求，将 Pods 调度到合适的节点上。</p>
</li>
<li><p><strong>容器管理</strong>：Kubelet 在节点上执行容器运行和管理任务，保持 Pod 的期望状态。</p>
</li>
</ul>
<h3 id="heading-4">4. 高可用和扩展性</h3>
<ul>
<li><p><strong>高可用控制平面</strong>：可以通过运行多个 API Server、Controller Manager 和 Scheduler 实例来实现。</p>
</li>
<li><p><strong>节点扩展</strong>：可以动态添加和删除节点来扩展或缩减集群容量。</p>
</li>
<li><p><strong>分布式存储</strong>：etcd 和其他组件支持分布式部署以保证数据的持久性和高可用性。</p>
</li>
</ul>
<p>通过这些组件和概念，Kubernetes 实现了容器化应用的自动化部署、扩展和管理。</p>
<h1 id="heading-elk">三、部署ELK</h1>
<p>在 Kubernetes 上部署 ELK（Elasticsearch, Logstash, Kibana）堆栈涉及多个步骤。ELK 堆栈是一个强大的日志处理和分析工具，广泛用于日志聚合和数据可视化。以下是简要的部署步骤（tldr）：</p>
<h3 id="heading-1-2">1. 准备工作</h3>
<p>确保你的 Kubernetes 集群已准备好，并且 <code>kubectl</code> 已配置为与集群通信。</p>
<h3 id="heading-2-elasticsearch">2. 部署 Elasticsearch</h3>
<p>Elasticsearch 是一个分布式搜索和分析引擎。你可以使用 Helm charts 或 YAML 配置文件来部署 Elasticsearch。</p>
<p><strong>使用 Helm 部署</strong>：</p>
<ol>
<li><p><strong>添加 Elastic Helm 仓库</strong>：</p>
<pre><code class="lang-bash"> helm repo add elastic https://helm.elastic.co
 helm repo update
</code></pre>
</li>
<li><p><strong>安装 Elasticsearch</strong>：</p>
<pre><code class="lang-bash"> helm install elasticsearch elastic/elasticsearch
</code></pre>
</li>
</ol>
<p><strong>使用 YAML 文件部署</strong>：</p>
<ol>
<li><p><strong>创建 Elasticsearch 部署 YAML 文件</strong>：</p>
<p> <strong>elasticsearch-deployment.yaml</strong>：</p>
<pre><code class="lang-yaml"> <span class="hljs-attr">apiVersion:</span> <span class="hljs-string">apps/v1</span>
 <span class="hljs-attr">kind:</span> <span class="hljs-string">Deployment</span>
 <span class="hljs-attr">metadata:</span>
   <span class="hljs-attr">name:</span> <span class="hljs-string">elasticsearch</span>
   <span class="hljs-attr">labels:</span>
     <span class="hljs-attr">app:</span> <span class="hljs-string">elasticsearch</span>
 <span class="hljs-attr">spec:</span>
   <span class="hljs-attr">replicas:</span> <span class="hljs-number">3</span>
   <span class="hljs-attr">selector:</span>
     <span class="hljs-attr">matchLabels:</span>
       <span class="hljs-attr">app:</span> <span class="hljs-string">elasticsearch</span>
   <span class="hljs-attr">template:</span>
     <span class="hljs-attr">metadata:</span>
       <span class="hljs-attr">labels:</span>
         <span class="hljs-attr">app:</span> <span class="hljs-string">elasticsearch</span>
     <span class="hljs-attr">spec:</span>
       <span class="hljs-attr">containers:</span>
       <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">elasticsearch</span>
         <span class="hljs-attr">image:</span> <span class="hljs-string">docker.elastic.co/elasticsearch/elasticsearch:7.9.3</span>
         <span class="hljs-attr">env:</span>
         <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">discovery.type</span>
           <span class="hljs-attr">value:</span> <span class="hljs-string">single-node</span>
         <span class="hljs-attr">ports:</span>
         <span class="hljs-bullet">-</span> <span class="hljs-attr">containerPort:</span> <span class="hljs-number">9200</span>
         <span class="hljs-attr">volumeMounts:</span>
         <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">es-data</span>
           <span class="hljs-attr">mountPath:</span> <span class="hljs-string">/usr/share/elasticsearch/data</span>
       <span class="hljs-attr">volumes:</span>
       <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">es-data</span>
         <span class="hljs-attr">emptyDir:</span> {}
</code></pre>
</li>
<li><p><strong>应用 YAML 文件</strong>：</p>
<pre><code class="lang-bash"> kubectl apply -f elasticsearch-deployment.yaml
</code></pre>
</li>
</ol>
<h3 id="heading-3-logstash">3. 部署 Logstash</h3>
<p>Logstash 是用于处理和转发日志数据的工具。与 Elasticsearch 类似，你可以使用 Helm 或 YAML 配置文件部署 Logstash。</p>
<p><strong>使用 Helm 部署</strong>：</p>
<ol>
<li><p><strong>安装 Logstash</strong>：</p>
<pre><code class="lang-bash"> helm install logstash elastic/logstash
</code></pre>
</li>
</ol>
<p><strong>使用 YAML 文件部署</strong>：</p>
<ol>
<li><p><strong>创建 Logstash 部署 YAML 文件</strong>：</p>
<p> <strong>logstash-deployment.yaml</strong>：</p>
<pre><code class="lang-yaml"> <span class="hljs-attr">apiVersion:</span> <span class="hljs-string">apps/v1</span>
 <span class="hljs-attr">kind:</span> <span class="hljs-string">Deployment</span>
 <span class="hljs-attr">metadata:</span>
   <span class="hljs-attr">name:</span> <span class="hljs-string">logstash</span>
   <span class="hljs-attr">labels:</span>
     <span class="hljs-attr">app:</span> <span class="hljs-string">logstash</span>
 <span class="hljs-attr">spec:</span>
   <span class="hljs-attr">replicas:</span> <span class="hljs-number">1</span>
   <span class="hljs-attr">selector:</span>
     <span class="hljs-attr">matchLabels:</span>
       <span class="hljs-attr">app:</span> <span class="hljs-string">logstash</span>
   <span class="hljs-attr">template:</span>
     <span class="hljs-attr">metadata:</span>
       <span class="hljs-attr">labels:</span>
         <span class="hljs-attr">app:</span> <span class="hljs-string">logstash</span>
     <span class="hljs-attr">spec:</span>
       <span class="hljs-attr">containers:</span>
       <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">logstash</span>
         <span class="hljs-attr">image:</span> <span class="hljs-string">docker.elastic.co/logstash/logstash:7.9.3</span>
         <span class="hljs-attr">ports:</span>
         <span class="hljs-bullet">-</span> <span class="hljs-attr">containerPort:</span> <span class="hljs-number">5044</span>
         <span class="hljs-attr">volumeMounts:</span>
         <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">logstash-config</span>
           <span class="hljs-attr">mountPath:</span> <span class="hljs-string">/usr/share/logstash/config</span>
       <span class="hljs-attr">volumes:</span>
       <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">logstash-config</span>
         <span class="hljs-attr">configMap:</span>
           <span class="hljs-attr">name:</span> <span class="hljs-string">logstash-config</span>
</code></pre>
</li>
<li><p><strong>创建 Logstash 配置 ConfigMap</strong>：</p>
<p> <strong>logstash-configmap.yaml</strong>：</p>
<pre><code class="lang-yaml"> <span class="hljs-attr">apiVersion:</span> <span class="hljs-string">v1</span>
 <span class="hljs-attr">kind:</span> <span class="hljs-string">ConfigMap</span>
 <span class="hljs-attr">metadata:</span>
   <span class="hljs-attr">name:</span> <span class="hljs-string">logstash-config</span>
 <span class="hljs-attr">data:</span>
   <span class="hljs-attr">logstash.conf:</span> <span class="hljs-string">|
     input {
       beats {
         port =&gt; 5044
       }
     }
     output {
       elasticsearch {
         hosts =&gt; ["http://elasticsearch:9200"]
       }
     }</span>
</code></pre>
</li>
<li><p><strong>应用 YAML 文件</strong>：</p>
<pre><code class="lang-bash"> kubectl apply -f logstash-configmap.yaml
 kubectl apply -f logstash-deployment.yaml
</code></pre>
</li>
</ol>
<h3 id="heading-4-kibana">4. 部署 Kibana</h3>
<p>Kibana 是用于可视化 Elasticsearch 数据的工具。</p>
<p><strong>使用 Helm 部署</strong>：</p>
<ol>
<li><p><strong>安装 Kibana</strong>：</p>
<pre><code class="lang-bash"> helm install kibana elastic/kibana
</code></pre>
</li>
</ol>
<p><strong>使用 YAML 文件部署</strong>：</p>
<ol>
<li><p><strong>创建 Kibana 部署 YAML 文件</strong>：</p>
<p> <strong>kibana-deployment.yaml</strong>：</p>
<pre><code class="lang-yaml"> <span class="hljs-attr">apiVersion:</span> <span class="hljs-string">apps/v1</span>
 <span class="hljs-attr">kind:</span> <span class="hljs-string">Deployment</span>
 <span class="hljs-attr">metadata:</span>
   <span class="hljs-attr">name:</span> <span class="hljs-string">kibana</span>
   <span class="hljs-attr">labels:</span>
     <span class="hljs-attr">app:</span> <span class="hljs-string">kibana</span>
 <span class="hljs-attr">spec:</span>
   <span class="hljs-attr">replicas:</span> <span class="hljs-number">1</span>
   <span class="hljs-attr">selector:</span>
     <span class="hljs-attr">matchLabels:</span>
       <span class="hljs-attr">app:</span> <span class="hljs-string">kibana</span>
   <span class="hljs-attr">template:</span>
     <span class="hljs-attr">metadata:</span>
       <span class="hljs-attr">labels:</span>
         <span class="hljs-attr">app:</span> <span class="hljs-string">kibana</span>
     <span class="hljs-attr">spec:</span>
       <span class="hljs-attr">containers:</span>
       <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">kibana</span>
         <span class="hljs-attr">image:</span> <span class="hljs-string">docker.elastic.co/kibana/kibana:7.9.3</span>
         <span class="hljs-attr">ports:</span>
         <span class="hljs-bullet">-</span> <span class="hljs-attr">containerPort:</span> <span class="hljs-number">5601</span>
         <span class="hljs-attr">env:</span>
         <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">ELASTICSEARCH_HOSTS</span>
           <span class="hljs-attr">value:</span> <span class="hljs-string">"http://elasticsearch:9200"</span>
</code></pre>
</li>
<li><p><strong>应用 YAML 文件</strong>：</p>
<pre><code class="lang-bash"> kubectl apply -f kibana-deployment.yaml
</code></pre>
</li>
</ol>
<h3 id="heading-5-1">5. 创建服务</h3>
<p><strong>创建服务暴露 Elasticsearch、Logstash 和 Kibana</strong>：</p>
<ol>
<li><p><strong>Elasticsearch 服务</strong>：</p>
<p> <strong>elasticsearch-service.yaml</strong>：</p>
<pre><code class="lang-yaml"> <span class="hljs-attr">apiVersion:</span> <span class="hljs-string">v1</span>
 <span class="hljs-attr">kind:</span> <span class="hljs-string">Service</span>
 <span class="hljs-attr">metadata:</span>
   <span class="hljs-attr">name:</span> <span class="hljs-string">elasticsearch</span>
 <span class="hljs-attr">spec:</span>
   <span class="hljs-attr">ports:</span>
   <span class="hljs-bullet">-</span> <span class="hljs-attr">port:</span> <span class="hljs-number">9200</span>
   <span class="hljs-attr">selector:</span>
     <span class="hljs-attr">app:</span> <span class="hljs-string">elasticsearch</span>
</code></pre>
</li>
<li><p><strong>Logstash 服务</strong>：</p>
<p> <strong>logstash-service.yaml</strong>：</p>
<pre><code class="lang-yaml"> <span class="hljs-attr">apiVersion:</span> <span class="hljs-string">v1</span>
 <span class="hljs-attr">kind:</span> <span class="hljs-string">Service</span>
 <span class="hljs-attr">metadata:</span>
   <span class="hljs-attr">name:</span> <span class="hljs-string">logstash</span>
 <span class="hljs-attr">spec:</span>
   <span class="hljs-attr">ports:</span>
   <span class="hljs-bullet">-</span> <span class="hljs-attr">port:</span> <span class="hljs-number">5044</span>
   <span class="hljs-attr">selector:</span>
     <span class="hljs-attr">app:</span> <span class="hljs-string">logstash</span>
</code></pre>
</li>
<li><p><strong>Kibana 服务</strong>：</p>
<p> <strong>kibana-service.yaml</strong>：</p>
<pre><code class="lang-yaml"> <span class="hljs-attr">apiVersion:</span> <span class="hljs-string">v1</span>
 <span class="hljs-attr">kind:</span> <span class="hljs-string">Service</span>
 <span class="hljs-attr">metadata:</span>
   <span class="hljs-attr">name:</span> <span class="hljs-string">kibana</span>
 <span class="hljs-attr">spec:</span>
   <span class="hljs-attr">ports:</span>
   <span class="hljs-bullet">-</span> <span class="hljs-attr">port:</span> <span class="hljs-number">5601</span>
   <span class="hljs-attr">selector:</span>
     <span class="hljs-attr">app:</span> <span class="hljs-string">kibana</span>
</code></pre>
</li>
<li><p><strong>应用服务 YAML 文件</strong>：</p>
<pre><code class="lang-bash"> kubectl apply -f elasticsearch-service.yaml
 kubectl apply -f logstash-service.yaml
 kubectl apply -f kibana-service.yaml
</code></pre>
</li>
</ol>
<h3 id="heading-6-kibana">6. 访问 Kibana</h3>
<p><strong>获取 Kibana 服务的外部 IP 地址</strong>：</p>
<pre><code class="lang-bash">kubectl get services
</code></pre>
<p>使用浏览器访问 Kibana 的外部 IP 地址（通常是端口 <code>5601</code>）。</p>
<p>通过这些步骤，你可以在 Kubernetes 集群中部署和运行 ELK 堆栈，实现日志数据的收集、处理和可视化。</p>
<h1 id="heading-prometheus-grafana">四、部署 Prometheus 和 Grafana</h1>
<p>在 Kubernetes 集群中部署 Prometheus 和 Grafana 进行监控是一个常见的做法。Prometheus 是一个开源监控和警报系统，Grafana 是一个开源的数据可视化平台。以下是如何在 Kubernetes 上部署 Prometheus 和 Grafana 的步骤。</p>
<h3 id="heading-1-prometheus">1. 部署 Prometheus</h3>
<p>Prometheus 是一个用于收集和存储指标数据的系统。可以使用 Helm 或直接使用 YAML 文件来部署 Prometheus。</p>
<h4 id="heading-helm-prometheus">使用 Helm 部署 Prometheus</h4>
<ol>
<li><p><strong>添加 Prometheus Helm 仓库</strong>：</p>
<pre><code class="lang-bash"> helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
 helm repo update
</code></pre>
</li>
<li><p><strong>安装 Prometheus</strong>：</p>
<pre><code class="lang-bash"> helm install prometheus prometheus-community/prometheus
</code></pre>
<p> 这将自动创建 Prometheus 的部署、服务以及其他必要资源。</p>
</li>
</ol>
<h4 id="heading-yaml-prometheus">使用 YAML 文件部署 Prometheus</h4>
<ol>
<li><p><strong>创建 Prometheus 配置 ConfigMap</strong>：</p>
<p> <strong>prometheus-configmap.yaml</strong>：</p>
<pre><code class="lang-yaml"> <span class="hljs-attr">apiVersion:</span> <span class="hljs-string">v1</span>
 <span class="hljs-attr">kind:</span> <span class="hljs-string">ConfigMap</span>
 <span class="hljs-attr">metadata:</span>
   <span class="hljs-attr">name:</span> <span class="hljs-string">prometheus-config</span>
 <span class="hljs-attr">data:</span>
   <span class="hljs-attr">prometheus.yml:</span> <span class="hljs-string">|
     global:
       scrape_interval: 15s
     scrape_configs:
       - job_name: 'kubernetes-apiservers'
         kubernetes_sd_configs:
           - role: endpoints
         relabel_configs:
           - source_labels: [__meta_kubernetes_service_name]
             action: keep
             regex: kubernetes</span>
</code></pre>
</li>
<li><p><strong>创建 Prometheus 部署 YAML 文件</strong>：</p>
<p> <strong>prometheus-deployment.yaml</strong>：</p>
<pre><code class="lang-yaml"> <span class="hljs-attr">apiVersion:</span> <span class="hljs-string">apps/v1</span>
 <span class="hljs-attr">kind:</span> <span class="hljs-string">Deployment</span>
 <span class="hljs-attr">metadata:</span>
   <span class="hljs-attr">name:</span> <span class="hljs-string">prometheus</span>
   <span class="hljs-attr">labels:</span>
     <span class="hljs-attr">app:</span> <span class="hljs-string">prometheus</span>
 <span class="hljs-attr">spec:</span>
   <span class="hljs-attr">replicas:</span> <span class="hljs-number">1</span>
   <span class="hljs-attr">selector:</span>
     <span class="hljs-attr">matchLabels:</span>
       <span class="hljs-attr">app:</span> <span class="hljs-string">prometheus</span>
   <span class="hljs-attr">template:</span>
     <span class="hljs-attr">metadata:</span>
       <span class="hljs-attr">labels:</span>
         <span class="hljs-attr">app:</span> <span class="hljs-string">prometheus</span>
     <span class="hljs-attr">spec:</span>
       <span class="hljs-attr">containers:</span>
       <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">prometheus</span>
         <span class="hljs-attr">image:</span> <span class="hljs-string">prom/prometheus:latest</span>
         <span class="hljs-attr">ports:</span>
         <span class="hljs-bullet">-</span> <span class="hljs-attr">containerPort:</span> <span class="hljs-number">9090</span>
         <span class="hljs-attr">volumeMounts:</span>
         <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">prometheus-config</span>
           <span class="hljs-attr">mountPath:</span> <span class="hljs-string">/etc/prometheus</span>
           <span class="hljs-attr">subPath:</span> <span class="hljs-string">prometheus.yml</span>
       <span class="hljs-attr">volumes:</span>
       <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">prometheus-config</span>
         <span class="hljs-attr">configMap:</span>
           <span class="hljs-attr">name:</span> <span class="hljs-string">prometheus-config</span>
</code></pre>
</li>
<li><p><strong>创建 Prometheus 服务 YAML 文件</strong>：</p>
<p> <strong>prometheus-service.yaml</strong>：</p>
<pre><code class="lang-yaml"> <span class="hljs-attr">apiVersion:</span> <span class="hljs-string">v1</span>
 <span class="hljs-attr">kind:</span> <span class="hljs-string">Service</span>
 <span class="hljs-attr">metadata:</span>
   <span class="hljs-attr">name:</span> <span class="hljs-string">prometheus</span>
 <span class="hljs-attr">spec:</span>
   <span class="hljs-attr">ports:</span>
   <span class="hljs-bullet">-</span> <span class="hljs-attr">port:</span> <span class="hljs-number">9090</span>
   <span class="hljs-attr">selector:</span>
     <span class="hljs-attr">app:</span> <span class="hljs-string">prometheus</span>
</code></pre>
</li>
<li><p><strong>应用 YAML 文件</strong>：</p>
<pre><code class="lang-bash"> kubectl apply -f prometheus-configmap.yaml
 kubectl apply -f prometheus-deployment.yaml
 kubectl apply -f prometheus-service.yaml
</code></pre>
</li>
</ol>
<h3 id="heading-2-grafana">2. 部署 Grafana</h3>
<p>Grafana 用于将 Prometheus 收集的指标数据可视化。</p>
<h4 id="heading-helm-grafana">使用 Helm 部署 Grafana</h4>
<ol>
<li><p><strong>安装 Grafana</strong>：</p>
<pre><code class="lang-bash"> helm install grafana grafana/grafana
</code></pre>
<p> 这将创建 Grafana 的部署、服务和相关资源。</p>
</li>
</ol>
<h4 id="heading-yaml-grafana">使用 YAML 文件部署 Grafana</h4>
<ol>
<li><p><strong>创建 Grafana 部署 YAML 文件</strong>：</p>
<p> <strong>grafana-deployment.yaml</strong>：</p>
<pre><code class="lang-yaml"> <span class="hljs-attr">apiVersion:</span> <span class="hljs-string">apps/v1</span>
 <span class="hljs-attr">kind:</span> <span class="hljs-string">Deployment</span>
 <span class="hljs-attr">metadata:</span>
   <span class="hljs-attr">name:</span> <span class="hljs-string">grafana</span>
   <span class="hljs-attr">labels:</span>
     <span class="hljs-attr">app:</span> <span class="hljs-string">grafana</span>
 <span class="hljs-attr">spec:</span>
   <span class="hljs-attr">replicas:</span> <span class="hljs-number">1</span>
   <span class="hljs-attr">selector:</span>
     <span class="hljs-attr">matchLabels:</span>
       <span class="hljs-attr">app:</span> <span class="hljs-string">grafana</span>
   <span class="hljs-attr">template:</span>
     <span class="hljs-attr">metadata:</span>
       <span class="hljs-attr">labels:</span>
         <span class="hljs-attr">app:</span> <span class="hljs-string">grafana</span>
     <span class="hljs-attr">spec:</span>
       <span class="hljs-attr">containers:</span>
       <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">grafana</span>
         <span class="hljs-attr">image:</span> <span class="hljs-string">grafana/grafana:latest</span>
         <span class="hljs-attr">ports:</span>
         <span class="hljs-bullet">-</span> <span class="hljs-attr">containerPort:</span> <span class="hljs-number">3000</span>
</code></pre>
</li>
<li><p><strong>创建 Grafana 服务 YAML 文件</strong>：</p>
<p> <strong>grafana-service.yaml</strong>：</p>
<pre><code class="lang-yaml"> <span class="hljs-attr">apiVersion:</span> <span class="hljs-string">v1</span>
 <span class="hljs-attr">kind:</span> <span class="hljs-string">Service</span>
 <span class="hljs-attr">metadata:</span>
   <span class="hljs-attr">name:</span> <span class="hljs-string">grafana</span>
 <span class="hljs-attr">spec:</span>
   <span class="hljs-attr">ports:</span>
   <span class="hljs-bullet">-</span> <span class="hljs-attr">port:</span> <span class="hljs-number">3000</span>
   <span class="hljs-attr">selector:</span>
     <span class="hljs-attr">app:</span> <span class="hljs-string">grafana</span>
</code></pre>
</li>
<li><p><strong>应用 YAML 文件</strong>：</p>
<pre><code class="lang-bash"> kubectl apply -f grafana-deployment.yaml
 kubectl apply -f grafana-service.yaml
</code></pre>
</li>
</ol>
<h3 id="heading-3-prometheus">3. 配置 Prometheus 数据源</h3>
<ol>
<li><p><strong>获取 Grafana 服务的外部 IP 地址</strong>：</p>
<pre><code class="lang-bash"> kubectl get services
</code></pre>
</li>
<li><p><strong>访问 Grafana</strong>：通过浏览器访问 Grafana 的外部 IP 地址（通常是端口 <code>3000</code>）。</p>
</li>
<li><p><strong>登录 Grafana</strong>：默认用户名和密码通常是 <code>admin</code> / <code>admin</code>。你可以在 Grafana 的设置中更改密码。</p>
</li>
<li><p><strong>添加 Prometheus 数据源</strong>：</p>
<ul>
<li><p>登录到 Grafana。</p>
</li>
<li><p>进入 <code>Configuration</code> &gt; <code>Data Sources</code>。</p>
</li>
<li><p>点击 <code>Add data source</code>。</p>
</li>
<li><p>选择 <code>Prometheus</code>。</p>
</li>
<li><p>配置 Prometheus 的 URL（例如 <a target="_blank" href="http://prometheus:9090%EF%BC%89%E3%80%82"><code>http://prometheus:9090</code>）。</a></p>
</li>
<li><p>点击 <code>Save &amp; Test</code> 确认连接成功。</p>
</li>
</ul>
</li>
</ol>
<h3 id="heading-4-1">4. 创建仪表板和可视化</h3>
<ol>
<li><p><strong>创建 Grafana 仪表板</strong>：</p>
<ul>
<li><p>进入 <code>Create</code> &gt; <code>Dashboard</code>。</p>
</li>
<li><p>添加新的 <code>Panel</code>。</p>
</li>
<li><p>配置查询、图表和可视化选项。</p>
</li>
<li><p>保存仪表板。</p>
</li>
</ul>
</li>
</ol>
<h3 id="heading-5-2">5. 监控和维护</h3>
<ul>
<li><p><strong>验证数据</strong>：确保 Grafana 能够从 Prometheus 获取数据，并且可视化显示正常。</p>
</li>
<li><p><strong>调整配置</strong>：根据需求调整 Prometheus 和 Grafana 的配置。</p>
</li>
<li><p><strong>定期检查</strong>：监控系统的运行状态和性能，定期检查日志和警报。</p>
</li>
</ul>
<p>通过这些步骤，你可以在 Kubernetes 集群中部署 Prometheus 和 Grafana，构建一个强大的监控和可视化系统。</p>
<h1 id="heading-mysql">五、部署MySQL集群</h1>
<p>在 Kubernetes 上部署 MySQL 集群，并配置主从复制（支持一主多从），涉及到多个步骤。你需要配置主数据库、从数据库以及它们之间的复制关系。以下是一个简要的指南，帮助你完成这一部署：</p>
<h3 id="heading-1-3">1. 准备工作</h3>
<p>确保 Kubernetes 集群正常运行，并且 <code>kubectl</code> 已配置为与集群通信。</p>
<h3 id="heading-2-mysql">2. 部署 MySQL 主节点</h3>
<h4 id="heading-helm-mysql">使用 Helm 部署 MySQL</h4>
<ol>
<li><p><strong>添加 Bitnami Helm 仓库</strong>（提供 MySQL chart）：</p>
<pre><code class="lang-bash"> helm repo add bitnami https://charts.bitnami.com/bitnami
 helm repo update
</code></pre>
</li>
<li><p><strong>安装 MySQL 主节点</strong>：</p>
<pre><code class="lang-bash"> helm install mysql-master bitnami/mysql \
   --<span class="hljs-built_in">set</span> replication.enabled=<span class="hljs-literal">false</span> \
   --<span class="hljs-built_in">set</span> mysqlRootPassword=your_root_password \
   --<span class="hljs-built_in">set</span> mysqlUser=your_user \
   --<span class="hljs-built_in">set</span> mysqlPassword=your_password \
   --<span class="hljs-built_in">set</span> mysqlDatabase=your_database
</code></pre>
<p> 这里 <code>replication.enabled=false</code> 表示这是主节点，主节点不需要复制功能。</p>
</li>
</ol>
<h3 id="heading-3-mysql">3. 部署 MySQL 从节点</h3>
<ol>
<li><p><strong>创建 MySQL 从节点的自定义值文件</strong>（<code>values-replica.yaml</code>）：</p>
<pre><code class="lang-yaml"> <span class="hljs-attr">replica:</span>
   <span class="hljs-attr">enabled:</span> <span class="hljs-literal">true</span>
   <span class="hljs-attr">replicas:</span> <span class="hljs-number">3</span>
   <span class="hljs-attr">configuration:</span> <span class="hljs-string">|
     [mysqld]
     server-id=2
     log-bin=mysql-bin
     relay-log=mysqld-relay-bin
     binlog-do-db=your_database
</span> <span class="hljs-attr">primary:</span>
   <span class="hljs-attr">service:</span>
     <span class="hljs-attr">name:</span> <span class="hljs-string">mysql-master</span>
   <span class="hljs-attr">replication:</span>
     <span class="hljs-attr">enabled:</span> <span class="hljs-literal">true</span>
     <span class="hljs-attr">user:</span> <span class="hljs-string">your_replication_user</span>
     <span class="hljs-attr">password:</span> <span class="hljs-string">your_replication_password</span>
     <span class="hljs-attr">database:</span> <span class="hljs-string">your_database</span>
</code></pre>
<p> 这里 <code>server-id=2</code> 用于区分从节点。<a target="_blank" href="http://primary.service.name"><code>primary.service.name</code></a> 应该与主节点服务名称匹配。</p>
</li>
<li><p><strong>安装 MySQL 从节点</strong>：</p>
<pre><code class="lang-bash"> helm install mysql-replicas bitnami/mysql \
   -f values-replica.yaml
</code></pre>
</li>
</ol>
<h3 id="heading-4-mysql">4. 配置 MySQL 主从复制</h3>
<ol>
<li><p><strong>获取主节点的连接信息</strong>：</p>
<pre><code class="lang-bash"> kubectl get svc mysql-master
</code></pre>
<p> 记录下主节点的服务名称和端口。</p>
</li>
<li><p><strong>在主节点上配置复制用户</strong>：</p>
<p> 进入 MySQL 主节点的 Pod：</p>
<pre><code class="lang-bash"> kubectl <span class="hljs-built_in">exec</span> -it &lt;mysql-master-pod&gt; -- mysql -uroot -p
</code></pre>
<p> 创建一个用于复制的用户：</p>
<pre><code class="lang-sql"> <span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">USER</span> <span class="hljs-string">'replication_user'</span>@<span class="hljs-string">'%'</span> <span class="hljs-keyword">IDENTIFIED</span> <span class="hljs-keyword">BY</span> <span class="hljs-string">'replication_password'</span>;
 <span class="hljs-keyword">GRANT</span> <span class="hljs-keyword">REPLICATION</span> <span class="hljs-keyword">SLAVE</span> <span class="hljs-keyword">ON</span> *.* <span class="hljs-keyword">TO</span> <span class="hljs-string">'replication_user'</span>@<span class="hljs-string">'%'</span>;
 <span class="hljs-keyword">FLUSH</span> <span class="hljs-keyword">PRIVILEGES</span>;
</code></pre>
<p> 获取主节点的二进制日志文件名和位置：</p>
<pre><code class="lang-sql"> <span class="hljs-keyword">SHOW</span> <span class="hljs-keyword">MASTER</span> <span class="hljs-keyword">STATUS</span>;
</code></pre>
<p> 记录下 <code>File</code> 和 <code>Position</code> 的值。</p>
</li>
<li><p><strong>在从节点上配置复制</strong>：</p>
<p> 进入 MySQL 从节点的 Pod：</p>
<pre><code class="lang-bash"> kubectl <span class="hljs-built_in">exec</span> -it &lt;mysql-replica-pod&gt; -- mysql -uroot -p
</code></pre>
<p> 配置从节点连接到主节点：</p>
<pre><code class="lang-sql"> <span class="hljs-keyword">CHANGE</span> <span class="hljs-keyword">MASTER</span> <span class="hljs-keyword">TO</span>
   MASTER_HOST=<span class="hljs-string">'mysql-master'</span>,
   MASTER_USER=<span class="hljs-string">'replication_user'</span>,
   MASTER_PASSWORD=<span class="hljs-string">'replication_password'</span>,
   MASTER_LOG_FILE=<span class="hljs-string">'mysql-bin.000001'</span>,  <span class="hljs-comment">-- Replace with File from SHOW MASTER STATUS</span>
   MASTER_LOG_POS= <span class="hljs-number">4</span>;  <span class="hljs-comment">-- Replace with Position from SHOW MASTER STATUS</span>
 <span class="hljs-keyword">START</span> <span class="hljs-keyword">SLAVE</span>;
</code></pre>
</li>
<li><p><strong>验证复制状态</strong>：</p>
<pre><code class="lang-sql"> <span class="hljs-keyword">SHOW</span> <span class="hljs-keyword">SLAVE</span> <span class="hljs-keyword">STATUS</span>\G;
</code></pre>
<p> 确保 <code>Slave_IO_Running</code> 和 <code>Slave_SQL_Running</code> 都显示为 <code>Yes</code>。</p>
</li>
</ol>
<h3 id="heading-5-3">5. 维护和监控</h3>
<ul>
<li><p><strong>监控 MySQL 实例</strong>：使用 Prometheus + Grafana 或其他监控工具来监控 MySQL 的健康状态和性能。</p>
</li>
<li><p><strong>备份数据</strong>：配置备份和恢复策略以确保数据安全。</p>
</li>
<li><p><strong>故障排除</strong>：定期检查日志文件，确保复制正常进行。</p>
</li>
</ul>
<p>通过这些步骤，你可以在 Kubernetes 上部署一个支持主从复制的 MySQL 集群，其中一个主节点和多个从节点。</p>
<h1 id="heading-mq">六、部署MQ集群</h1>
<p>在 Kubernetes 上部署一个消息队列（MQ）集群可以选择多种流行的消息队列系统，如 RabbitMQ、Apache Kafka 和 NATS 等。以下是如何在 Kubernetes 上部署 RabbitMQ 和 Apache Kafka 的步骤，因为这两个系统在生产环境中都非常流行，并且支持高可用性和分布式部署。</p>
<h3 id="heading-rabbitmq">部署 RabbitMQ 集群</h3>
<p>RabbitMQ 是一个流行的开源消息代理，支持 AMQP 协议，并且可以配置成集群模式以实现高可用性。</p>
<h4 id="heading-helm-rabbitmq">使用 Helm 部署 RabbitMQ</h4>
<ol>
<li><p><strong>添加 Bitnami Helm 仓库</strong>：</p>
<pre><code class="lang-bash"> helm repo add bitnami https://charts.bitnami.com/bitnami
 helm repo update
</code></pre>
</li>
<li><p><strong>安装 RabbitMQ 集群</strong>：</p>
<pre><code class="lang-bash"> helm install rabbitmq bitnami/rabbitmq \
   --<span class="hljs-built_in">set</span> replicaCount=3 \
   --<span class="hljs-built_in">set</span> auth.username=your_user \
   --<span class="hljs-built_in">set</span> auth.password=your_password \
   --<span class="hljs-built_in">set</span> auth.erlangCookie=your_erlang_cookie
</code></pre>
<ul>
<li><p><code>replicaCount=3</code> 表示部署一个包含 3 个 RabbitMQ 节点的集群。</p>
</li>
<li><p><code>auth.username</code> 和 <code>auth.password</code> 是 RabbitMQ 的管理用户名和密码。</p>
</li>
<li><p><code>auth.erlangCookie</code> 是 RabbitMQ 节点之间通信的 Erlang Cookie，必须相同。</p>
</li>
</ul>
</li>
</ol>
<h4 id="heading-yaml-rabbitmq">使用 YAML 文件部署 RabbitMQ</h4>
<ol>
<li><p><strong>创建 RabbitMQ 配置文件</strong>：</p>
<p> <strong>rabbitmq-configmap.yaml</strong>：</p>
<pre><code class="lang-yaml"> <span class="hljs-attr">apiVersion:</span> <span class="hljs-string">v1</span>
 <span class="hljs-attr">kind:</span> <span class="hljs-string">ConfigMap</span>
 <span class="hljs-attr">metadata:</span>
   <span class="hljs-attr">name:</span> <span class="hljs-string">rabbitmq-config</span>
 <span class="hljs-attr">data:</span>
   <span class="hljs-attr">rabbitmq.conf:</span> <span class="hljs-string">|</span>
     <span class="hljs-string">loopback_users.guest</span> <span class="hljs-string">=</span> <span class="hljs-literal">false</span>
</code></pre>
</li>
<li><p><strong>创建 RabbitMQ 部署 YAML 文件</strong>：</p>
<p> <strong>rabbitmq-deployment.yaml</strong>：</p>
<pre><code class="lang-yaml"> <span class="hljs-attr">apiVersion:</span> <span class="hljs-string">apps/v1</span>
 <span class="hljs-attr">kind:</span> <span class="hljs-string">Deployment</span>
 <span class="hljs-attr">metadata:</span>
   <span class="hljs-attr">name:</span> <span class="hljs-string">rabbitmq</span>
   <span class="hljs-attr">labels:</span>
     <span class="hljs-attr">app:</span> <span class="hljs-string">rabbitmq</span>
 <span class="hljs-attr">spec:</span>
   <span class="hljs-attr">replicas:</span> <span class="hljs-number">3</span>
   <span class="hljs-attr">selector:</span>
     <span class="hljs-attr">matchLabels:</span>
       <span class="hljs-attr">app:</span> <span class="hljs-string">rabbitmq</span>
   <span class="hljs-attr">template:</span>
     <span class="hljs-attr">metadata:</span>
       <span class="hljs-attr">labels:</span>
         <span class="hljs-attr">app:</span> <span class="hljs-string">rabbitmq</span>
     <span class="hljs-attr">spec:</span>
       <span class="hljs-attr">containers:</span>
       <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">rabbitmq</span>
         <span class="hljs-attr">image:</span> <span class="hljs-string">bitnami/rabbitmq:latest</span>
         <span class="hljs-attr">ports:</span>
         <span class="hljs-bullet">-</span> <span class="hljs-attr">containerPort:</span> <span class="hljs-number">5672</span>
         <span class="hljs-bullet">-</span> <span class="hljs-attr">containerPort:</span> <span class="hljs-number">15672</span>
         <span class="hljs-attr">env:</span>
         <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">RABBITMQ_ERLANG_COOKIE</span>
           <span class="hljs-attr">value:</span> <span class="hljs-string">"your_erlang_cookie"</span>
         <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">RABBITMQ_DEFAULT_USER</span>
           <span class="hljs-attr">value:</span> <span class="hljs-string">"your_user"</span>
         <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">RABBITMQ_DEFAULT_PASS</span>
           <span class="hljs-attr">value:</span> <span class="hljs-string">"your_password"</span>
         <span class="hljs-attr">volumeMounts:</span>
         <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">config-volume</span>
           <span class="hljs-attr">mountPath:</span> <span class="hljs-string">/opt/bitnami/rabbitmq/conf</span>
           <span class="hljs-attr">subPath:</span> <span class="hljs-string">rabbitmq.conf</span>
       <span class="hljs-attr">volumes:</span>
       <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">config-volume</span>
         <span class="hljs-attr">configMap:</span>
           <span class="hljs-attr">name:</span> <span class="hljs-string">rabbitmq-config</span>
</code></pre>
</li>
<li><p><strong>创建 RabbitMQ 服务 YAML 文件</strong>：</p>
<p> <strong>rabbitmq-service.yaml</strong>：</p>
<pre><code class="lang-yaml"> <span class="hljs-attr">apiVersion:</span> <span class="hljs-string">v1</span>
 <span class="hljs-attr">kind:</span> <span class="hljs-string">Service</span>
 <span class="hljs-attr">metadata:</span>
   <span class="hljs-attr">name:</span> <span class="hljs-string">rabbitmq</span>
 <span class="hljs-attr">spec:</span>
   <span class="hljs-attr">ports:</span>
   <span class="hljs-bullet">-</span> <span class="hljs-attr">port:</span> <span class="hljs-number">5672</span>
     <span class="hljs-attr">name:</span> <span class="hljs-string">amqp</span>
   <span class="hljs-bullet">-</span> <span class="hljs-attr">port:</span> <span class="hljs-number">15672</span>
     <span class="hljs-attr">name:</span> <span class="hljs-string">management</span>
   <span class="hljs-attr">selector:</span>
     <span class="hljs-attr">app:</span> <span class="hljs-string">rabbitmq</span>
</code></pre>
</li>
<li><p><strong>应用 YAML 文件</strong>：</p>
<pre><code class="lang-bash"> kubectl apply -f rabbitmq-configmap.yaml
 kubectl apply -f rabbitmq-deployment.yaml
 kubectl apply -f rabbitmq-service.yaml
</code></pre>
</li>
</ol>
<h3 id="heading-apache-kafka">部署 Apache Kafka 集群</h3>
<p>Apache Kafka 是一个分布式流平台，适用于大规模消息传递和流数据处理。</p>
<h4 id="heading-helm-apache-kafka">使用 Helm 部署 Apache Kafka</h4>
<ol>
<li><p><strong>添加 Bitnami Helm 仓库</strong>：</p>
<pre><code class="lang-bash"> helm repo add bitnami https://charts.bitnami.com/bitnami
 helm repo update
</code></pre>
</li>
<li><p><strong>安装 Apache Kafka 集群</strong>：</p>
<pre><code class="lang-bash"> helm install kafka bitnami/kafka \
   --<span class="hljs-built_in">set</span> replicaCount=3 \
   --<span class="hljs-built_in">set</span> zookeeper.enabled=<span class="hljs-literal">true</span> \
   --<span class="hljs-built_in">set</span> zookeeper.replicaCount=3
</code></pre>
<ul>
<li><p><code>replicaCount=3</code> 表示部署一个包含 3 个 Kafka 节点的集群。</p>
</li>
<li><p><code>zookeeper.replicaCount=3</code> 表示部署一个包含 3 个 Zookeeper 节点的集群。</p>
</li>
</ul>
</li>
</ol>
<h4 id="heading-yaml-apache-kafka">使用 YAML 文件部署 Apache Kafka</h4>
<ol>
<li><p><strong>创建 Zookeeper 部署 YAML 文件</strong>：</p>
<p> <strong>zookeeper-deployment.yaml</strong>：</p>
<pre><code class="lang-yaml"> <span class="hljs-attr">apiVersion:</span> <span class="hljs-string">apps/v1</span>
 <span class="hljs-attr">kind:</span> <span class="hljs-string">Deployment</span>
 <span class="hljs-attr">metadata:</span>
   <span class="hljs-attr">name:</span> <span class="hljs-string">zookeeper</span>
 <span class="hljs-attr">spec:</span>
   <span class="hljs-attr">replicas:</span> <span class="hljs-number">3</span>
   <span class="hljs-attr">selector:</span>
     <span class="hljs-attr">matchLabels:</span>
       <span class="hljs-attr">app:</span> <span class="hljs-string">zookeeper</span>
   <span class="hljs-attr">template:</span>
     <span class="hljs-attr">metadata:</span>
       <span class="hljs-attr">labels:</span>
         <span class="hljs-attr">app:</span> <span class="hljs-string">zookeeper</span>
     <span class="hljs-attr">spec:</span>
       <span class="hljs-attr">containers:</span>
       <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">zookeeper</span>
         <span class="hljs-attr">image:</span> <span class="hljs-string">bitnami/zookeeper:latest</span>
         <span class="hljs-attr">ports:</span>
         <span class="hljs-bullet">-</span> <span class="hljs-attr">containerPort:</span> <span class="hljs-number">2181</span>
</code></pre>
</li>
<li><p><strong>创建 Kafka 部署 YAML 文件</strong>：</p>
<p> <strong>kafka-deployment.yaml</strong>：</p>
<pre><code class="lang-yaml"> <span class="hljs-attr">apiVersion:</span> <span class="hljs-string">apps/v1</span>
 <span class="hljs-attr">kind:</span> <span class="hljs-string">Deployment</span>
 <span class="hljs-attr">metadata:</span>
   <span class="hljs-attr">name:</span> <span class="hljs-string">kafka</span>
 <span class="hljs-attr">spec:</span>
   <span class="hljs-attr">replicas:</span> <span class="hljs-number">3</span>
   <span class="hljs-attr">selector:</span>
     <span class="hljs-attr">matchLabels:</span>
       <span class="hljs-attr">app:</span> <span class="hljs-string">kafka</span>
   <span class="hljs-attr">template:</span>
     <span class="hljs-attr">metadata:</span>
       <span class="hljs-attr">labels:</span>
         <span class="hljs-attr">app:</span> <span class="hljs-string">kafka</span>
     <span class="hljs-attr">spec:</span>
       <span class="hljs-attr">containers:</span>
       <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">kafka</span>
         <span class="hljs-attr">image:</span> <span class="hljs-string">bitnami/kafka:latest</span>
         <span class="hljs-attr">ports:</span>
         <span class="hljs-bullet">-</span> <span class="hljs-attr">containerPort:</span> <span class="hljs-number">9092</span>
         <span class="hljs-attr">env:</span>
         <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">KAFKA_ZOOKEEPER_CONNECT</span>
           <span class="hljs-attr">value:</span> <span class="hljs-string">"zookeeper:2181"</span>
</code></pre>
</li>
<li><p><strong>创建 Kafka 服务 YAML 文件</strong>：</p>
<p> <strong>kafka-service.yaml</strong>：</p>
<pre><code class="lang-yaml"> <span class="hljs-attr">apiVersion:</span> <span class="hljs-string">v1</span>
 <span class="hljs-attr">kind:</span> <span class="hljs-string">Service</span>
 <span class="hljs-attr">metadata:</span>
   <span class="hljs-attr">name:</span> <span class="hljs-string">kafka</span>
 <span class="hljs-attr">spec:</span>
   <span class="hljs-attr">ports:</span>
   <span class="hljs-bullet">-</span> <span class="hljs-attr">port:</span> <span class="hljs-number">9092</span>
     <span class="hljs-attr">name:</span> <span class="hljs-string">kafka</span>
   <span class="hljs-attr">selector:</span>
     <span class="hljs-attr">app:</span> <span class="hljs-string">kafka</span>
</code></pre>
</li>
<li><p><strong>应用 YAML 文件</strong>：</p>
<pre><code class="lang-bash"> kubectl apply -f zookeeper-deployment.yaml
 kubectl apply -f kafka-deployment.yaml
 kubectl apply -f kafka-service.yaml
</code></pre>
</li>
</ol>
<h3 id="heading-57u05oqk5zkm55ur5o6n">维护和监控</h3>
<ul>
<li><p><strong>监控 MQ 实例</strong>：使用监控工具（如 Prometheus + Grafana）来监控消息队列的健康状态和性能。</p>
</li>
<li><p><strong>备份数据</strong>：配置数据备份和恢复策略，确保数据安全。</p>
</li>
<li><p><strong>故障排除</strong>：检查日志文件，确保消息队列正常运行并解决任何问题。</p>
</li>
</ul>
<p>通过这些步骤，你可以在 Kubernetes 集群中部署一个支持高可用性的 RabbitMQ 或 Apache Kafka 集群。根据需要选择适合你的消息队列系统。</p>
<h1 id="heading-codis">七、部署codis集群</h1>
<p>Codis 是一个高可用的 Redis 集群解决方案，支持分片和高可用性。如果你想在 Kubernetes 集群上部署 Codis，以下是一个基本的指南。这个指南涵盖了 Codis 的主要组件，包括 Codis Proxy、Codis Dashboard 和 Codis Server。</p>
<h3 id="heading-1-4">1. 准备工作</h3>
<p>确保 Kubernetes 集群已经正常运行，并且 <code>kubectl</code> 已配置为与集群通信。</p>
<h3 id="heading-2-codis-serverredis">2. 部署 Codis Server（Redis 实例）</h3>
<p>Codis Server 是实际的数据存储部分，通常运行多个 Redis 实例来实现分片。</p>
<ol>
<li><p><strong>创建 Codis Server 部署 YAML 文件</strong>：</p>
<p> <strong>codis-server-deployment.yaml</strong>：</p>
<pre><code class="lang-yaml"> <span class="hljs-attr">apiVersion:</span> <span class="hljs-string">apps/v1</span>
 <span class="hljs-attr">kind:</span> <span class="hljs-string">Deployment</span>
 <span class="hljs-attr">metadata:</span>
   <span class="hljs-attr">name:</span> <span class="hljs-string">codis-server</span>
 <span class="hljs-attr">spec:</span>
   <span class="hljs-attr">replicas:</span> <span class="hljs-number">3</span>
   <span class="hljs-attr">selector:</span>
     <span class="hljs-attr">matchLabels:</span>
       <span class="hljs-attr">app:</span> <span class="hljs-string">codis-server</span>
   <span class="hljs-attr">template:</span>
     <span class="hljs-attr">metadata:</span>
       <span class="hljs-attr">labels:</span>
         <span class="hljs-attr">app:</span> <span class="hljs-string">codis-server</span>
     <span class="hljs-attr">spec:</span>
       <span class="hljs-attr">containers:</span>
       <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">redis</span>
         <span class="hljs-attr">image:</span> <span class="hljs-string">redis:latest</span>
         <span class="hljs-attr">ports:</span>
         <span class="hljs-bullet">-</span> <span class="hljs-attr">containerPort:</span> <span class="hljs-number">6379</span>
</code></pre>
</li>
<li><p><strong>创建 Codis Server 服务 YAML 文件</strong>：</p>
<p> <strong>codis-server-service.yaml</strong>：</p>
<pre><code class="lang-yaml"> <span class="hljs-attr">apiVersion:</span> <span class="hljs-string">v1</span>
 <span class="hljs-attr">kind:</span> <span class="hljs-string">Service</span>
 <span class="hljs-attr">metadata:</span>
   <span class="hljs-attr">name:</span> <span class="hljs-string">codis-server</span>
 <span class="hljs-attr">spec:</span>
   <span class="hljs-attr">ports:</span>
   <span class="hljs-bullet">-</span> <span class="hljs-attr">port:</span> <span class="hljs-number">6379</span>
     <span class="hljs-attr">targetPort:</span> <span class="hljs-number">6379</span>
   <span class="hljs-attr">selector:</span>
     <span class="hljs-attr">app:</span> <span class="hljs-string">codis-server</span>
</code></pre>
</li>
<li><p><strong>应用 YAML 文件</strong>：</p>
<pre><code class="lang-bash"> kubectl apply -f codis-server-deployment.yaml
 kubectl apply -f codis-server-service.yaml
</code></pre>
</li>
</ol>
<h3 id="heading-3-codis-proxy">3. 部署 Codis Proxy</h3>
<p>Codis Proxy 充当客户端与 Codis Server 之间的中间层，实现负载均衡和请求路由。</p>
<ol>
<li><p><strong>创建 Codis Proxy 部署 YAML 文件</strong>：</p>
<p> <strong>codis-proxy-deployment.yaml</strong>：</p>
<pre><code class="lang-yaml"> <span class="hljs-attr">apiVersion:</span> <span class="hljs-string">apps/v1</span>
 <span class="hljs-attr">kind:</span> <span class="hljs-string">Deployment</span>
 <span class="hljs-attr">metadata:</span>
   <span class="hljs-attr">name:</span> <span class="hljs-string">codis-proxy</span>
 <span class="hljs-attr">spec:</span>
   <span class="hljs-attr">replicas:</span> <span class="hljs-number">3</span>
   <span class="hljs-attr">selector:</span>
     <span class="hljs-attr">matchLabels:</span>
       <span class="hljs-attr">app:</span> <span class="hljs-string">codis-proxy</span>
   <span class="hljs-attr">template:</span>
     <span class="hljs-attr">metadata:</span>
       <span class="hljs-attr">labels:</span>
         <span class="hljs-attr">app:</span> <span class="hljs-string">codis-proxy</span>
     <span class="hljs-attr">spec:</span>
       <span class="hljs-attr">containers:</span>
       <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">codis-proxy</span>
         <span class="hljs-attr">image:</span> <span class="hljs-string">codis/codis-proxy:latest</span>
         <span class="hljs-attr">ports:</span>
         <span class="hljs-bullet">-</span> <span class="hljs-attr">containerPort:</span> <span class="hljs-number">19000</span>
</code></pre>
</li>
<li><p><strong>创建 Codis Proxy 服务 YAML 文件</strong>：</p>
<p> <strong>codis-proxy-service.yaml</strong>：</p>
<pre><code class="lang-yaml"> <span class="hljs-attr">apiVersion:</span> <span class="hljs-string">v1</span>
 <span class="hljs-attr">kind:</span> <span class="hljs-string">Service</span>
 <span class="hljs-attr">metadata:</span>
   <span class="hljs-attr">name:</span> <span class="hljs-string">codis-proxy</span>
 <span class="hljs-attr">spec:</span>
   <span class="hljs-attr">ports:</span>
   <span class="hljs-bullet">-</span> <span class="hljs-attr">port:</span> <span class="hljs-number">19000</span>
     <span class="hljs-attr">targetPort:</span> <span class="hljs-number">19000</span>
   <span class="hljs-attr">selector:</span>
     <span class="hljs-attr">app:</span> <span class="hljs-string">codis-proxy</span>
</code></pre>
</li>
<li><p><strong>应用 YAML 文件</strong>：</p>
<pre><code class="lang-bash"> kubectl apply -f codis-proxy-deployment.yaml
 kubectl apply -f codis-proxy-service.yaml
</code></pre>
</li>
</ol>
<h3 id="heading-4-codis-dashboard">4. 部署 Codis Dashboard</h3>
<p>Codis Dashboard 是 Codis 集群的管理界面，用于监控和管理 Codis 集群。</p>
<ol>
<li><p><strong>创建 Codis Dashboard 部署 YAML 文件</strong>：</p>
<p> <strong>codis-dashboard-deployment.yaml</strong>：</p>
<pre><code class="lang-yaml"> <span class="hljs-attr">apiVersion:</span> <span class="hljs-string">apps/v1</span>
 <span class="hljs-attr">kind:</span> <span class="hljs-string">Deployment</span>
 <span class="hljs-attr">metadata:</span>
   <span class="hljs-attr">name:</span> <span class="hljs-string">codis-dashboard</span>
 <span class="hljs-attr">spec:</span>
   <span class="hljs-attr">replicas:</span> <span class="hljs-number">1</span>
   <span class="hljs-attr">selector:</span>
     <span class="hljs-attr">matchLabels:</span>
       <span class="hljs-attr">app:</span> <span class="hljs-string">codis-dashboard</span>
   <span class="hljs-attr">template:</span>
     <span class="hljs-attr">metadata:</span>
       <span class="hljs-attr">labels:</span>
         <span class="hljs-attr">app:</span> <span class="hljs-string">codis-dashboard</span>
     <span class="hljs-attr">spec:</span>
       <span class="hljs-attr">containers:</span>
       <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">codis-dashboard</span>
         <span class="hljs-attr">image:</span> <span class="hljs-string">codis/codis-dashboard:latest</span>
         <span class="hljs-attr">ports:</span>
         <span class="hljs-bullet">-</span> <span class="hljs-attr">containerPort:</span> <span class="hljs-number">18080</span>
</code></pre>
</li>
<li><p><strong>创建 Codis Dashboard 服务 YAML 文件</strong>：</p>
<p> <strong>codis-dashboard-service.yaml</strong>：</p>
<pre><code class="lang-yaml"> <span class="hljs-attr">apiVersion:</span> <span class="hljs-string">v1</span>
 <span class="hljs-attr">kind:</span> <span class="hljs-string">Service</span>
 <span class="hljs-attr">metadata:</span>
   <span class="hljs-attr">name:</span> <span class="hljs-string">codis-dashboard</span>
 <span class="hljs-attr">spec:</span>
   <span class="hljs-attr">ports:</span>
   <span class="hljs-bullet">-</span> <span class="hljs-attr">port:</span> <span class="hljs-number">18080</span>
     <span class="hljs-attr">targetPort:</span> <span class="hljs-number">18080</span>
   <span class="hljs-attr">selector:</span>
     <span class="hljs-attr">app:</span> <span class="hljs-string">codis-dashboard</span>
</code></pre>
</li>
<li><p><strong>应用 YAML 文件</strong>：</p>
<pre><code class="lang-bash"> kubectl apply -f codis-dashboard-deployment.yaml
 kubectl apply -f codis-dashboard-service.yaml
</code></pre>
</li>
</ol>
<h3 id="heading-5-codis">5. 配置和初始化 Codis</h3>
<ol>
<li><p><strong>访问 Codis Dashboard</strong>：通过浏览器访问 Codis Dashboard 的外部 IP 地址（通常是端口 <code>18080</code>）。</p>
</li>
<li><p><strong>配置 Codis 集群</strong>：</p>
<ul>
<li><p>在 Codis Dashboard 中，配置 Redis 实例和 Codis Proxy 的连接。</p>
</li>
<li><p>配置分片和负载均衡策略。</p>
</li>
</ul>
</li>
<li><p><strong>监控和管理</strong>：</p>
<ul>
<li><p>使用 Codis Dashboard 监控 Redis 实例的健康状态。</p>
</li>
<li><p>配置报警和性能监控。</p>
</li>
</ul>
</li>
</ol>
<h3 id="heading-6-1">6. 维护和监控</h3>
<ul>
<li><p><strong>监控 Codis 集群</strong>：使用监控工具（如 Prometheus + Grafana）来监控 Codis 的健康状态和性能。</p>
</li>
<li><p><strong>备份数据</strong>：配置备份和恢复策略，确保数据安全。</p>
</li>
<li><p><strong>故障排除</strong>：检查日志文件，确保 Codis 集群正常运行并解决任何问题。</p>
</li>
</ul>
<p>通过这些步骤，你可以在 Kubernetes 集群中部署 Codis 集群，实现高可用的 Redis 服务。</p>
<h1 id="heading-cicd">八、部署CI/CD系统</h1>
<p>在 Kubernetes 上部署 CI/CD 系统可以帮助自动化构建、测试和部署流程。以下是常见的 CI/CD 系统的部署步骤示例，包括 <strong>Jenkins X</strong> 和 <strong>Argo CD</strong>，两个流行的 Kubernetes 原生 CI/CD 工具。</p>
<h3 id="heading-1-jenkins-x">1. Jenkins X</h3>
<p><strong>Jenkins X</strong> 是一个基于 Kubernetes 的 CI/CD 系统，提供 GitOps 工作流和自动化功能。</p>
<h4 id="heading-jenkins-x">部署 Jenkins X</h4>
<ol>
<li><p><strong>安装 Jenkins X CLI</strong>：</p>
<pre><code class="lang-bash"> curl -L https://github.com/jenkins-x/jx/releases/download/v3.2.279/jx-linux-amd64.tar.gz | tar xzv
 sudo mv jx /usr/<span class="hljs-built_in">local</span>/bin
</code></pre>
</li>
<li><p><strong>创建 Kubernetes 集群</strong>（如果尚未创建）：</p>
<p> 你可以使用任何云提供商或本地工具创建 Kubernetes 集群。</p>
</li>
<li><p><strong>初始化 Jenkins X</strong>：</p>
<pre><code class="lang-bash"> jx create cluster &lt;provider&gt;  <span class="hljs-comment"># 例如: jx create cluster gke</span>
</code></pre>
</li>
<li><p><strong>安装 Jenkins X</strong>：</p>
<pre><code class="lang-bash"> jx install
</code></pre>
</li>
<li><p><strong>配置 Jenkins X</strong>：</p>
<ul>
<li><p>选择要使用的 Git 服务（如 GitHub、GitLab）。</p>
</li>
<li><p>配置用于构建和部署的环境。</p>
</li>
</ul>
</li>
<li><p><strong>访问 Jenkins X</strong>：</p>
<p> Jenkins X 会自动设置好服务，通常可以通过集群的外部 IP 或端口访问。</p>
</li>
</ol>
<h3 id="heading-2-argo-cd">2. Argo CD</h3>
<p><strong>Argo CD</strong> 是一个 Kubernetes 原生的持续交付工具，支持 GitOps 模式。</p>
<h4 id="heading-argo-cd">部署 Argo CD</h4>
<ol>
<li><p><strong>创建 Kubernetes 集群</strong>（如果尚未创建）。</p>
</li>
<li><p><strong>安装 Argo CD</strong>：</p>
<pre><code class="lang-bash"> kubectl create namespace argocd
 kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
</code></pre>
</li>
<li><p><strong>访问 Argo CD</strong>：</p>
<p> 通过 <code>kubectl port-forward</code> 将 Argo CD 的 API 服务器暴露到本地：</p>
<pre><code class="lang-bash"> kubectl port-forward svc/argocd-server -n argocd 8080:443
</code></pre>
<p> 然后在浏览器中访问 <a target="_blank" href="http://localhost:8080%E3%80%82"><code>http://localhost:8080</code>。</a></p>
</li>
<li><p><strong>登录 Argo CD</strong>：</p>
<p> 获取初始管理员密码：</p>
<pre><code class="lang-bash"> kubectl get secret argocd-initial-admin-secret -n argocd -o yaml
</code></pre>
<p> 登录到 Argo CD Web 界面，使用用户名 <code>admin</code> 和获取的密码。</p>
</li>
<li><p><strong>配置 GitOps</strong>：</p>
<ul>
<li><p>在 Argo CD 中创建应用，指定 Git 仓库和部署路径。</p>
</li>
<li><p>Argo CD 将自动同步应用的状态与 Git 仓库中的配置。</p>
</li>
</ul>
</li>
</ol>
<h3 id="heading-3-cicd">3. 其他 CI/CD 工具</h3>
<p>如果你需要其他 CI/CD 工具，以下是一些常见的选择：</p>
<ul>
<li><p><strong>GitLab CI/CD</strong>：</p>
<ul>
<li><p>GitLab 提供内置的 CI/CD 功能，支持 Kubernetes 集群部署。</p>
</li>
<li><p><a target="_blank" href="https://docs.gitlab.com/ee/ci/">官方文档</a></p>
</li>
</ul>
</li>
<li><p><strong>Tekton</strong>：</p>
<ul>
<li><p>一个 Kubernetes 原生的 CI/CD 系统，支持管道和任务。</p>
</li>
<li><p><a target="_blank" href="https://tekton.dev/docs/">官方文档</a></p>
</li>
</ul>
</li>
<li><p><strong>Jenkins</strong>：</p>
<ul>
<li><p>传统的 CI/CD 工具，可通过 Kubernetes 部署 Jenkins Master 和 Agent。</p>
</li>
<li><p><a target="_blank" href="https://www.jenkins.io/doc/book/kubernetes/">官方文档</a></p>
</li>
</ul>
</li>
</ul>
<p>这些 CI/CD 工具可以帮助你在 Kubernetes 集群上实现自动化构建、测试和部署，选择适合你需求的工具来提升开发和运维效率。</p>
<h1 id="heading-6zme5b2v">附录</h1>
<h2 id="heading-k8s">k8s前端界面使用指南</h2>
<p>在 Kubernetes 中，前端界面通常指的是可视化工具和管理控制台，它们用于简化集群的管理和监控。以下是常见的 Kubernetes 前端界面的简要概述：</p>
<h3 id="heading-1-kubernetes-dashboard">1. <strong>Kubernetes Dashboard</strong></h3>
<ul>
<li><p><strong>功能</strong>：Kubernetes 官方提供的图形用户界面，用于监控和管理集群资源。</p>
</li>
<li><p><strong>特点</strong>：</p>
<ul>
<li><p>查看集群状态、Pod、服务、部署等。</p>
</li>
<li><p>提供集群资源的详细信息和管理功能。</p>
</li>
</ul>
</li>
<li><p><strong>安装</strong>：</p>
<pre><code class="lang-bash">  kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.5.0/aio/deploy/recommended.yaml
</code></pre>
</li>
<li><p><strong>访问</strong>：</p>
<pre><code class="lang-bash">  kubectl proxy
  <span class="hljs-comment"># 通过浏览器访问</span>
  http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/
</code></pre>
</li>
</ul>
<h3 id="heading-2-lens">2. <strong>Lens</strong></h3>
<ul>
<li><p><strong>功能</strong>：开源的 Kubernetes IDE，提供集群管理和监控功能。</p>
</li>
<li><p><strong>特点</strong>：</p>
<ul>
<li><p>支持多集群管理。</p>
</li>
<li><p>可视化的资源浏览器和日志查看。</p>
</li>
<li><p>插件支持扩展功能。</p>
</li>
</ul>
</li>
<li><p><strong>安装</strong>：从 <a target="_blank" href="https://k8slens.dev/">Lens 官网</a> 下载并安装客户端应用。</p>
</li>
</ul>
<h3 id="heading-3-octant">3. <strong>Octant</strong></h3>
<ul>
<li><p><strong>功能</strong>：开源的 Kubernetes 管理界面，由 VMware 开发。</p>
</li>
<li><p><strong>特点</strong>：</p>
<ul>
<li><p>实时监控 Kubernetes 集群状态。</p>
</li>
<li><p>提供丰富的资源视图和交互功能。</p>
</li>
</ul>
</li>
<li><p><strong>安装</strong>：</p>
<pre><code class="lang-bash">  brew install octant
</code></pre>
</li>
<li><p><strong>启动</strong>：</p>
<pre><code class="lang-bash">  octant
  <span class="hljs-comment"># 通过浏览器访问 http://localhost:7777</span>
</code></pre>
</li>
</ul>
<h3 id="heading-4-rancher">4. <strong>Rancher</strong></h3>
<ul>
<li><p><strong>功能</strong>：全面的 Kubernetes 管理平台，适用于多集群管理。</p>
</li>
<li><p><strong>特点</strong>：</p>
<ul>
<li><p>支持集群的创建和管理。</p>
</li>
<li><p>提供强大的用户权限管理和多集群操作功能。</p>
</li>
</ul>
</li>
<li><p><strong>安装</strong>：</p>
<pre><code class="lang-bash">  docker run -d --restart=unless-stopped -p 80:80 -p 443:443 rancher/rancher:latest
</code></pre>
</li>
<li><p><strong>访问</strong>：通过浏览器访问 <code>https://&lt;your-rancher-ip&gt;</code>。</p>
</li>
</ul>
<h3 id="heading-5-portainer">5. <strong>Portainer</strong></h3>
<ul>
<li><p><strong>功能</strong>：用户友好的容器管理工具，也支持 Kubernetes。</p>
</li>
<li><p><strong>特点</strong>：</p>
<ul>
<li><p>提供简洁的用户界面来管理 Kubernetes 集群。</p>
</li>
<li><p>支持容器和镜像的可视化管理。</p>
</li>
</ul>
</li>
<li><p><strong>安装</strong>：</p>
<pre><code class="lang-bash">  docker run -d -p 9000:9000 --name portainer --restart=always portainer/portainer-ce
</code></pre>
</li>
<li><p><strong>访问</strong>：通过浏览器访问 <a target="_blank" href="http://localhost:9000%E3%80%82"><code>http://localhost:9000</code>。</a></p>
</li>
</ul>
<p>这些前端界面可以帮助你更高效地管理和监控 Kubernetes 集群，选择合适的工具取决于你的需求和使用场景。</p>
<h2 id="heading-5yv6keg5yyw5zkm566h55cg5pyn5yqh5l6d6lww5ywz57o7">可视化和管理服务依赖关系</h2>
<p>在 Kubernetes 上搭建一个开源服务树管理应用通常涉及使用合适的开源工具来可视化和管理服务依赖关系。以下是一个示例，展示如何使用 <strong>Kiali</strong> 作为开源服务树管理应用来实现这一目标。Kiali 是一个用于可视化和管理服务网格的工具，特别适用于 Istio 服务网格。</p>
<h3 id="heading-1-5">1. 准备工作</h3>
<p>确保你有一个运行中的 Kubernetes 集群和已安装的 <strong>Istio</strong> 服务网格，因为 Kiali 通常与 Istio 配合使用。</p>
<h3 id="heading-2-istio">2. 安装 Istio</h3>
<ol>
<li><p><strong>下载 Istio 安装程序</strong>：</p>
<pre><code class="lang-bash"> curl -L https://istio.io/downloadIstio | sh -
</code></pre>
</li>
<li><p><strong>安装 Istio CLI</strong>：</p>
<pre><code class="lang-bash"> <span class="hljs-built_in">export</span> PATH=<span class="hljs-variable">$PATH</span>:`<span class="hljs-built_in">pwd</span>`/istio-&lt;version&gt;/bin
</code></pre>
</li>
<li><p><strong>安装 Istio 默认配置</strong>：</p>
<pre><code class="lang-bash"> istioctl install --<span class="hljs-built_in">set</span> profile=demo
</code></pre>
</li>
<li><p><strong>启用自动注入 sidecar</strong>：</p>
<pre><code class="lang-bash"> kubectl label namespace default istio-injection=enabled
</code></pre>
</li>
<li><p><strong>部署示例应用</strong>（可选，但推荐用于测试）：</p>
<pre><code class="lang-bash"> kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.14/samples/bookinfo/platform/kube/bookinfo.yaml
</code></pre>
</li>
</ol>
<h3 id="heading-3-kiali">3. 安装 Kiali</h3>
<ol>
<li><p><strong>安装 Kiali</strong>：</p>
<p> 如果你使用的是 Istio 的 Helm Chart，你可以通过以下命令安装 Kiali：</p>
<pre><code class="lang-bash"> helm install kiali-server kiali/kiali-server --namespace istio-system
</code></pre>
<p> 或者通过 Istio 的 <code>istioctl</code> 工具：</p>
<pre><code class="lang-bash"> istioctl manifest apply --<span class="hljs-built_in">set</span> values.kiali.enabled=<span class="hljs-literal">true</span>
</code></pre>
</li>
<li><p><strong>验证 Kiali 部署</strong>：</p>
<pre><code class="lang-bash"> kubectl get pods -n istio-system
</code></pre>
<p> 确保 <code>kiali</code> Pod 正在运行。</p>
</li>
<li><p><strong>获取 Kiali 的访问地址</strong>：</p>
<pre><code class="lang-bash"> kubectl get svc -n istio-system
</code></pre>
<p> 记录下 <code>kiali</code> 服务的 <code>EXTERNAL-IP</code> 或使用 <code>kubectl port-forward</code> 来访问：</p>
<pre><code class="lang-bash"> kubectl port-forward svc/kiali -n istio-system 20001:20001
</code></pre>
</li>
<li><p><strong>访问 Kiali</strong>：</p>
<p> 通过浏览器访问 <a target="_blank" href="http://localhost:20001%EF%BC%8C%E4%BD%A0%E5%B0%86%E7%9C%8B%E5%88%B0"><code>http://localhost:20001</code>，你将看到</a> Kiali 的用户界面。</p>
</li>
</ol>
<h3 id="heading-4-kiali">4. 配置和使用 Kiali</h3>
<ol>
<li><p><strong>配置服务树视图</strong>：</p>
<ul>
<li><p>在 Kiali 的用户界面中，你可以查看到服务网格的拓扑图。</p>
</li>
<li><p>Kiali 会自动从 Istio 收集服务的流量数据并绘制服务依赖图（服务树）。</p>
</li>
</ul>
</li>
<li><p><strong>监控和分析</strong>：</p>
<ul>
<li>使用 Kiali 的功能来监控流量、查看服务间的调用关系、分析请求的延迟和错误等。</li>
</ul>
</li>
<li><p><strong>安全和访问控制</strong>：</p>
<ul>
<li>配置用户权限和访问控制，以保护你的 Kiali 界面。</li>
</ul>
</li>
</ol>
<h3 id="heading-5-4">5. 维护和监控</h3>
<ul>
<li><p><strong>更新</strong>：定期更新 Kiali 和 Istio 以获取新功能和安全修复。</p>
</li>
<li><p><strong>备份</strong>：根据需要配置备份策略，确保数据的持久性。</p>
</li>
<li><p><strong>故障排除</strong>：检查 Kiali 和 Istio 的日志，解决任何出现的问题。</p>
</li>
</ul>
<p>通过这些步骤，你可以在 Kubernetes 上成功搭建一个开源服务树管理应用（如 Kiali），用于可视化和管理你的服务网格。</p>
<h2 id="heading-kubernetes-2">Kubernetes 生态系统</h2>
<p><strong>Kubernetes</strong> 生态系统包括多个组件和工具，协同工作以管理和优化容器化应用程序的部署、运行和维护。</p>
<ul>
<li><p><strong>核心组件</strong>：</p>
<ul>
<li><p><strong>Kubernetes API Server</strong>：集群的中心控制点，处理所有 API 请求。</p>
</li>
<li><p><strong>Scheduler</strong>：分配 Pod 到合适的节点。</p>
</li>
<li><p><strong>Controller Manager</strong>：管理集群的状态，确保实际状态符合期望状态。</p>
</li>
<li><p><strong>Kubelet</strong>：在每个节点上运行，管理 Pod 的生命周期。</p>
</li>
<li><p><strong>Kube Proxy</strong>：提供网络代理服务，处理服务的负载均衡。</p>
</li>
<li><p><strong>etcd</strong>：分布式键值存储，用于存储集群的配置和状态数据。</p>
</li>
</ul>
</li>
<li><p><strong>常用工具</strong>：</p>
<ul>
<li><p><strong>kubectl</strong>：命令行工具，用于与 Kubernetes 集群交互。</p>
</li>
<li><p><strong>Helm</strong>：包管理工具，用于简化应用程序的部署和管理。</p>
</li>
<li><p><strong>kubeadm</strong>：用于集群的初始化和管理。</p>
</li>
</ul>
</li>
<li><p><strong>监控和日志</strong>：</p>
<ul>
<li><p><strong>Prometheus</strong>：开源监控系统，集成 Grafana 进行可视化。</p>
</li>
<li><p><strong>ELK Stack</strong>（Elasticsearch, Logstash, Kibana）：用于日志收集、分析和可视化。</p>
</li>
</ul>
</li>
<li><p><strong>服务网格</strong>：</p>
<ul>
<li><p><strong>Istio</strong>：服务网格平台，提供流量管理、服务治理和安全功能。</p>
</li>
<li><p><strong>Linkerd</strong>：另一个流行的轻量级服务网格。</p>
</li>
</ul>
</li>
<li><p><strong>CI/CD</strong>：</p>
<ul>
<li><p><strong>Argo CD</strong>：持续交付工具，支持 GitOps 模式。</p>
</li>
<li><p><strong>Jenkins X</strong>：自动化 CI/CD 平台，集成 Kubernetes 和 GitOps。</p>
</li>
</ul>
</li>
<li><p><strong>存储和网络</strong>：</p>
<ul>
<li><p><strong>StorageClass</strong>：定义不同类型的存储，支持动态卷供应。</p>
</li>
<li><p><strong>Calico</strong>、<strong>Weave</strong>：网络插件，提供网络策略和多租户支持。</p>
</li>
</ul>
</li>
<li><p><strong>开发和调试</strong>：</p>
<ul>
<li><p><strong>Kubernetes Dashboard</strong>：集群的图形用户界面，用于管理和监控集群资源。</p>
</li>
<li><p><strong>Skaffold</strong>：开发工具，简化应用程序的构建、部署和迭代。</p>
</li>
</ul>
</li>
</ul>
<p>Kubernetes 生态系统提供了一整套工具和组件，帮助用户管理复杂的容器化应用程序和微服务架构。</p>
<h2 id="heading-istio">Istio</h2>
<p><strong>Istio</strong> 是一个开源的服务网格平台，提供了流量管理、服务治理、安全和可观察性功能，帮助管理和保护微服务架构中的应用。</p>
<ul>
<li><p><strong>主要功能</strong>：</p>
<ul>
<li><p><strong>流量管理</strong>：控制和分配服务间的流量，支持流量镜像、蓝绿部署等。</p>
</li>
<li><p><strong>安全</strong>：提供服务间的身份验证、授权和加密通信。</p>
</li>
<li><p><strong>可观察性</strong>：监控和跟踪服务的性能，包括日志、指标和分布式追踪。</p>
</li>
<li><p><strong>政策管理</strong>：实施访问控制、流量控制和速率限制等策略。</p>
</li>
</ul>
</li>
<li><p><strong>组件</strong>：</p>
<ul>
<li><p><strong>Envoy</strong>：轻量级代理，注入到服务的 sidecar 中，处理流量和策略。</p>
</li>
<li><p><strong>Pilot</strong>：配置和管理 Envoy 代理。</p>
</li>
<li><p><strong>Mixer</strong>：处理遥测数据和策略检查。</p>
</li>
<li><p><strong>Citadel</strong>：提供服务间的身份验证和密钥管理。</p>
</li>
<li><p><strong>Galley</strong>：配置验证和分发。</p>
</li>
</ul>
</li>
<li><p><strong>安装</strong>：</p>
<ul>
<li>可以通过 <code>istioctl</code>、Helm 或直接应用 Kubernetes YAML 文件来安装。</li>
</ul>
</li>
<li><p><strong>访问</strong>：</p>
<ul>
<li>提供多种控制面板和 CLI 工具来管理和监控服务网格。</li>
</ul>
</li>
</ul>
<p>Istio 是一个强大的服务网格解决方案，适用于需要精细流量控制和综合可观察性的现代应用架构。</p>
]]></content:encoded></item><item><title><![CDATA[搭建可复用的前端开发环境]]></title><description><![CDATA[前言
在现代前端开发中，搭建一个高效且可复用的开发环境至关重要。无论你是初学者还是经验丰富的开发者，一个良好的开发环境不仅能提升工作效率，还能减少调试和配置的时间成本。本篇文章将详细介绍如何从零开始搭建一个全面的前端开发环境，涵盖运行时、包管理工具、镜像源管理、问题排查等多个方面，帮助你在开发过程中游刃有余。让我们一起探索如何打造一个强大且灵活的前端开发环境吧！
关键字

前端开发环境 (Frontend Development Environment)

运行时 (Runtime)

包管理工...]]></description><link>https://blog.wuzhiguo.tech/reusable-frontend-development-environment-setup</link><guid isPermaLink="true">https://blog.wuzhiguo.tech/reusable-frontend-development-environment-setup</guid><category><![CDATA[Frontend Development Environment]]></category><category><![CDATA[Registry Management]]></category><category><![CDATA[前端开发环境]]></category><category><![CDATA[运行时]]></category><category><![CDATA[包管理工具]]></category><category><![CDATA[镜像源管理]]></category><category><![CDATA[package manager]]></category><category><![CDATA[runtime]]></category><category><![CDATA[troubleshooting]]></category><category><![CDATA[问题排查]]></category><dc:creator><![CDATA[wuzhiguocarter]]></dc:creator><pubDate>Wed, 07 Aug 2024 14:40:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/UYsBCu9RP3Y/upload/c3c302faf8ac33e53b5270307feadb76.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-5ymn6kia">前言</h1>
<p>在现代前端开发中，搭建一个高效且可复用的开发环境至关重要。无论你是初学者还是经验丰富的开发者，一个良好的开发环境不仅能提升工作效率，还能减少调试和配置的时间成本。本篇文章将详细介绍如何从零开始搭建一个全面的前端开发环境，涵盖运行时、包管理工具、镜像源管理、问题排查等多个方面，帮助你在开发过程中游刃有余。让我们一起探索如何打造一个强大且灵活的前端开发环境吧！</p>
<p>关键字</p>
<ol>
<li><p>前端开发环境 (Frontend Development Environment)</p>
</li>
<li><p>运行时 (Runtime)</p>
</li>
<li><p>包管理工具 (Package Manager)</p>
</li>
<li><p>镜像源管理 (Registry Management)</p>
</li>
<li><p>问题排查 (Troubleshooting)</p>
</li>
</ol>
<h1 id="heading-5lia44cb6lq6kgm5pe2">一、运行时</h1>
<p><a target="_blank" href="https://nodejs.org/en/download/package-manager">https://nodejs.org/en/download/package-manager</a></p>
<p>使用运行时版本管理工具<code>nvm</code>安装node</p>
<pre><code class="lang-bash"><span class="hljs-comment"># installs nvm (Node Version Manager)</span>
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash

<span class="hljs-comment"># download and install Node.js (you may need to restart the terminal)</span>
nvm install 22

<span class="hljs-comment"># verifies the right Node.js version is in the environment</span>
node -v <span class="hljs-comment"># should print `v22.5.1`</span>

<span class="hljs-comment"># verifies the right npm version is in the environment</span>
npm -v <span class="hljs-comment"># should print `10.8.2`</span>
</code></pre>
<h1 id="heading-5lqm44cb5yyf566h55cg5bel5yw3">二、包管理工具</h1>
<p><code>npm</code> 是 Node.js 的包管理工具，用于安装、共享、发布和管理项目依赖。以下是一些常用的 <code>npm</code> 命令及其功能的简要介绍（tldr）：</p>
<h3 id="heading-5z65pys5zg95luk">基本命令</h3>
<ol>
<li><p><strong>安装依赖包</strong></p>
<ul>
<li><p>本地安装（将包安装到项目的 <code>node_modules</code> 目录）：</p>
<pre><code class="lang-bash">  npm install &lt;package-name&gt;
</code></pre>
<p>  或</p>
<pre><code class="lang-bash">  npm i &lt;package-name&gt;
</code></pre>
</li>
<li><p>全局安装（将包安装到全局环境）：</p>
<pre><code class="lang-bash">  npm install -g &lt;package-name&gt;
</code></pre>
</li>
</ul>
</li>
<li><p><strong>移除依赖包</strong></p>
<ul>
<li><p>本地移除：</p>
<pre><code class="lang-bash">  npm uninstall &lt;package-name&gt;
</code></pre>
</li>
<li><p>全局移除：</p>
<pre><code class="lang-bash">  npm uninstall -g &lt;package-name&gt;
</code></pre>
</li>
</ul>
</li>
<li><p><strong>更新依赖包</strong></p>
<ul>
<li><p>本地更新：</p>
<pre><code class="lang-bash">  npm update &lt;package-name&gt;
</code></pre>
</li>
<li><p>全局更新：</p>
<pre><code class="lang-bash">  npm update -g &lt;package-name&gt;
</code></pre>
</li>
</ul>
</li>
<li><p><strong>查看已安装的包</strong></p>
<ul>
<li><p>本地查看：</p>
<pre><code class="lang-bash">  npm list
</code></pre>
</li>
<li><p>全局查看：</p>
<pre><code class="lang-bash">  npm list -g
</code></pre>
</li>
</ul>
</li>
<li><p><strong>查看依赖包信息</strong></p>
<pre><code class="lang-bash"> npm info &lt;package-name&gt;
</code></pre>
</li>
<li><p><strong>初始化项目</strong></p>
<pre><code class="lang-bash"> npm init
</code></pre>
<p> 或快速初始化：</p>
<pre><code class="lang-bash"> npm init -y
</code></pre>
</li>
</ol>
<h3 id="heading-6auy57qn5zg95luk">高级命令</h3>
<ol>
<li><p><strong>安装指定版本的包</strong></p>
<pre><code class="lang-bash"> npm install &lt;package-name&gt;@&lt;version&gt;
</code></pre>
<p> 例如：</p>
<pre><code class="lang-bash"> npm install lodash@4.17.21
</code></pre>
</li>
<li><p><strong>列出过时的包</strong></p>
<pre><code class="lang-bash"> npm outdated
</code></pre>
</li>
<li><p><strong>修复漏洞</strong></p>
<pre><code class="lang-bash"> npm audit fix
</code></pre>
</li>
<li><p><strong>运行测试</strong></p>
<pre><code class="lang-bash"> npm <span class="hljs-built_in">test</span>
</code></pre>
</li>
<li><p><strong>运行自定义脚本</strong> 在 <code>package.json</code> 中定义脚本后，运行自定义脚本：</p>
<pre><code class="lang-bash"> npm run &lt;script-name&gt;
</code></pre>
<p> 例如，在 <code>package.json</code> 中有如下脚本：</p>
<pre><code class="lang-json"> <span class="hljs-string">"scripts"</span>: {
   <span class="hljs-attr">"start"</span>: <span class="hljs-string">"node app.js"</span>,
   <span class="hljs-attr">"build"</span>: <span class="hljs-string">"webpack --config webpack.config.js"</span>
 }
</code></pre>
<p> 运行脚本：</p>
<pre><code class="lang-bash"> npm run start
 npm run build
</code></pre>
</li>
</ol>
<h3 id="heading-5l6d6lww566h55cg">依赖管理</h3>
<ol>
<li><p><strong>安装并保存为项目依赖</strong></p>
<pre><code class="lang-bash"> npm install &lt;package-name&gt; --save
</code></pre>
<p> 或简写：</p>
<pre><code class="lang-bash"> npm install &lt;package-name&gt; -S
</code></pre>
</li>
<li><p><strong>安装并保存为开发依赖</strong></p>
<pre><code class="lang-bash"> npm install &lt;package-name&gt; --save-dev
</code></pre>
<p> 或简写：</p>
<pre><code class="lang-bash"> npm install &lt;package-name&gt; -D
</code></pre>
</li>
<li><p><strong>安装并保存为可选依赖</strong></p>
<pre><code class="lang-bash"> npm install &lt;package-name&gt; --save-optional
</code></pre>
<p> 或简写：</p>
<pre><code class="lang-bash"> npm install &lt;package-name&gt; -O
</code></pre>
</li>
<li><p><strong>安装并保存为对等依赖</strong></p>
<pre><code class="lang-bash"> npm install &lt;package-name&gt; --save-peer
</code></pre>
</li>
</ol>
<h3 id="heading-5yw25luw5pyj55so5zg95luk">其他有用命令</h3>
<ol>
<li><p><strong>清除缓存</strong></p>
<pre><code class="lang-bash"> npm cache clean --force
</code></pre>
</li>
<li><p><strong>显示帮助信息</strong></p>
<pre><code class="lang-bash"> npm <span class="hljs-built_in">help</span>
</code></pre>
</li>
<li><p><strong>查看npm版本</strong></p>
<pre><code class="lang-bash"> npm -v
</code></pre>
</li>
<li><p><strong>查看node版本</strong></p>
<pre><code class="lang-bash"> node -v
</code></pre>
</li>
</ol>
<p>这些命令涵盖了大多数常见的 <code>npm</code> 使用场景，帮助你有效地管理项目依赖和脚本。</p>
<h1 id="heading-5lij44cb5yyf6zwc5yop5rqq566h55cg5bel5yw3">三、包镜像源管理工具</h1>
<p><code>nrm</code> (npm registry manager) 是一个用于管理和切换 npm 源的工具，它允许你在不同的 npm 镜像源之间快速切换。以下是 <code>nrm</code> 的简要介绍（tldr）及其常用命令：</p>
<h3 id="heading-nrm">安装 nrm</h3>
<p>你可以通过 npm 全局安装 nrm：</p>
<pre><code class="lang-bash">npm install -g nrm
</code></pre>
<h3 id="heading-npm">列出可用的 npm 源</h3>
<pre><code class="lang-bash">nrm ls
</code></pre>
<p>这将显示当前配置的所有 npm 源，并标记当前正在使用的源。</p>
<h3 id="heading-npm-1">切换 npm 源</h3>
<pre><code class="lang-bash">nrm use &lt;registry&gt;
</code></pre>
<p>例如，要切换到淘宝的 npm 源：</p>
<pre><code class="lang-bash">nrm use taobao
</code></pre>
<h3 id="heading-npm-2">测试 npm 源速度</h3>
<pre><code class="lang-bash">nrm <span class="hljs-built_in">test</span>
</code></pre>
<p>这将测试所有配置的 npm 源的响应速度，以帮助你选择最快的源。</p>
<h3 id="heading-npm-3">添加新的 npm 源</h3>
<pre><code class="lang-bash">nrm add &lt;registry&gt; &lt;url&gt;
</code></pre>
<p>例如，添加一个自定义的 npm 源：</p>
<pre><code class="lang-bash">nrm add custom https://custom.registry.com/
</code></pre>
<h3 id="heading-npm-4">删除 npm 源</h3>
<pre><code class="lang-bash">nrm del &lt;registry&gt;
</code></pre>
<p>例如，删除自定义的 npm 源：</p>
<pre><code class="lang-bash">nrm del custom
</code></pre>
<h3 id="heading-npm-5">查看当前使用的 npm 源</h3>
<pre><code class="lang-bash">nrm current
</code></pre>
<h3 id="heading-npm-6">重新设置默认 npm 源</h3>
<p>你可以使用 <code>nrm</code> 切换回官方的 npm 源：</p>
<pre><code class="lang-bash">nrm use npm
</code></pre>
<h3 id="heading-56s65l6l">示例</h3>
<p>假设你想在官方 npm 源和淘宝源之间切换，可以按照以下步骤操作：</p>
<ol>
<li><p>列出所有可用的源：</p>
<pre><code class="lang-bash"> nrm ls
</code></pre>
<p> 输出示例：</p>
<pre><code class="lang-plaintext"> * npm ----- https://registry.npmjs.org/
   yarn ---- https://registry.yarnpkg.com/
   taobao -- https://registry.npm.taobao.org/
   cnpm ---- http://r.cnpmjs.org/
   nj ------ https://registry.nodejitsu.com/
   skimdb -- https://skimdb.npmjs.com/registry
</code></pre>
</li>
<li><p>切换到淘宝源：</p>
<pre><code class="lang-bash"> nrm use taobao
</code></pre>
</li>
<li><p>验证当前使用的源：</p>
<pre><code class="lang-bash"> nrm current
</code></pre>
</li>
<li><p>测试所有源的速度：</p>
<pre><code class="lang-bash"> nrm <span class="hljs-built_in">test</span>
</code></pre>
</li>
</ol>
<p>使用 <code>nrm</code>，你可以方便地在不同的 npm 源之间切换，以找到最快和最稳定的源，提升包安装和更新的速度。</p>
<h1 id="heading-5zub44cb5ymn56uv546v5akd5pct5bu6">四、前端环境搭建</h1>
<p>搭建前端开发环境是一个综合的过程，涉及多个工具和配置。以下是详细的步骤，包括必要的工具和配置：</p>
<h3 id="heading-1-nodejs-npm">1. 安装 Node.js 和 npm</h3>
<p>首先，确保你已经安装了 Node.js 和 npm，这是前端开发的基础。</p>
<pre><code class="lang-bash">node -v
npm -v
</code></pre>
<h3 id="heading-2-nrm-npm">2. 使用 nrm 切换 npm 源</h3>
<p>如果你在中国，可以使用 <code>nrm</code> 切换到淘宝源以加快下载速度。</p>
<pre><code class="lang-bash">nrm use taobao
</code></pre>
<h3 id="heading-3">3. 安装常用的全局工具</h3>
<h4 id="heading-a-npx">a. npx</h4>
<p>npx 已经包含在 npm 中，无需单独安装。它用于运行本地或全局安装的 npm 包。</p>
<h4 id="heading-b-yarn">b. yarn</h4>
<p>Yarn 是另一个包管理工具，提供比 npm 更快和更稳定的体验。</p>
<pre><code class="lang-bash">npm install -g yarn
</code></pre>
<h4 id="heading-c-cli">c. 前端框架CLI 工具</h4>
<p>根据你使用的前端框架，安装相应的 CLI 工具。</p>
<ul>
<li><p>Vue CLI：</p>
<pre><code class="lang-bash">  npm install -g @vue/cli
</code></pre>
</li>
<li><p>Create React App：</p>
<pre><code class="lang-bash">  npm install -g create-react-app
</code></pre>
</li>
<li><p>Angular CLI：</p>
<pre><code class="lang-bash">  npm install -g @angular/cli
</code></pre>
</li>
</ul>
<h3 id="heading-4">4. 配置代码编辑器</h3>
<h4 id="heading-a-vs-code">a. VS Code</h4>
<p>Visual Studio Code 是一个流行的代码编辑器，支持丰富的扩展和配置。</p>
<ol>
<li><p>下载并安装 <a target="_blank" href="https://code.visualstudio.com/">Visual Studio Code</a>.</p>
</li>
<li><p>安装推荐的扩展：</p>
<ul>
<li><p>ESLint</p>
</li>
<li><p>Prettier - Code formatter</p>
</li>
<li><p>Live Server</p>
</li>
<li><p>GitLens</p>
</li>
<li><p>Vetur (for Vue.js)</p>
</li>
<li><p>ESLint Plugin (for React)</p>
</li>
<li><p>Angular Essentials (for Angular)</p>
</li>
</ul>
</li>
</ol>
<h4 id="heading-b-linting">b. 配置代码格式化和 linting</h4>
<ul>
<li><p>创建或更新 <code>.eslintrc</code> 文件以配置 ESLint。</p>
</li>
<li><p>创建或更新 <code>.prettierrc</code> 文件以配置 Prettier。</p>
</li>
<li><p>在 VS Code 的 <code>settings.json</code> 中添加以下配置，以确保每次保存文件时自动格式化：</p>
<pre><code class="lang-json">  {
    <span class="hljs-attr">"editor.formatOnSave"</span>: <span class="hljs-literal">true</span>,
    <span class="hljs-attr">"eslint.autoFixOnSave"</span>: <span class="hljs-literal">true</span>,
    <span class="hljs-attr">"prettier.requireConfig"</span>: <span class="hljs-literal">true</span>,
    <span class="hljs-attr">"prettier.singleQuote"</span>: <span class="hljs-literal">true</span>,
    <span class="hljs-attr">"prettier.trailingComma"</span>: <span class="hljs-string">"es5"</span>
  }
</code></pre>
</li>
</ul>
<h3 id="heading-5">5. 初始化项目</h3>
<p>根据使用的框架初始化项目。</p>
<ul>
<li><p>Vue：</p>
<pre><code class="lang-bash">  vue create my-project
  <span class="hljs-built_in">cd</span> my-project
  npm run serve
</code></pre>
</li>
<li><p>React：</p>
<pre><code class="lang-bash">  create-react-app my-project
  <span class="hljs-built_in">cd</span> my-project
  npm start
</code></pre>
</li>
<li><p>Angular：</p>
<pre><code class="lang-bash">  ng new my-project
  <span class="hljs-built_in">cd</span> my-project
  ng serve
</code></pre>
</li>
</ul>
<h3 id="heading-6">6. 版本控制</h3>
<p>使用 Git 进行版本控制。</p>
<ol>
<li><p>初始化 Git 仓库：</p>
<pre><code class="lang-bash"> git init
</code></pre>
</li>
<li><p>创建 <code>.gitignore</code> 文件，忽略不需要的文件和文件夹。例如：</p>
<pre><code class="lang-plaintext"> node_modules/
 dist/
 .env
</code></pre>
</li>
<li><p>提交初始代码：</p>
<pre><code class="lang-bash"> git add .
 git commit -m <span class="hljs-string">"Initial commit"</span>
</code></pre>
</li>
</ol>
<h3 id="heading-7">7. 安装项目依赖</h3>
<p>在项目根目录下安装所需的依赖：</p>
<pre><code class="lang-bash">npm install
</code></pre>
<p>或者：</p>
<pre><code class="lang-bash">yarn install
</code></pre>
<h3 id="heading-8-webpack">8. 配置 Webpack (可选)</h3>
<p>如果需要自定义打包配置，可以手动配置 Webpack。</p>
<ol>
<li><p>安装 Webpack 和相关依赖：</p>
<pre><code class="lang-bash"> npm install --save-dev webpack webpack-cli webpack-dev-server
</code></pre>
</li>
<li><p>创建 <code>webpack.config.js</code> 文件并添加基本配置：</p>
<pre><code class="lang-javascript"> <span class="hljs-keyword">const</span> path = <span class="hljs-built_in">require</span>(<span class="hljs-string">'path'</span>);

 <span class="hljs-built_in">module</span>.exports = {
   <span class="hljs-attr">entry</span>: <span class="hljs-string">'./src/index.js'</span>,
   <span class="hljs-attr">output</span>: {
     <span class="hljs-attr">filename</span>: <span class="hljs-string">'bundle.js'</span>,
     <span class="hljs-attr">path</span>: path.resolve(__dirname, <span class="hljs-string">'dist'</span>)
   },
   <span class="hljs-attr">module</span>: {
     <span class="hljs-attr">rules</span>: [
       {
         <span class="hljs-attr">test</span>: <span class="hljs-regexp">/\.js$/</span>,
         exclude: <span class="hljs-regexp">/node_modules/</span>,
         use: {
           <span class="hljs-attr">loader</span>: <span class="hljs-string">'babel-loader'</span>
         }
       }
     ]
   },
   <span class="hljs-attr">devServer</span>: {
     <span class="hljs-attr">contentBase</span>: <span class="hljs-string">'./dist'</span>
   }
 };
</code></pre>
</li>
<li><p>配置 <code>package.json</code> 中的脚本：</p>
<pre><code class="lang-json"> <span class="hljs-string">"scripts"</span>: {
   <span class="hljs-attr">"start"</span>: <span class="hljs-string">"webpack-dev-server --open"</span>,
   <span class="hljs-attr">"build"</span>: <span class="hljs-string">"webpack"</span>
 }
</code></pre>
</li>
</ol>
<h3 id="heading-9">9. 环境变量配置</h3>
<p>使用 <code>.env</code> 文件配置环境变量，确保在不同环境中使用不同配置。</p>
<ol>
<li><p>创建 <code>.env</code> 文件：</p>
<pre><code class="lang-plaintext"> REACT_APP_API_URL=https://api.example.com
</code></pre>
</li>
<li><p>在代码中使用环境变量：</p>
<pre><code class="lang-javascript"> <span class="hljs-keyword">const</span> apiUrl = process.env.REACT_APP_API_URL;
</code></pre>
</li>
</ol>
<h3 id="heading-10">10. 其他工具和配置</h3>
<ul>
<li><p><strong>测试工具</strong>：如 Jest、Mocha、Chai 等，根据项目需求安装和配置。</p>
</li>
<li><p><strong>样式工具</strong>：如 SASS、LESS、Styled-components，根据项目需求安装和配置。</p>
</li>
<li><p><strong>状态管理工具</strong>：如 Redux、Vuex，根据项目需求安装和配置。</p>
</li>
</ul>
<p>通过以上步骤，你可以搭建一个完整的前端开发环境，涵盖从基本工具到高级配置的各个方面，确保高效和高质量的开发体验。</p>
<h1 id="heading-trouble-shooting">五、环境问题trouble-shooting</h1>
<p>在搭建前端开发环境时，可能会遇到各种问题。以下是一些常见问题的简要介绍（tldr）及其解决方法：</p>
<h3 id="heading-1-nodejs-npm-1">1. Node.js 和 npm 版本问题</h3>
<p><strong>问题</strong>：安装包时出现错误，提示 Node.js 或 npm 版本不兼容。</p>
<p><strong>解决方法</strong>：</p>
<ul>
<li><p>使用 <code>nvm</code>（Node Version Manager）管理和切换 Node.js 版本：</p>
<pre><code class="lang-bash">  nvm install &lt;version&gt;
  nvm use &lt;version&gt;
</code></pre>
</li>
<li><p>确认你安装的是最新版本的 npm：</p>
<pre><code class="lang-bash">  npm install -g npm@latest
</code></pre>
</li>
</ul>
<h3 id="heading-2">2. 网络连接问题</h3>
<p><strong>问题</strong>：npm 安装速度慢，或者安装失败。</p>
<p><strong>解决方法</strong>：</p>
<ul>
<li><p>使用 <code>nrm</code> 切换到镜像源，如淘宝源：</p>
<pre><code class="lang-bash">  nrm use taobao
</code></pre>
</li>
</ul>
<h3 id="heading-3-1">3. 权限问题</h3>
<p><strong>问题</strong>：全局安装 npm 包时出现权限错误。</p>
<p><strong>解决方法</strong>：</p>
<ul>
<li><p>使用 <code>sudo</code> 提升权限（仅限 Unix 系统）：</p>
<pre><code class="lang-bash">  sudo npm install -g &lt;package-name&gt;
</code></pre>
</li>
<li><p>更改 npm 的默认安装目录：</p>
<pre><code class="lang-bash">  mkdir ~/.npm-global
  npm config <span class="hljs-built_in">set</span> prefix <span class="hljs-string">'~/.npm-global'</span>
  <span class="hljs-built_in">export</span> PATH=~/.npm-global/bin:<span class="hljs-variable">$PATH</span>
  <span class="hljs-built_in">echo</span> <span class="hljs-string">'export PATH=~/.npm-global/bin:$PATH'</span> &gt;&gt; ~/.profile
  <span class="hljs-built_in">source</span> ~/.profile
</code></pre>
</li>
</ul>
<h3 id="heading-4-1">4. 项目依赖冲突</h3>
<p><strong>问题</strong>：安装项目依赖时出现版本冲突或兼容性问题。</p>
<p><strong>解决方法</strong>：</p>
<ul>
<li><p>删除 <code>node_modules</code> 目录和 <code>package-lock.json</code> 文件，然后重新安装依赖：</p>
<pre><code class="lang-bash">  rm -rf node_modules package-lock.json
  npm install
</code></pre>
</li>
<li><p>使用 <code>yarn</code> 作为包管理工具，yarn 具有更好的依赖解析机制：</p>
<pre><code class="lang-bash">  yarn install
</code></pre>
</li>
</ul>
<h3 id="heading-5-eslintprettier">5. ESLint/Prettier 配置问题</h3>
<p><strong>问题</strong>：代码格式化或 linting 不工作。</p>
<p><strong>解决方法</strong>：</p>
<ul>
<li><p>确认你已经安装了相应的 VS Code 扩展，如 ESLint 和 Prettier。</p>
</li>
<li><p>检查项目根目录下的 <code>.eslintrc</code> 和 <code>.prettierrc</code> 文件是否正确配置。</p>
</li>
<li><p>在 VS Code 设置中启用自动格式化：</p>
<pre><code class="lang-json">  {
    <span class="hljs-attr">"editor.formatOnSave"</span>: <span class="hljs-literal">true</span>,
    <span class="hljs-attr">"eslint.autoFixOnSave"</span>: <span class="hljs-literal">true</span>,
    <span class="hljs-attr">"prettier.requireConfig"</span>: <span class="hljs-literal">true</span>
  }
</code></pre>
</li>
</ul>
<h3 id="heading-6-webpack">6. Webpack 配置问题</h3>
<p><strong>问题</strong>：Webpack 打包失败或配置错误。</p>
<p><strong>解决方法</strong>：</p>
<ul>
<li><p>检查 <code>webpack.config.js</code> 文件中的配置是否正确，确保路径和 loader 配置无误。</p>
</li>
<li><p>查看控制台输出的错误信息，根据提示修改配置。</p>
</li>
<li><p>如果问题持续，可以尝试创建一个最小化的 Webpack 配置，只包含基本的入口和输出设置，逐步添加其他配置。</p>
</li>
</ul>
<h3 id="heading-7-1">7. 版本控制问题</h3>
<p><strong>问题</strong>：<code>.gitignore</code> 文件未正确忽略文件或文件夹。</p>
<p><strong>解决方法</strong>：</p>
<ul>
<li><p>确保 <code>.gitignore</code> 文件位于项目根目录，并正确书写忽略规则。</p>
</li>
<li><p>如果文件已被 Git 跟踪，需要先移除再提交：</p>
<pre><code class="lang-bash">  git rm -r --cached &lt;file-or-folder&gt;
  git add .
  git commit -m <span class="hljs-string">"Update .gitignore"</span>
</code></pre>
</li>
</ul>
<h3 id="heading-8">8. 环境变量问题</h3>
<p><strong>问题</strong>：环境变量未正确加载或应用。</p>
<p><strong>解决方法</strong>：</p>
<ul>
<li><p>确认 <code>.env</code> 文件位于项目根目录，并正确定义变量。</p>
</li>
<li><p>在代码中使用 <code>process.env.VARIABLE_NAME</code> 访问环境变量。</p>
</li>
<li><p>使用 <code>dotenv</code> 包加载环境变量（如果未使用 CRA 或类似工具）：</p>
<pre><code class="lang-bash">  npm install dotenv
</code></pre>
<p>  在项目入口文件中添加：</p>
<pre><code class="lang-javascript">  <span class="hljs-built_in">require</span>(<span class="hljs-string">'dotenv'</span>).config();
</code></pre>
</li>
</ul>
<h3 id="heading-9-1">9. 本地服务器问题</h3>
<p><strong>问题</strong>：开发服务器无法启动或访问。</p>
<p><strong>解决方法</strong>：</p>
<ul>
<li><p>检查开发服务器的配置，如端口设置和主机名。</p>
</li>
<li><p>确认没有其他进程占用相同端口。</p>
</li>
<li><p>查看终端输出的错误信息，排查配置或代码中的问题。</p>
</li>
</ul>
<h3 id="heading-10-1">10. 浏览器兼容性问题</h3>
<p><strong>问题</strong>：在不同浏览器中出现样式或功能差异。</p>
<p><strong>解决方法</strong>：</p>
<ul>
<li><p>使用现代 CSS 重置工具，如 Normalize.css，确保一致的样式基础。</p>
</li>
<li><p>使用 Polyfill 提供对旧版浏览器的支持，例如 Babel 或 core-js。</p>
</li>
<li><p>在不同浏览器中测试应用，使用开发者工具排查问题。</p>
</li>
</ul>
<p>通过这些步骤，你可以解决大多数前端开发环境搭建中遇到的问题，确保一个稳定高效的开发环境。</p>
<h1 id="heading-github-codespaces">六、使用GitHub Codespaces快速搭建前端项目的开发环境</h1>
<p>使用 GitHub Codespaces 快速搭建前端项目的开发环境非常方便，下面是详细的步骤：</p>
<h3 id="heading-1">1. 准备工作</h3>
<p>确保你已经有一个 GitHub 账户，并且在本地安装了 Visual Studio Code（可选，如果你希望本地连接 Codespaces）。</p>
<h3 id="heading-2-1">2. 创建或选择一个仓库</h3>
<ol>
<li><p><strong>创建一个新的 GitHub 仓库</strong>：</p>
<ul>
<li><p>登录 GitHub，点击右上角的 <code>+</code> 按钮，选择 <code>New repository</code>。</p>
</li>
<li><p>输入仓库名称、描述，选择公开或私有，然后点击 <code>Create repository</code>。</p>
</li>
</ul>
</li>
<li><p><strong>选择一个已有的仓库</strong>：</p>
<ul>
<li>打开你希望使用的已有仓库页面。</li>
</ul>
</li>
</ol>
<h3 id="heading-3-devcontainer">3. 配置 <code>.devcontainer</code></h3>
<p>在仓库的根目录创建一个 <code>.devcontainer</code> 文件夹，包含以下配置文件：</p>
<ol>
<li><p><strong>创建</strong><code>devcontainer.json</code> 文件：</p>
<pre><code class="lang-json"> {
   <span class="hljs-attr">"name"</span>: <span class="hljs-string">"My Frontend Project"</span>,
   <span class="hljs-attr">"image"</span>: <span class="hljs-string">"mcr.microsoft.com/vscode/devcontainers/javascript-node:0-14"</span>,
   <span class="hljs-attr">"extensions"</span>: [
     <span class="hljs-string">"dbaeumer.vscode-eslint"</span>,
     <span class="hljs-string">"esbenp.prettier-vscode"</span>,
     <span class="hljs-string">"formulahendry.auto-close-tag"</span>,
     <span class="hljs-string">"formulahendry.auto-rename-tag"</span>,
     <span class="hljs-string">"eamodio.gitlens"</span>,
     <span class="hljs-string">"streetsidesoftware.code-spell-checker"</span>
   ],
   <span class="hljs-attr">"settings"</span>: {
     <span class="hljs-attr">"editor.formatOnSave"</span>: <span class="hljs-literal">true</span>,
     <span class="hljs-attr">"editor.tabSize"</span>: <span class="hljs-number">2</span>
   },
   <span class="hljs-attr">"postCreateCommand"</span>: <span class="hljs-string">"npm install"</span>
 }
</code></pre>
</li>
<li><p><strong>添加 Dockerfile（可选）</strong>： 如果你需要更多自定义，可以添加一个 Dockerfile 来指定自定义的开发环境。</p>
<pre><code class="lang-dockerfile"> <span class="hljs-keyword">FROM</span> mcr.microsoft.com/vscode/devcontainers/javascript-node:<span class="hljs-number">0</span>-<span class="hljs-number">14</span>

 <span class="hljs-comment"># 安装额外的依赖</span>
 <span class="hljs-keyword">RUN</span><span class="bash"> npm install -g yarn</span>
</code></pre>
</li>
</ol>
<h3 id="heading-4-codespace">4. 启动 Codespace</h3>
<ol>
<li><p><strong>从 GitHub 仓库页面启动</strong>：</p>
<ul>
<li>打开仓库页面，点击 <code>Code</code> 按钮，然后选择 <code>Codespaces</code> 标签，点击 <code>Create codespace on main</code>（或选择其他分支）。</li>
</ul>
</li>
<li><p><strong>从 GitHub 主页启动</strong>：</p>
<ul>
<li>点击你的头像，选择 <code>Codespaces</code>，然后点击 <code>New codespace</code> 按钮，选择仓库和分支。</li>
</ul>
</li>
</ol>
<h3 id="heading-5-codespace">5. 使用 Codespace</h3>
<ol>
<li><p><strong>在浏览器中开发</strong>：</p>
<ul>
<li>Codespace 创建完成后，会自动在浏览器中启动 VS Code，你可以开始编写代码。</li>
</ul>
</li>
<li><p><strong>在本地 VS Code 中开发</strong>（可选）：</p>
<ul>
<li><p>安装 <code>GitHub Codespaces</code> 扩展。</p>
</li>
<li><p>打开 VS Code，点击左侧活动栏中的 <code>Remote Explorer</code> 图标。</p>
</li>
<li><p>找到并连接到你的 Codespace。</p>
</li>
</ul>
</li>
</ol>
<h3 id="heading-6-1">6. 项目初始化</h3>
<ol>
<li><p><strong>创建一个新的前端项目</strong>： 根据你使用的前端框架，运行相应的命令初始化项目。</p>
<ul>
<li><p><strong>Vue.js</strong>：</p>
<pre><code class="lang-bash">  vue create my-project
  <span class="hljs-built_in">cd</span> my-project
  npm run serve
</code></pre>
</li>
<li><p><strong>React</strong>：</p>
<pre><code class="lang-bash">  npx create-react-app my-project
  <span class="hljs-built_in">cd</span> my-project
  npm start
</code></pre>
</li>
<li><p><strong>Angular</strong>：</p>
<pre><code class="lang-bash">  npx -p @angular/cli ng new my-project
  <span class="hljs-built_in">cd</span> my-project
  ng serve
</code></pre>
</li>
</ul>
</li>
<li><p><strong>安装依赖</strong>： 在项目根目录运行以下命令安装依赖：</p>
<pre><code class="lang-bash"> npm install
</code></pre>
</li>
</ol>
<h3 id="heading-7-git">7. Git 和版本控制</h3>
<ol>
<li><p><strong>初始化 Git 仓库</strong>： 如果你的项目还没有初始化 Git 仓库，运行以下命令：</p>
<pre><code class="lang-bash"> git init
</code></pre>
</li>
<li><p><strong>创建</strong><code>.gitignore</code> 文件： 忽略不需要的文件和文件夹，例如：</p>
<pre><code class="lang-plaintext"> node_modules/
 dist/
 .env
</code></pre>
</li>
<li><p><strong>提交代码</strong>： 提交初始代码：</p>
<pre><code class="lang-bash"> git add .
 git commit -m <span class="hljs-string">"Initial commit"</span>
</code></pre>
</li>
<li><p><strong>推送到远程仓库</strong>： 确保你的远程仓库已配置，然后推送代码：</p>
<pre><code class="lang-bash"> git push origin main
</code></pre>
</li>
</ol>
<h3 id="heading-8-1">8. 其他工具和配置</h3>
<ol>
<li><p><strong>代码格式化和 Linting</strong>：</p>
<ul>
<li><p>确认你已经安装了 ESLint 和 Prettier 扩展，并在项目中配置相应的文件：</p>
<ul>
<li><p><code>.eslintrc.js</code> 或 <code>.eslintrc.json</code></p>
</li>
<li><p><code>.prettierrc</code> 或 <code>.prettierrc.json</code></p>
</li>
</ul>
</li>
</ul>
</li>
<li><p><strong>环境变量配置</strong>： 使用 <code>.env</code> 文件配置环境变量，确保在不同环境中使用不同配置。</p>
</li>
</ol>
<h3 id="heading-9-codespaces">9. 管理 Codespaces</h3>
<ol>
<li><p><strong>停止或删除 Codespace</strong>：</p>
<ul>
<li>在 GitHub 主页，点击你的头像，选择 <code>Codespaces</code>，你可以停止或删除不再需要的 Codespace。</li>
</ul>
</li>
<li><p><strong>查看资源使用情况</strong>：</p>
<ul>
<li>在 <code>Codespaces</code> 页面，你可以查看每个 Codespace 的资源使用情况，并进行相应调整。</li>
</ul>
</li>
</ol>
<p>通过以上步骤，你可以快速搭建一个功能齐全的前端开发环境，利用 GitHub Codespaces 提供的便利性和高效性进行云端开发。</p>
<h1 id="heading-6zme5b2v">附录</h1>
<h2 id="heading-git">Git版本管理</h2>
<p>Git 是一个分布式版本控制系统，广泛用于源代码管理。以下是一些常见 Git 操作的简要介绍（tldr）：</p>
<h3 id="heading-1-1">1. 初始化和克隆仓库</h3>
<p><strong>初始化新仓库</strong>：</p>
<pre><code class="lang-bash">git init
</code></pre>
<p><strong>克隆现有仓库</strong>：</p>
<pre><code class="lang-bash">git <span class="hljs-built_in">clone</span> &lt;repository-url&gt;
</code></pre>
<h3 id="heading-2-2">2. 查看状态和日志</h3>
<p><strong>查看工作目录状态</strong>：</p>
<pre><code class="lang-bash">git status
</code></pre>
<p><strong>查看提交历史</strong>：</p>
<pre><code class="lang-bash">git <span class="hljs-built_in">log</span>
</code></pre>
<h3 id="heading-3-2">3. 添加和提交更改</h3>
<p><strong>添加文件到暂存区</strong>：</p>
<pre><code class="lang-bash">git add &lt;file&gt;  <span class="hljs-comment"># 添加单个文件</span>
git add .       <span class="hljs-comment"># 添加所有更改的文件</span>
</code></pre>
<p><strong>提交更改</strong>：</p>
<pre><code class="lang-bash">git commit -m <span class="hljs-string">"Commit message"</span>
</code></pre>
<h3 id="heading-4-2">4. 分支管理</h3>
<p><strong>创建新分支</strong>：</p>
<pre><code class="lang-bash">git branch &lt;branch-name&gt;
</code></pre>
<p><strong>切换到指定分支</strong>：</p>
<pre><code class="lang-bash">git checkout &lt;branch-name&gt;
</code></pre>
<p><strong>创建并切换到新分支</strong>：</p>
<pre><code class="lang-bash">git checkout -b &lt;branch-name&gt;
</code></pre>
<p><strong>删除分支</strong>：</p>
<pre><code class="lang-bash">git branch -d &lt;branch-name&gt;  <span class="hljs-comment"># 删除本地分支</span>
git push origin --delete &lt;branch-name&gt;  <span class="hljs-comment"># 删除远程分支</span>
</code></pre>
<h3 id="heading-5-1">5. 合并和冲突解决</h3>
<p><strong>合并分支</strong>：</p>
<pre><code class="lang-bash">git merge &lt;branch-name&gt;
</code></pre>
<p><strong>查看合并冲突</strong>：</p>
<pre><code class="lang-bash">git status
</code></pre>
<p><strong>解决冲突后标记为已解决</strong>：</p>
<pre><code class="lang-bash">git add &lt;resolved-file&gt;
git commit
</code></pre>
<h3 id="heading-6-2">6. 远程仓库操作</h3>
<p><strong>查看远程仓库</strong>：</p>
<pre><code class="lang-bash">git remote -v
</code></pre>
<p><strong>添加远程仓库</strong>：</p>
<pre><code class="lang-bash">git remote add &lt;remote-name&gt; &lt;repository-url&gt;
</code></pre>
<p><strong>从远程仓库获取更新</strong>：</p>
<pre><code class="lang-bash">git fetch &lt;remote-name&gt;
</code></pre>
<p><strong>推送更改到远程仓库</strong>：</p>
<pre><code class="lang-bash">git push &lt;remote-name&gt; &lt;branch-name&gt;
</code></pre>
<p><strong>拉取远程仓库更新并合并</strong>：</p>
<pre><code class="lang-bash">git pull &lt;remote-name&gt; &lt;branch-name&gt;
</code></pre>
<h3 id="heading-7-2">7. 重置和撤销</h3>
<p><strong>撤销对文件的更改（未添加到暂存区）</strong>：</p>
<pre><code class="lang-bash">git checkout -- &lt;file&gt;
</code></pre>
<p><strong>撤销对已添加到暂存区的文件的更改</strong>：</p>
<pre><code class="lang-bash">git reset HEAD &lt;file&gt;
</code></pre>
<p><strong>撤销最后一次提交（保留更改）</strong>：</p>
<pre><code class="lang-bash">git reset --soft HEAD~1
</code></pre>
<p><strong>永久删除提交（不保留更改）</strong>：</p>
<pre><code class="lang-bash">git reset --hard HEAD~1
</code></pre>
<h3 id="heading-8-2">8. 标签管理</h3>
<p><strong>创建标签</strong>：</p>
<pre><code class="lang-bash">git tag &lt;tag-name&gt;
</code></pre>
<p><strong>推送标签到远程</strong>：</p>
<pre><code class="lang-bash">git push origin &lt;tag-name&gt;
</code></pre>
<p><strong>删除标签</strong>：</p>
<pre><code class="lang-bash">git tag -d &lt;tag-name&gt;  <span class="hljs-comment"># 删除本地标签</span>
git push origin --delete &lt;tag-name&gt;  <span class="hljs-comment"># 删除远程标签</span>
</code></pre>
<h3 id="heading-9-i">9. 工作流示例I</h3>
<p><strong>创建和切换到新分支，提交更改</strong>：</p>
<pre><code class="lang-bash">git checkout -b &lt;feature-branch&gt;
<span class="hljs-comment"># make changes</span>
git add .
git commit -m <span class="hljs-string">"Add new feature"</span>
git push origin &lt;feature-branch&gt;
</code></pre>
<p><strong>发起 Pull Request</strong>：</p>
<ul>
<li>在 GitHub 或其他托管平台上发起 Pull Request，将 <code>feature-branch</code> 合并到主分支。</li>
</ul>
<p>通过这些基本操作，你可以高效地使用 Git 进行版本控制和协作开发。</p>
<p><code>git rebase</code> 是一个重要的 Git 操作，用于将一个分支的更改移到另一个基准之上，以保持历史记录的整洁。以下是 <code>git rebase</code> 的简要介绍（tldr）以及如何将其应用到前面提到的工作流中：</p>
<h3 id="heading-10-git-rebase">10. 使用 <code>git rebase</code></h3>
<p><strong>基本用法</strong>：</p>
<p><strong>将当前分支的更改移到目标分支的最新提交上</strong>：</p>
<pre><code class="lang-bash">git rebase &lt;base-branch&gt;
</code></pre>
<p><strong>交互式 Rebase（修改提交历史）</strong>：</p>
<pre><code class="lang-bash">git rebase -i &lt;base-commit&gt;
</code></pre>
<h3 id="heading-11-ii">11. 工作流示例II</h3>
<p><strong>假设你正在开发一个新特性并已经创建了一个特性分支</strong><code>feature-branch</code>，并且在 <code>main</code> 分支上有新的提交。你希望将 <code>feature-branch</code> 的更改基于 <code>main</code> 分支的最新提交。</p>
<ol>
<li><p><strong>切换到特性分支</strong>：</p>
<pre><code class="lang-bash"> git checkout feature-branch
</code></pre>
</li>
<li><p><strong>执行 Rebase</strong>：</p>
<pre><code class="lang-bash"> git rebase main
</code></pre>
<p> 这将把 <code>feature-branch</code> 上的更改移动到 <code>main</code> 分支的最新提交之后。</p>
</li>
<li><p><strong>解决冲突（如果有）</strong>：</p>
<ul>
<li><p>如果在 Rebase 过程中出现冲突，Git 会暂停并提示你解决冲突。</p>
</li>
<li><p>解决冲突后，使用 <code>git add &lt;file&gt;</code> 将已解决的文件标记为已解决。</p>
</li>
<li><p>继续 Rebase 过程：</p>
<pre><code class="lang-bash">  git rebase --<span class="hljs-built_in">continue</span>
</code></pre>
</li>
</ul>
</li>
<li><p><strong>推送 Rebase 后的更改</strong>：</p>
<p> 如果你已经推送过 <code>feature-branch</code> 到远程仓库，在进行 Rebase 后需要强制推送（因为历史记录已更改）：</p>
<pre><code class="lang-bash"> git push --force
</code></pre>
</li>
</ol>
<p>额外操作</p>
<p><strong>中止 Rebase 过程（如果发生问题）</strong>：</p>
<pre><code class="lang-bash">git rebase --abort
</code></pre>
<p><strong>查看 Rebase 进度</strong>：</p>
<pre><code class="lang-bash">git rebase --show-current-patch
</code></pre>
<p>通过以上步骤，你可以有效地使用 <code>git rebase</code> 来保持分支的历史记录清晰，并将特性分支的更改基于最新的主分支提交。</p>
<h2 id="heading-linux">Linux用户权限管理</h2>
<p>在 Linux 中，用户和组管理是系统管理的重要部分。以下是一些常见的用户和组管理操作的简要介绍（tldr）：</p>
<h3 id="heading-1-2">1. 创建用户</h3>
<p><strong>命令</strong>：<code>useradd</code> 或 <code>adduser</code></p>
<pre><code class="lang-bash">sudo useradd username
sudo adduser username  <span class="hljs-comment"># 交互式创建用户</span>
</code></pre>
<h3 id="heading-2-3">2. 删除用户</h3>
<p><strong>命令</strong>：<code>userdel</code></p>
<pre><code class="lang-bash">sudo userdel username
sudo userdel -r username  <span class="hljs-comment"># 删除用户及其主目录</span>
</code></pre>
<h3 id="heading-3-3">3. 修改用户</h3>
<p><strong>命令</strong>：<code>usermod</code></p>
<pre><code class="lang-bash">sudo usermod -aG groupname username  <span class="hljs-comment"># 将用户添加到组</span>
sudo usermod -d /new/home/dir username  <span class="hljs-comment"># 修改用户主目录</span>
sudo usermod -l newusername oldusername  <span class="hljs-comment"># 修改用户名</span>
</code></pre>
<h3 id="heading-4-3">4. 创建组</h3>
<p><strong>命令</strong>：<code>groupadd</code></p>
<pre><code class="lang-bash">sudo groupadd groupname
</code></pre>
<h3 id="heading-5-2">5. 删除组</h3>
<p><strong>命令</strong>：<code>groupdel</code></p>
<pre><code class="lang-bash">sudo groupdel groupname
</code></pre>
<h3 id="heading-6-3">6. 查看用户和组信息</h3>
<p><strong>命令</strong>：<code>id</code>，<code>groups</code>，<code>getent</code></p>
<pre><code class="lang-bash">id username  <span class="hljs-comment"># 查看用户的 UID、GID 和所属组</span>
groups username  <span class="hljs-comment"># 查看用户所属的组</span>
getent passwd username  <span class="hljs-comment"># 查看用户的详细信息</span>
getent group groupname  <span class="hljs-comment"># 查看组的详细信息</span>
</code></pre>
<h3 id="heading-7-3">7. 修改用户密码</h3>
<p><strong>命令</strong>：<code>passwd</code></p>
<pre><code class="lang-bash">sudo passwd username  <span class="hljs-comment"># 为指定用户修改密码</span>
passwd  <span class="hljs-comment"># 为当前用户修改密码</span>
</code></pre>
<h3 id="heading-8-3">8. 锁定和解锁用户账户</h3>
<p><strong>命令</strong>：<code>usermod</code></p>
<pre><code class="lang-bash">sudo usermod -L username  <span class="hljs-comment"># 锁定用户账户</span>
sudo usermod -U username  <span class="hljs-comment"># 解锁用户账户</span>
</code></pre>
<h3 id="heading-9-2">9. 临时切换用户</h3>
<p><strong>命令</strong>：<code>su</code>，<code>sudo</code>，<code>sudo -i</code></p>
<pre><code class="lang-bash">su - username  <span class="hljs-comment"># 切换到指定用户</span>
sudo -i  <span class="hljs-comment"># 切换到 root 用户</span>
</code></pre>
<h3 id="heading-10-2">10. 文件权限管理</h3>
<p><strong>命令</strong>：<code>chown</code>，<code>chgrp</code>，<code>chmod</code></p>
<pre><code class="lang-bash">sudo chown username:groupname filename  <span class="hljs-comment"># 修改文件所有者和组</span>
sudo chgrp groupname filename  <span class="hljs-comment"># 修改文件组</span>
chmod 755 filename  <span class="hljs-comment"># 修改文件权限</span>
</code></pre>
<p>通过这些命令，你可以在 Linux 系统中高效地管理用户和组。</p>
<h2 id="heading-docker">Docker</h2>
<p>Docker 是一个开源的容器化平台，用于自动化应用程序的部署、扩展和管理。以下是 Docker 常用命令的简要介绍（tldr）：</p>
<h3 id="heading-1-docker">1. 安装 Docker</h3>
<p><strong>安装 Docker</strong>（具体步骤可能因操作系统不同而有所不同）：</p>
<ul>
<li><p><strong>Linux</strong>：使用包管理工具安装，例如 <code>apt</code>、<code>yum</code> 等。</p>
</li>
<li><p><strong>macOS</strong> 和 <strong>Windows</strong>：下载 Docker Desktop 安装包并按照提示进行安装。</p>
</li>
</ul>
<h3 id="heading-2-docker">2. Docker 基础命令</h3>
<p><strong>查看 Docker 版本</strong>：</p>
<pre><code class="lang-bash">docker --version
</code></pre>
<p><strong>查看 Docker 服务状态</strong>：</p>
<pre><code class="lang-bash">sudo systemctl status docker
</code></pre>
<p><strong>启动 Docker 服务</strong>：</p>
<pre><code class="lang-bash">sudo systemctl start docker
</code></pre>
<p><strong>停止 Docker 服务</strong>：</p>
<pre><code class="lang-bash">sudo systemctl stop docker
</code></pre>
<h3 id="heading-3-4">3. 镜像管理</h3>
<p><strong>拉取镜像</strong>：</p>
<pre><code class="lang-bash">docker pull &lt;image-name&gt;
</code></pre>
<p><strong>列出本地镜像</strong>：</p>
<pre><code class="lang-bash">docker images
</code></pre>
<p><strong>删除镜像</strong>：</p>
<pre><code class="lang-bash">docker rmi &lt;image-id&gt;
</code></pre>
<p><strong>构建镜像</strong>：</p>
<pre><code class="lang-bash">docker build -t &lt;tag&gt; &lt;path-to-Dockerfile&gt;
</code></pre>
<h3 id="heading-4-4">4. 容器管理</h3>
<p><strong>运行容器</strong>：</p>
<pre><code class="lang-bash">docker run &lt;options&gt; &lt;image-name&gt;
</code></pre>
<p><strong>列出运行中的容器</strong>：</p>
<pre><code class="lang-bash">docker ps
</code></pre>
<p><strong>列出所有容器（包括停止的）</strong>：</p>
<pre><code class="lang-bash">docker ps -a
</code></pre>
<p><strong>停止容器</strong>：</p>
<pre><code class="lang-bash">docker stop &lt;container-id&gt;
</code></pre>
<p><strong>启动已停止的容器</strong>：</p>
<pre><code class="lang-bash">docker start &lt;container-id&gt;
</code></pre>
<p><strong>删除容器</strong>：</p>
<pre><code class="lang-bash">docker rm &lt;container-id&gt;
</code></pre>
<p><strong>查看容器日志</strong>：</p>
<pre><code class="lang-bash">docker logs &lt;container-id&gt;
</code></pre>
<h3 id="heading-5-3">5. 容器和镜像操作</h3>
<p><strong>进入运行中的容器</strong>：</p>
<pre><code class="lang-bash">docker <span class="hljs-built_in">exec</span> -it &lt;container-id&gt; /bin/bash
</code></pre>
<p><strong>查看容器内的进程</strong>：</p>
<pre><code class="lang-bash">docker top &lt;container-id&gt;
</code></pre>
<p><strong>查看容器的详细信息</strong>：</p>
<pre><code class="lang-bash">docker inspect &lt;container-id&gt;
</code></pre>
<h3 id="heading-6-4">6. 网络和数据管理</h3>
<p><strong>列出 Docker 网络</strong>：</p>
<pre><code class="lang-bash">docker network ls
</code></pre>
<p><strong>创建 Docker 网络</strong>：</p>
<pre><code class="lang-bash">docker network create &lt;network-name&gt;
</code></pre>
<p><strong>删除 Docker 网络</strong>：</p>
<pre><code class="lang-bash">docker network rm &lt;network-name&gt;
</code></pre>
<p><strong>列出 Docker 卷</strong>：</p>
<pre><code class="lang-bash">docker volume ls
</code></pre>
<p><strong>创建 Docker 卷</strong>：</p>
<pre><code class="lang-bash">docker volume create &lt;volume-name&gt;
</code></pre>
<p><strong>删除 Docker 卷</strong>：</p>
<pre><code class="lang-bash">docker volume rm &lt;volume-name&gt;
</code></pre>
<h3 id="heading-7-docker-compose">7. Docker Compose</h3>
<p><strong>安装 Docker Compose</strong>：</p>
<ul>
<li><p>Docker Compose 通常与 Docker Desktop 一起安装。也可以通过以下命令安装：</p>
<pre><code class="lang-bash">  sudo curl -L <span class="hljs-string">"https://github.com/docker/compose/releases/download/<span class="hljs-subst">$(curl -s https://api.github.com/repos/docker/compose/releases/latest | grep tag_name | cut -d '<span class="hljs-string">"' -f 4)/docker-compose-<span class="hljs-subst">$(uname -s)</span>-<span class="hljs-subst">$(uname -m)</span>"</span> -o /usr/local/bin/docker-compose
  sudo chmod +x /usr/local/bin/docker-compose</span></span>
</code></pre>
</li>
</ul>
<p><strong>使用 Docker Compose 启动服务</strong>：</p>
<pre><code class="lang-bash">docker-compose up
</code></pre>
<p><strong>停止 Docker Compose 服务</strong>：</p>
<pre><code class="lang-bash">docker-compose down
</code></pre>
<p><strong>查看 Docker Compose 日志</strong>：</p>
<pre><code class="lang-bash">docker-compose logs
</code></pre>
<p>通过这些基本命令，你可以高效地使用 Docker 进行容器化应用的管理和部署。</p>
<h2 id="heading-dev-containers">Dev Containers</h2>
<p><strong>Dev Containers</strong> 是一种在 Visual Studio Code 中定义和管理开发环境的方法。通过使用 Dev Containers，你可以确保团队中的所有开发人员使用一致的开发环境，从而减少环境配置问题。以下是 Dev Containers 的简要介绍（tldr）：</p>
<h3 id="heading-1-dev-containers">1. 什么是 Dev Containers?</h3>
<p>Dev Containers 允许你在容器中定义开发环境，通常通过 Docker 来实现。它们包括所有必要的工具、依赖项和设置，从而确保开发环境的一致性。</p>
<h3 id="heading-2-dev-container">2. 创建 Dev Container</h3>
<p><strong>步骤</strong>：</p>
<ol>
<li><p><strong>在项目中创建</strong><code>.devcontainer</code> 目录： 在你的项目根目录下创建一个 <code>.devcontainer</code> 目录，用于存放 Dev Container 配置文件。</p>
</li>
<li><p><strong>添加</strong><code>devcontainer.json</code> 文件： 在 <code>.devcontainer</code> 目录中创建一个 <code>devcontainer.json</code> 文件，定义容器的配置。</p>
<p> <strong>示例</strong><code>devcontainer.json</code>：</p>
<pre><code class="lang-json"> {
   <span class="hljs-attr">"name"</span>: <span class="hljs-string">"Node.js &amp; TypeScript"</span>,
   <span class="hljs-attr">"dockerFile"</span>: <span class="hljs-string">"Dockerfile"</span>,
   <span class="hljs-attr">"extensions"</span>: [
     <span class="hljs-string">"dbaeumer.vscode-eslint"</span>,
     <span class="hljs-string">"esbenp.prettier-vscode"</span>
   ],
   <span class="hljs-attr">"settings"</span>: {
     <span class="hljs-attr">"editor.formatOnSave"</span>: <span class="hljs-literal">true</span>
   },
   <span class="hljs-attr">"postCreateCommand"</span>: <span class="hljs-string">"npm install"</span>
 }
</code></pre>
</li>
<li><p><strong>创建</strong><code>Dockerfile</code>（可选）： 如果你需要自定义容器环境，可以创建一个 <code>Dockerfile</code> 文件来指定容器的基础镜像和安装额外的软件包。</p>
<p> <strong>示例</strong><code>Dockerfile</code>：</p>
<pre><code class="lang-dockerfile"> <span class="hljs-keyword">FROM</span> mcr.microsoft.com/vscode/devcontainers/javascript-node:<span class="hljs-number">0</span>-<span class="hljs-number">14</span>

 <span class="hljs-comment"># 安装额外的依赖</span>
 <span class="hljs-keyword">RUN</span><span class="bash"> npm install -g typescript</span>
</code></pre>
</li>
</ol>
<h3 id="heading-3-dev-containers">3. 使用 Dev Containers</h3>
<p><strong>在 VS Code 中打开 Dev Container</strong>：</p>
<ol>
<li><p><strong>打开 VS Code</strong>。</p>
</li>
<li><p><strong>从命令面板启动 Dev Container</strong>：</p>
<ul>
<li><p>使用快捷键 <code>Ctrl+Shift+P</code>（Windows/Linux）或 <code>Cmd+Shift+P</code>（macOS）打开命令面板。</p>
</li>
<li><p>输入并选择 <code>Remote-Containers: Reopen in Container</code>。</p>
</li>
</ul>
</li>
<li><p><strong>VS Code 会自动构建并启动 Dev Container</strong>：</p>
<ul>
<li>VS Code 会构建 Docker 容器并打开该容器中的工作目录，你现在可以在容器中开发代码。</li>
</ul>
</li>
</ol>
<h3 id="heading-4-5">4. 其他操作</h3>
<p><strong>更新 Dev Container 配置</strong>：</p>
<ul>
<li>更新 <code>devcontainer.json</code> 或 <code>Dockerfile</code> 后，可以通过 <code>Remote-Containers: Rebuild Container</code> 命令重建容器以应用更改。</li>
</ul>
<p><strong>删除 Dev Container</strong>：</p>
<ul>
<li>在 VS Code 的 <code>Remote Explorer</code> 视图中，选择 <code>Remove</code> 操作来删除不再需要的容器。</li>
</ul>
<p><strong>共享 Dev Container 配置</strong>：</p>
<ul>
<li>将 <code>.devcontainer</code> 目录添加到版本控制系统（如 Git）中，以便团队成员可以使用相同的开发环境。</li>
</ul>
<h3 id="heading-5-4">5. 故障排除</h3>
<p><strong>容器无法启动或构建失败</strong>：</p>
<ul>
<li><p>检查 Dockerfile 和 <code>devcontainer.json</code> 的配置是否正确。</p>
</li>
<li><p>查看 VS Code 的 <code>Remote-Containers</code> 输出日志以获取更多信息。</p>
</li>
</ul>
<p><strong>容器中缺少工具或依赖</strong>：</p>
<ul>
<li>更新 <code>Dockerfile</code> 或 <code>devcontainer.json</code> 文件，确保安装了所需的工具和依赖，然后重新构建容器。</li>
</ul>
<p>通过这些步骤，你可以快速设置和使用 Dev Containers，为开发团队提供一致的开发环境，并简化开发过程。</p>
<h2 id="heading-github-codespaces-1">GitHub Codespaces简介</h2>
<p>GitHub Codespaces 是一个基于云的开发环境，允许你在任何地方使用 VS Code 开发代码。以下是 GitHub Codespaces 的简要介绍（tldr）及其常用操作：</p>
<h3 id="heading-1-codespace">1. 创建 Codespace</h3>
<p><strong>从 GitHub 仓库创建 Codespace</strong>：</p>
<ol>
<li><p>打开你想要创建 Codespace 的仓库。</p>
</li>
<li><p>点击 <code>Code</code> 按钮，然后选择 <code>Create codespace on main</code>（或选择其他分支）。</p>
</li>
</ol>
<p><strong>从 GitHub 首页创建 Codespace</strong>：</p>
<ol>
<li><p>点击你的头像，选择 <code>Codespaces</code>。</p>
</li>
<li><p>点击 <code>New codespace</code> 按钮，然后选择一个仓库。</p>
</li>
</ol>
<h3 id="heading-2-codespace">2. 配置 Codespace</h3>
<p><strong>配置开发环境</strong>：</p>
<ul>
<li>你可以在仓库的 <code>.devcontainer</code> 目录中添加配置文件来定义 Codespace 的开发环境，包括基础镜像、扩展、工具等。</li>
</ul>
<p><strong>示例</strong><code>.devcontainer/devcontainer.json</code>：</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"name"</span>: <span class="hljs-string">"My Codespace"</span>,
  <span class="hljs-attr">"image"</span>: <span class="hljs-string">"mcr.microsoft.com/vscode/devcontainers/javascript-node:0-14"</span>,
  <span class="hljs-attr">"extensions"</span>: [
    <span class="hljs-string">"dbaeumer.vscode-eslint"</span>,
    <span class="hljs-string">"esbenp.prettier-vscode"</span>
  ],
  <span class="hljs-attr">"settings"</span>: {
    <span class="hljs-attr">"editor.formatOnSave"</span>: <span class="hljs-literal">true</span>
  }
}
</code></pre>
<h3 id="heading-3-codespace">3. 使用 Codespace</h3>
<p><strong>启动 Codespace</strong>：</p>
<ul>
<li>一旦 Codespace 创建完成，GitHub 会自动在浏览器中启动 VS Code，你可以开始编写代码。</li>
</ul>
<p><strong>连接本地 VS Code 到 Codespace</strong>：</p>
<ol>
<li><p>安装 VS Code 和 <code>GitHub Codespaces</code> 扩展。</p>
</li>
<li><p>打开 VS Code，点击左侧活动栏中的 <code>Remote Explorer</code> 图标。</p>
</li>
<li><p>找到并连接到你的 Codespace。</p>
</li>
</ol>
<h3 id="heading-4-codespaces">4. 管理 Codespaces</h3>
<p><strong>列出所有 Codespaces</strong>：</p>
<ul>
<li>在 GitHub 主页，点击你的头像，选择 <code>Codespaces</code> 查看你所有的 Codespaces。</li>
</ul>
<p><strong>停止或删除 Codespace</strong>：</p>
<ul>
<li>在 <code>Codespaces</code> 页面，可以停止、重命名或删除你不再需要的 Codespace。</li>
</ul>
<h3 id="heading-5-git-github">5. 使用 Git 和 GitHub</h3>
<p><strong>常用 Git 命令</strong>：</p>
<ul>
<li><p>Codespaces 内置 Git，你可以在终端中使用常规 Git 命令：</p>
<pre><code class="lang-bash">  git status
  git add .
  git commit -m <span class="hljs-string">"Initial commit"</span>
  git push origin main
</code></pre>
</li>
</ul>
<p><strong>GitHub 扩展</strong>：</p>
<ul>
<li>你还可以使用 GitHub 提供的 VS Code 扩展进行 Pull Request 管理、代码审查等。</li>
</ul>
<h3 id="heading-6-5">6. 终端和任务</h3>
<p><strong>打开终端</strong>：</p>
<ul>
<li>在 VS Code 中使用 <code>Ctrl +</code> （反引号）或通过菜单 <code>Terminal &gt; New Terminal</code> 打开内置终端。</li>
</ul>
<p><strong>运行任务</strong>：</p>
<ul>
<li>你可以在 <code>Tasks &gt; Run Task</code> 中运行预定义的任务，例如构建、测试等。</li>
</ul>
<h3 id="heading-7-dev-containers">7. 使用 Dev Containers</h3>
<p><strong>定义 Dev Container</strong>：</p>
<ul>
<li>Dev Container 文件位于 <code>.devcontainer</code> 目录，通过配置该文件，Codespace 会自动为你创建和配置开发环境。</li>
</ul>
<h3 id="heading-8-4">8. 资源管理</h3>
<p><strong>检查和调整资源</strong>：</p>
<ul>
<li>GitHub 提供不同的资源配置（CPU、内存等），你可以在创建 Codespace 时进行选择。</li>
</ul>
<p><strong>查看使用情况</strong>：</p>
<ul>
<li>在 <code>Codespaces</code> 页面，你可以查看每个 Codespace 的资源使用情况。</li>
</ul>
<p>通过以上步骤和操作，你可以有效地使用 GitHub Codespaces 进行云端开发，实现随时随地的高效开发体验。</p>
]]></content:encoded></item><item><title><![CDATA[Google Test表格驱动测试最佳实践案例]]></title><description><![CDATA[案例一：用列表组织测试用例
在使用 Google Test 进行表驱动测试时，遵循最佳实践可以确保测试代码的可读性、可维护性和扩展性。以下是一些最佳实践建议：
1. 组织测试数据
将测试数据和预期结果放在一个结构体或类中，以便于管理和扩展。
2. 使用 TestWithParam 和 INSTANTIATE_TEST_SUITE_P
TestWithParam 可以让你轻松地将参数化测试与测试数据关联。确保使用最新的 Google Test 版本以利用其新功能。
3. 明确测试名称
使用 INS...]]></description><link>https://blog.wuzhiguo.tech/google-test-table-driven-test-best-practice</link><guid isPermaLink="true">https://blog.wuzhiguo.tech/google-test-table-driven-test-best-practice</guid><category><![CDATA[UnitTest]]></category><category><![CDATA[table-driven-testing]]></category><category><![CDATA[google test]]></category><dc:creator><![CDATA[wuzhiguocarter]]></dc:creator><pubDate>Wed, 07 Aug 2024 14:28:59 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1723042417925/00827bd2-79d1-4166-a22a-facc25810176.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-5qgi5l6l5lia77ya55so5yix6kgo57ue57uh5rwl6kv55so5l6l">案例一：用列表组织测试用例</h1>
<p>在使用 Google Test 进行表驱动测试时，遵循最佳实践可以确保测试代码的可读性、可维护性和扩展性。以下是一些最佳实践建议：</p>
<h3 id="heading-1">1. 组织测试数据</h3>
<p>将测试数据和预期结果放在一个结构体或类中，以便于管理和扩展。</p>
<h3 id="heading-2-testwithparam-instantiatetestsuitep">2. 使用 <code>TestWithParam</code> 和 <code>INSTANTIATE_TEST_SUITE_P</code></h3>
<p><code>TestWithParam</code> 可以让你轻松地将参数化测试与测试数据关联。确保使用最新的 Google Test 版本以利用其新功能。</p>
<h3 id="heading-3">3. 明确测试名称</h3>
<p>使用 <code>INSTANTIATE_TEST_SUITE_P</code> 时，确保测试名称和参数名称明确，这有助于调试和理解测试输出。</p>
<h3 id="heading-4">4. 使用自定义比较函数</h3>
<p>对于复杂的比较，可以编写自定义比较函数来提高测试的清晰度。</p>
<h3 id="heading-56s65l6l">示例</h3>
<p>以下是一个完整的表驱动测试示例，包括组合生成函数和最佳实践。</p>
<h4 id="heading-57ue5zci55sf5oiq5ye95pww">组合生成函数</h4>
<pre><code class="lang-cpp"><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;vector&gt;</span></span>

<span class="hljs-keyword">template</span> &lt;<span class="hljs-keyword">typename</span> T&gt;
<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">GenerateCombinations</span><span class="hljs-params">(<span class="hljs-keyword">const</span> <span class="hljs-built_in">std</span>::<span class="hljs-built_in">vector</span>&lt;T&gt;&amp; elements, <span class="hljs-keyword">int</span> start, <span class="hljs-keyword">int</span> remaining, <span class="hljs-built_in">std</span>::<span class="hljs-built_in">vector</span>&lt;T&gt;&amp; currentCombination, <span class="hljs-built_in">std</span>::<span class="hljs-built_in">vector</span>&lt;<span class="hljs-built_in">std</span>::<span class="hljs-built_in">vector</span>&lt;T&gt;&gt;&amp; result)</span> </span>{
    <span class="hljs-keyword">if</span> (remaining == <span class="hljs-number">0</span>) {
        result.push_back(currentCombination);
        <span class="hljs-keyword">return</span>;
    }

    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = start; i &lt;= elements.size() - remaining; ++i) {
        currentCombination.push_back(elements[i]);
        GenerateCombinations(elements, i + <span class="hljs-number">1</span>, remaining - <span class="hljs-number">1</span>, currentCombination, result);
        currentCombination.pop_back();
    }
}

<span class="hljs-keyword">template</span> &lt;<span class="hljs-keyword">typename</span> T&gt;
<span class="hljs-function"><span class="hljs-built_in">std</span>::<span class="hljs-built_in">vector</span>&lt;<span class="hljs-built_in">std</span>::<span class="hljs-built_in">vector</span>&lt;T&gt;&gt; <span class="hljs-title">GetAllCombinations</span><span class="hljs-params">(<span class="hljs-keyword">const</span> <span class="hljs-built_in">std</span>::<span class="hljs-built_in">vector</span>&lt;T&gt;&amp; elements)</span> </span>{
    <span class="hljs-keyword">int</span> N = elements.size();
    <span class="hljs-built_in">std</span>::<span class="hljs-built_in">vector</span>&lt;<span class="hljs-built_in">std</span>::<span class="hljs-built_in">vector</span>&lt;T&gt;&gt; allCombinations;
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> k = <span class="hljs-number">0</span>; k &lt;= N; ++k) {
        <span class="hljs-built_in">std</span>::<span class="hljs-built_in">vector</span>&lt;T&gt; currentCombination;
        GenerateCombinations(elements, <span class="hljs-number">0</span>, k, currentCombination, allCombinations);
    }
    <span class="hljs-keyword">return</span> allCombinations;
}
</code></pre>
<h4 id="heading-6kgo6amx5yqo5rwl6kv">表驱动测试</h4>
<pre><code class="lang-cpp"><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;gtest/gtest.h&gt;</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;vector&gt;</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;algorithm&gt;</span></span>

<span class="hljs-comment">// 声明组合生成函数</span>
<span class="hljs-keyword">template</span> &lt;<span class="hljs-keyword">typename</span> T&gt;
<span class="hljs-function"><span class="hljs-built_in">std</span>::<span class="hljs-built_in">vector</span>&lt;<span class="hljs-built_in">std</span>::<span class="hljs-built_in">vector</span>&lt;T&gt;&gt; <span class="hljs-title">GetAllCombinations</span><span class="hljs-params">(<span class="hljs-keyword">const</span> <span class="hljs-built_in">std</span>::<span class="hljs-built_in">vector</span>&lt;T&gt;&amp; elements)</span></span>;

<span class="hljs-comment">// 组合测试用例结构体</span>
<span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">CombinationTestCase</span> {</span>
    <span class="hljs-built_in">std</span>::<span class="hljs-built_in">vector</span>&lt;<span class="hljs-keyword">int</span>&gt; input;
    <span class="hljs-built_in">std</span>::<span class="hljs-built_in">vector</span>&lt;<span class="hljs-built_in">std</span>::<span class="hljs-built_in">vector</span>&lt;<span class="hljs-keyword">int</span>&gt;&gt; expected;
};

<span class="hljs-comment">// 自定义比较函数</span>
<span class="hljs-function"><span class="hljs-keyword">bool</span> <span class="hljs-title">CompareCombinations</span><span class="hljs-params">(<span class="hljs-keyword">const</span> <span class="hljs-built_in">std</span>::<span class="hljs-built_in">vector</span>&lt;<span class="hljs-built_in">std</span>::<span class="hljs-built_in">vector</span>&lt;<span class="hljs-keyword">int</span>&gt;&gt;&amp; a, <span class="hljs-keyword">const</span> <span class="hljs-built_in">std</span>::<span class="hljs-built_in">vector</span>&lt;<span class="hljs-built_in">std</span>::<span class="hljs-built_in">vector</span>&lt;<span class="hljs-keyword">int</span>&gt;&gt;&amp; b)</span> </span>{
    <span class="hljs-keyword">auto</span> sorted_a = a;
    <span class="hljs-keyword">auto</span> sorted_b = b;

    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">auto</span>&amp; combination : sorted_a) {
        <span class="hljs-built_in">std</span>::sort(combination.begin(), combination.end());
    }
    <span class="hljs-built_in">std</span>::sort(sorted_a.begin(), sorted_a.end());

    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">auto</span>&amp; combination : sorted_b) {
        <span class="hljs-built_in">std</span>::sort(combination.begin(), combination.end());
    }
    <span class="hljs-built_in">std</span>::sort(sorted_b.begin(), sorted_b.end());

    <span class="hljs-keyword">return</span> sorted_a == sorted_b;
}

<span class="hljs-comment">// 测试类</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CombinationTest</span> :</span> <span class="hljs-keyword">public</span> ::testing::TestWithParam&lt;CombinationTestCase&gt; {};

TEST_P(CombinationTest, GeneratesCorrectCombinations) {
    <span class="hljs-keyword">auto</span> testCase = GetParam();
    <span class="hljs-keyword">auto</span> result = GetAllCombinations(testCase.input);
    EXPECT_TRUE(CompareCombinations(result, testCase.expected));
}

<span class="hljs-comment">// 定义测试数据</span>
CombinationTestCase testCases[] = {
    {
        {<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>},
        {
            {}, {<span class="hljs-number">1</span>}, {<span class="hljs-number">2</span>}, {<span class="hljs-number">3</span>}, {<span class="hljs-number">1</span>, <span class="hljs-number">2</span>}, {<span class="hljs-number">1</span>, <span class="hljs-number">3</span>}, {<span class="hljs-number">2</span>, <span class="hljs-number">3</span>}, {<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>}
        }
    },
    {
        {<span class="hljs-number">1</span>, <span class="hljs-number">2</span>},
        {
            {}, {<span class="hljs-number">1</span>}, {<span class="hljs-number">2</span>}, {<span class="hljs-number">1</span>, <span class="hljs-number">2</span>}
        }
    },
    {
        {<span class="hljs-number">1</span>},
        {
            {}, {<span class="hljs-number">1</span>}
        }
    },
    {
        {},
        {
            {}
        }
    }
};

<span class="hljs-comment">// 实例化测试用例</span>
INSTANTIATE_TEST_SUITE_P(CombinationTests, CombinationTest, ::testing::ValuesIn(testCases));

<span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">main</span><span class="hljs-params">(<span class="hljs-keyword">int</span> argc, <span class="hljs-keyword">char</span> **argv)</span> </span>{
    ::testing::InitGoogleTest(&amp;argc, argv);
    <span class="hljs-keyword">return</span> RUN_ALL_TESTS();
}
</code></pre>
<h3 id="heading-6kej6yek">解释</h3>
<ol>
<li><p><strong>组合生成函数的实现</strong>：代码提供了生成所有组合的 <code>GenerateCombinations</code> 和 <code>GetAllCombinations</code> 函数。</p>
</li>
<li><p><strong>表驱动单元测试</strong>：</p>
<ul>
<li><p><strong>组合测试用例结构体</strong>：<code>CombinationTestCase</code> 存储了输入和预期结果。</p>
</li>
<li><p><strong>自定义比较函数</strong>：<code>CompareCombinations</code> 用于对比两个组合结果，确保在比较前对每个组合和整体结果进行排序。</p>
</li>
<li><p><strong>测试类</strong>：<code>CombinationTest</code> 继承自 <code>::testing::TestWithParam&lt;CombinationTestCase&gt;</code>。</p>
</li>
<li><p><strong>测试逻辑</strong>：在 <code>TEST_P</code> 宏中定义，通过 <code>GetParam</code> 获取测试参数，并使用自定义比较函数 <code>CompareCombinations</code> 验证结果。</p>
</li>
<li><p><strong>定义测试数据</strong>：<code>testCases</code> 包含输入和期望结果。</p>
</li>
<li><p><strong>实例化测试用例</strong>：<code>INSTANTIATE_TEST_SUITE_P</code> 将测试数据与测试用例关联。</p>
</li>
</ul>
</li>
</ol>
<h3 id="heading-5oc757ut">总结</h3>
<p>遵循上述最佳实践，可以提高测试代码的可读性和可维护性，使得添加和管理测试数据更加方便。通过使用自定义比较函数，可以更清晰地表达复杂的比较逻辑，确保测试的准确性。</p>
<h1 id="heading-5qgi5l6l5lqm77ya5luo5pah5lu25yqg6l295rwl6kv55so5l6l">案例二：从文件加载测试用例</h1>
<p>Google Test（通常称为gtest）是一个用于C++的测试框架，它提供了丰富的测试功能，包括参数化测试。如果你想要在使用Google Test时在<code>main</code>函数之前从文件中加载测试用例，你可以考虑使用参数化测试和环境设置（Environment）来实现。</p>
<p>以下是一个简单的步骤说明，展示如何实现这一目标：</p>
<ol>
<li><p><strong>定义参数化测试</strong>: 首先，你需要定义一个参数化测试。这通常涉及到创建一个测试参数结构体，一个参数化测试的工厂函数，以及一个测试模板。</p>
</li>
<li><p><strong>从文件读取测试数据</strong>: 在<code>main</code>函数之前，你可以创建一个<code>Environment</code>对象，它在测试开始前运行。在这个环境设置中，你可以从文件中读取测试数据，并将这些数据作为参数传递给测试。</p>
</li>
<li><p><strong>注册测试</strong>: 使用从文件中读取的数据注册参数化测试。</p>
</li>
</ol>
<p>下面是一个简化的代码示例：</p>
<pre><code class="lang-cpp"><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;fstream&gt;</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;gtest/gtest.h&gt;</span></span>

<span class="hljs-keyword">using</span> ::testing::TestWithParam;
<span class="hljs-keyword">using</span> ::testing::ValuesIn;

<span class="hljs-comment">// 测试参数结构体</span>
<span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">TestCase</span> {</span>
    <span class="hljs-keyword">int</span> input;
    <span class="hljs-keyword">int</span> expected;
};

<span class="hljs-comment">// 测试环境，用于从文件加载测试用例</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TestCaseEnvironment</span> :</span> <span class="hljs-keyword">public</span> ::testing::Environment {
<span class="hljs-keyword">public</span>:
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">SetUp</span><span class="hljs-params">()</span> <span class="hljs-keyword">override</span> </span>{
        <span class="hljs-function"><span class="hljs-built_in">std</span>::ifstream <span class="hljs-title">file</span><span class="hljs-params">(<span class="hljs-string">"test_cases.txt"</span>)</span></span>;
        <span class="hljs-keyword">if</span> (!file) {
            <span class="hljs-built_in">std</span>::<span class="hljs-built_in">cerr</span> &lt;&lt; <span class="hljs-string">"Cannot open test cases file."</span> &lt;&lt; <span class="hljs-built_in">std</span>::<span class="hljs-built_in">endl</span>;
            <span class="hljs-built_in">exit</span>(<span class="hljs-number">1</span>);
        }

        TestCase test_case;
        <span class="hljs-keyword">while</span> (file &gt;&gt; test_case.input &gt;&gt; test_case.expected) {
            test_cases.push_back(test_case);
        }
    }

    <span class="hljs-function"><span class="hljs-keyword">const</span> <span class="hljs-built_in">std</span>::<span class="hljs-built_in">vector</span>&lt;TestCase&gt;&amp; <span class="hljs-title">GetTestCases</span><span class="hljs-params">()</span> <span class="hljs-keyword">const</span> </span>{
        <span class="hljs-keyword">return</span> test_cases;
    }

<span class="hljs-keyword">private</span>:
    <span class="hljs-built_in">std</span>::<span class="hljs-built_in">vector</span>&lt;TestCase&gt; test_cases;
};

<span class="hljs-comment">// 参数化测试</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyTest</span> :</span> <span class="hljs-keyword">public</span> TestWithParam&lt;TestCase&gt; {};

TEST_P(MyTest, TestFunction) {
    <span class="hljs-keyword">const</span> TestCase&amp; test_case = GetParam();
    <span class="hljs-comment">// 执行测试逻辑...</span>
    EXPECT_EQ(<span class="hljs-comment">/* 计算结果 */</span>, test_case.expected);
}

<span class="hljs-comment">// 从环境获取测试用例并注册测试</span>
<span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">main</span><span class="hljs-params">(<span class="hljs-keyword">int</span> argc, <span class="hljs-keyword">char</span> **argv)</span> </span>{
    ::testing::InitGoogleTest(&amp;argc, argv);
    TestCaseEnvironment env;
    ::testing::AddGlobalTestEnvironment(&amp;env);

    <span class="hljs-built_in">std</span>::<span class="hljs-built_in">vector</span>&lt;TestCase&gt; test_cases = env.GetTestCases();
    ::testing::GTEST_FLAG(GetArgvs().c_str()) = ValuesIn(test_cases);

    <span class="hljs-keyword">return</span> RUN_ALL_TESTS();
}
</code></pre>
<p>在这个例子中，<code>TestCaseEnvironment</code>类负责从文件中读取测试用例，并在测试开始前进行设置。<code>MyTest</code>是一个参数化测试类，它使用<code>TEST_P</code>宏定义测试。在<code>main</code>函数中，我们通过<code>TestCaseEnvironment</code>获取测试用例，并将它们注册到测试中。</p>
<p>请注意，这个例子是一个简化的示例，实际使用时可能需要根据你的具体需求进行调整。此外，确保你的测试用例文件（在这个例子中是<code>test_cases.txt</code>）格式正确，并且与代码中的读取逻辑相匹配。</p>
<h1 id="heading-5qgi5l6l5lij77ya5yc5pww5yyw5rwl6kv55qe5omn6kgm6lh56il">案例三：参数化测试的执行过程</h1>
<p>在使用 GoogleTest（gtest）进行参数化测试时，可以通过从文件中读取测试用例并将其传递给参数化测试的方式来加载测试数据。这通常涉及以下步骤：</p>
<ol>
<li><p><strong>编写测试数据文件</strong>：创建一个包含测试用例的文件，通常使用CSV或JSON格式。文件内容应该能够被程序轻松解析。</p>
</li>
<li><p><strong>读取文件并解析数据</strong>：使用C++代码读取文件内容并解析为所需的结构，例如一个向量或其他容器，以便用作测试数据。</p>
</li>
<li><p><strong>自定义参数生成器</strong>：为GoogleTest的参数化测试定义一个自定义参数生成器函数。这个函数将读取文件内容并返回一个表示测试参数的容器（如<code>std::vector</code>）。</p>
</li>
<li><p><strong>使用</strong><code>INSTANTIATE_TEST_SUITE_P</code>宏：使用<code>INSTANTIATE_TEST_SUITE_P</code>宏将自定义参数生成器绑定到测试用例。</p>
</li>
</ol>
<p>以下是一个示例，演示如何从文件加载CSV格式的测试用例：</p>
<h3 id="heading-56s65l6l5luj56cb">示例代码</h3>
<h4 id="heading-1csvtestcasescsv">步骤1：准备CSV测试数据文件（<code>test_cases.csv</code>）</h4>
<pre><code class="lang-python">input,expected_output
<span class="hljs-number">1</span>,<span class="hljs-number">2</span>
<span class="hljs-number">2</span>,<span class="hljs-number">3</span>
<span class="hljs-number">3</span>,<span class="hljs-number">4</span>
</code></pre>
<h4 id="heading-2">步骤2：读取文件并解析数据</h4>
<pre><code class="lang-cpp"><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;gtest/gtest.h&gt;</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;fstream&gt;</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;sstream&gt;</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;vector&gt;</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;string&gt;</span></span>

<span class="hljs-comment">// 定义一个结构来表示单个测试用例</span>
<span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">TestCase</span> {</span>
    <span class="hljs-keyword">int</span> input;
    <span class="hljs-keyword">int</span> expected_output;
};

<span class="hljs-comment">// 从CSV文件加载测试用例</span>
<span class="hljs-function"><span class="hljs-built_in">std</span>::<span class="hljs-built_in">vector</span>&lt;TestCase&gt; <span class="hljs-title">LoadTestCasesFromFile</span><span class="hljs-params">(<span class="hljs-keyword">const</span> <span class="hljs-built_in">std</span>::<span class="hljs-built_in">string</span>&amp; filename)</span> </span>{
    <span class="hljs-built_in">std</span>::<span class="hljs-built_in">vector</span>&lt;TestCase&gt; test_cases;
    <span class="hljs-function"><span class="hljs-built_in">std</span>::ifstream <span class="hljs-title">file</span><span class="hljs-params">(filename)</span></span>;
    <span class="hljs-built_in">std</span>::<span class="hljs-built_in">string</span> line;

    <span class="hljs-comment">// 跳过CSV头行</span>
    <span class="hljs-built_in">std</span>::getline(file, line);

    <span class="hljs-keyword">while</span> (<span class="hljs-built_in">std</span>::getline(file, line)) {
        <span class="hljs-function"><span class="hljs-built_in">std</span>::<span class="hljs-built_in">stringstream</span> <span class="hljs-title">ss</span><span class="hljs-params">(line)</span></span>;
        <span class="hljs-built_in">std</span>::<span class="hljs-built_in">string</span> input_str, expected_output_str;

        <span class="hljs-built_in">std</span>::getline(ss, input_str, <span class="hljs-string">','</span>);
        <span class="hljs-built_in">std</span>::getline(ss, expected_output_str, <span class="hljs-string">','</span>);

        TestCase test_case;
        test_case.input = <span class="hljs-built_in">std</span>::stoi(input_str);
        test_case.expected_output = <span class="hljs-built_in">std</span>::stoi(expected_output_str);
        test_cases.push_back(test_case);
    }

    <span class="hljs-keyword">return</span> test_cases;
}
</code></pre>
<h4 id="heading-3-1">步骤3：定义参数化测试</h4>
<pre><code class="lang-cpp"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyParamTest</span> :</span> <span class="hljs-keyword">public</span> ::testing::TestWithParam&lt;TestCase&gt; {
};

TEST_P(MyParamTest, TestFunction) {
    TestCase test_case = GetParam();
    <span class="hljs-comment">// 假设有一个函数叫做MyFunction</span>
    <span class="hljs-keyword">int</span> result = MyFunction(test_case.input);
    EXPECT_EQ(result, test_case.expected_output);
}
</code></pre>
<h4 id="heading-4-1">步骤4：实例化参数化测试</h4>
<pre><code class="lang-cpp">INSTANTIATE_TEST_SUITE_P(
    FromFile,
    MyParamTest,
    ::testing::ValuesIn(LoadTestCasesFromFile(<span class="hljs-string">"test_cases.csv"</span>))
);
</code></pre>
<h3 id="heading-6kej6yek-1">解释</h3>
<ul>
<li><p><code>LoadTestCasesFromFile</code>：读取CSV文件并将每行解析为一个<code>TestCase</code>对象。</p>
</li>
<li><p><code>TEST_P</code>：定义参数化测试的测试体。</p>
</li>
<li><p><code>INSTANTIATE_TEST_SUITE_P</code>：实例化参数化测试，使用<code>ValuesIn</code>从文件中加载测试数据。</p>
</li>
</ul>
<p>通过这种方式，你可以从文件加载测试用例，并使用GoogleTest的参数化测试功能来进行测试。</p>
<p>下面是将上述代码整合到一个完整的 C++ 文件中的示例。这段代码演示了如何使用 GoogleTest 的参数化测试从文件加载测试用例，并进行测试。</p>
<h3 id="heading-maincpp">完整示例代码（<code>main.cpp</code>）</h3>
<pre><code class="lang-cpp"><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;gtest/gtest.h&gt;</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;fstream&gt;</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;sstream&gt;</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;vector&gt;</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;string&gt;</span></span>

<span class="hljs-comment">// 定义一个结构来表示单个测试用例</span>
<span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">TestCase</span> {</span>
    <span class="hljs-keyword">int</span> input;
    <span class="hljs-keyword">int</span> expected_output;
};

<span class="hljs-comment">// 假设要测试的函数</span>
<span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">MyFunction</span><span class="hljs-params">(<span class="hljs-keyword">int</span> x)</span> </span>{
    <span class="hljs-keyword">return</span> x + <span class="hljs-number">1</span>; <span class="hljs-comment">// 示例实现</span>
}

<span class="hljs-comment">// 从CSV文件加载测试用例</span>
<span class="hljs-function"><span class="hljs-built_in">std</span>::<span class="hljs-built_in">vector</span>&lt;TestCase&gt; <span class="hljs-title">LoadTestCasesFromFile</span><span class="hljs-params">(<span class="hljs-keyword">const</span> <span class="hljs-built_in">std</span>::<span class="hljs-built_in">string</span>&amp; filename)</span> </span>{
    <span class="hljs-built_in">std</span>::<span class="hljs-built_in">vector</span>&lt;TestCase&gt; test_cases;
    <span class="hljs-function"><span class="hljs-built_in">std</span>::ifstream <span class="hljs-title">file</span><span class="hljs-params">(filename)</span></span>;
    <span class="hljs-built_in">std</span>::<span class="hljs-built_in">string</span> line;

    <span class="hljs-comment">// 检查文件是否成功打开</span>
    <span class="hljs-keyword">if</span> (!file.is_open()) {
        <span class="hljs-built_in">std</span>::<span class="hljs-built_in">cerr</span> &lt;&lt; <span class="hljs-string">"Unable to open file: "</span> &lt;&lt; filename &lt;&lt; <span class="hljs-built_in">std</span>::<span class="hljs-built_in">endl</span>;
        <span class="hljs-keyword">return</span> test_cases;
    }

    <span class="hljs-comment">// 跳过CSV头行</span>
    <span class="hljs-built_in">std</span>::getline(file, line);

    <span class="hljs-keyword">while</span> (<span class="hljs-built_in">std</span>::getline(file, line)) {
        <span class="hljs-function"><span class="hljs-built_in">std</span>::<span class="hljs-built_in">stringstream</span> <span class="hljs-title">ss</span><span class="hljs-params">(line)</span></span>;
        <span class="hljs-built_in">std</span>::<span class="hljs-built_in">string</span> input_str, expected_output_str;

        <span class="hljs-built_in">std</span>::getline(ss, input_str, <span class="hljs-string">','</span>);
        <span class="hljs-built_in">std</span>::getline(ss, expected_output_str, <span class="hljs-string">','</span>);

        TestCase test_case;
        test_case.input = <span class="hljs-built_in">std</span>::stoi(input_str);
        test_case.expected_output = <span class="hljs-built_in">std</span>::stoi(expected_output_str);
        test_cases.push_back(test_case);
    }

    <span class="hljs-keyword">return</span> test_cases;
}

<span class="hljs-comment">// 定义参数化测试类</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyParamTest</span> :</span> <span class="hljs-keyword">public</span> ::testing::TestWithParam&lt;TestCase&gt; {
};

TEST_P(MyParamTest, TestFunction) {
    TestCase test_case = GetParam();
    <span class="hljs-keyword">int</span> result = MyFunction(test_case.input);
    EXPECT_EQ(result, test_case.expected_output);
}

<span class="hljs-comment">// 实例化参数化测试</span>
INSTANTIATE_TEST_SUITE_P(
    FromFile,
    MyParamTest,
    ::testing::ValuesIn(LoadTestCasesFromFile(<span class="hljs-string">"test_cases.csv"</span>))
);

<span class="hljs-comment">// 主函数：运行所有测试</span>
<span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">main</span><span class="hljs-params">(<span class="hljs-keyword">int</span> argc, <span class="hljs-keyword">char</span> **argv)</span> </span>{
    ::testing::InitGoogleTest(&amp;argc, argv);
    <span class="hljs-keyword">return</span> RUN_ALL_TESTS();
}
</code></pre>
<h3 id="heading-57yw6kr5zkm6lq6kgm">编译和运行</h3>
<ol>
<li><p><strong>准备测试数据文件</strong>：在与<code>main.cpp</code>同一目录下创建一个名为<code>test_cases.csv</code>的文件，内容如下：</p>
<pre><code class="lang-python"> input,expected_output
 <span class="hljs-number">1</span>,<span class="hljs-number">2</span>
 <span class="hljs-number">2</span>,<span class="hljs-number">3</span>
 <span class="hljs-number">3</span>,<span class="hljs-number">4</span>
</code></pre>
</li>
<li><p><strong>编译代码</strong>：确保你已经安装了GoogleTest库，并使用以下命令编译代码：</p>
<pre><code class="lang-bash"> g++ -std=c++11 -isystem /path/to/googletest/include -pthread main.cpp -L/path/to/googletest/lib -lgtest -lgtest_main -o test_executable
</code></pre>
<p> 请将<code>/path/to/googletest/include</code>和<code>/path/to/googletest/lib</code>替换为你本地GoogleTest库的实际路径。</p>
</li>
<li><p><strong>运行测试</strong>：编译成功后，运行生成的可执行文件：</p>
<pre><code class="lang-bash"> ./test_executable
</code></pre>
<p> 你应该会看到类似于以下的测试输出：</p>
<pre><code class="lang-python"> [==========] Running <span class="hljs-number">3</span> tests <span class="hljs-keyword">from</span> <span class="hljs-number">1</span> test suite.
 [----------] Global test environment set-up.
 [----------] <span class="hljs-number">3</span> tests <span class="hljs-keyword">from</span> FromFile/MyParamTest
 [ RUN      ] FromFile/MyParamTest.TestFunction/<span class="hljs-number">0</span>
 [       OK ] FromFile/MyParamTest.TestFunction/<span class="hljs-number">0</span> (<span class="hljs-number">0</span> ms)
 [ RUN      ] FromFile/MyParamTest.TestFunction/<span class="hljs-number">1</span>
 [       OK ] FromFile/MyParamTest.TestFunction/<span class="hljs-number">1</span> (<span class="hljs-number">0</span> ms)
 [ RUN      ] FromFile/MyParamTest.TestFunction/<span class="hljs-number">2</span>
 [       OK ] FromFile/MyParamTest.TestFunction/<span class="hljs-number">2</span> (<span class="hljs-number">0</span> ms)
 [----------] <span class="hljs-number">3</span> tests <span class="hljs-keyword">from</span> FromFile/MyParamTest (<span class="hljs-number">0</span> ms total)

 [----------] Global test environment tear-down
 [==========] <span class="hljs-number">3</span> tests <span class="hljs-keyword">from</span> <span class="hljs-number">1</span> test suite ran. (<span class="hljs-number">0</span> ms total)
 [  PASSED  ] <span class="hljs-number">3</span> tests.
</code></pre>
</li>
</ol>
<p>这样，你就完成了一个完整的、可以从文件加载测试用例的 GoogleTest 参数化测试的示例。</p>
<p><code>INSTANTIATE_TEST_SUITE_P</code> 宏的执行是在 <code>main</code> 函数之前完成的。具体来说，<code>INSTANTIATE_TEST_SUITE_P</code> 在编译期生成一组测试用例，并在程序启动时进行初始化。这意味着在进入 <code>main</code> 函数之前，GoogleTest 会初始化所有测试套件和测试用例。</p>
<h3 id="heading-6km57ug6kej6yek">详细解释</h3>
<p>在 C++ 中，<code>INSTANTIATE_TEST_SUITE_P</code> 宏定义一个全局的测试用例实例化结构，该结构在程序加载时会自动初始化。因此，这个宏的执行顺序如下：</p>
<ol>
<li><p><strong>编译期生成测试代码</strong>：在编译期，<code>INSTANTIATE_TEST_SUITE_P</code> 宏会生成所有参数化测试的代码，并将这些测试用例添加到 GoogleTest 的测试注册表中。</p>
</li>
<li><p><strong>程序启动时初始化</strong>：当程序运行时（在进入 <code>main</code> 函数之前），所有全局或静态变量和对象会被初始化，包括由 <code>INSTANTIATE_TEST_SUITE_P</code> 宏生成的测试用例。这是因为 GoogleTest 会在 <code>main</code> 函数执行之前注册所有的测试。</p>
</li>
<li><p><strong>运行</strong> <code>main</code> 函数：在测试用例注册和初始化完成后，<code>main</code> 函数才会被调用。在 <code>main</code> 函数中，<code>::testing::InitGoogleTest(&amp;argc, argv);</code> 会再次初始化 GoogleTest 的运行环境，之后 <code>RUN_ALL_TESTS()</code> 函数会执行所有注册的测试用例。</p>
</li>
</ol>
<h3 id="heading-5luj56cb5omn6kgm6ag65bqp56s65osp">代码执行顺序示意</h3>
<p>以下是一个简化的顺序图，说明了代码执行的顺序：</p>
<ol>
<li><p><strong>全局/静态对象初始化阶段</strong></p>
<ul>
<li><p><code>INSTANTIATE_TEST_SUITE_P</code> 宏生成的代码会在这个阶段执行。</p>
</li>
<li><p>测试用例被注册到 GoogleTest 框架中。</p>
</li>
</ul>
</li>
<li><p><strong>进入</strong> <code>main</code> 函数</p>
<ul>
<li><p>调用 <code>::testing::InitGoogleTest(&amp;argc, argv);</code> 初始化 GoogleTest 的运行环境。</p>
</li>
<li><p>调用 <code>RUN_ALL_TESTS()</code> 执行所有注册的测试用例。</p>
</li>
</ul>
</li>
</ol>
<h3 id="heading-57ut6k66">结论</h3>
<p><code>INSTANTIATE_TEST_SUITE_P</code> 的执行确实发生在 <code>main</code> 函数之前，确保在进入 <code>main</code> 函数时，所有测试用例都已经被正确注册并准备好执行。</p>
]]></content:encoded></item><item><title><![CDATA[如何用RSSHub创建自定义RSS源?]]></title><description><![CDATA[RSSHub 是一个开源的、轻量的 RSS 生成器，它通过定义路由规则来抓取和生成各类网站的 RSS 源。而 RSSHub Radar 是一个浏览器扩展，它可以帮助你快速生成适合当前网页的 RSSHub 路由。
以下是使用 RSSHub Radar 的简要步骤：
安装 RSSHub Radar

安装浏览器扩展：

进入浏览器的扩展商店，搜索并安装 RSSHub Radar 扩展。

RSSHub Radar for Chrome

RSSHub Radar for Firefox




使用...]]></description><link>https://blog.wuzhiguo.tech/diy-rss-based-on-rsshub</link><guid isPermaLink="true">https://blog.wuzhiguo.tech/diy-rss-based-on-rsshub</guid><category><![CDATA[diy rss]]></category><category><![CDATA[rsshub]]></category><category><![CDATA[rss]]></category><dc:creator><![CDATA[wuzhiguocarter]]></dc:creator><pubDate>Mon, 29 Jul 2024 00:19:46 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1722212308264/1d225e7a-1135-4bbc-ba05-d7b69e62eb05.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>RSSHub 是一个开源的、轻量的 RSS 生成器，它通过定义路由规则来抓取和生成各类网站的 RSS 源。而 RSSHub Radar 是一个浏览器扩展，它可以帮助你快速生成适合当前网页的 RSSHub 路由。</p>
<p>以下是使用 RSSHub Radar 的简要步骤：</p>
<h3 id="heading-rsshub-radar">安装 RSSHub Radar</h3>
<ol>
<li><p><strong>安装浏览器扩展</strong>：</p>
<ul>
<li><p>进入浏览器的扩展商店，搜索并安装 RSSHub Radar 扩展。</p>
</li>
<li><p><a target="_blank" href="https://chrome.google.com/webstore/detail/rsshub-radar/kefjpfngnndepjbopdmoebkipbgkggaa">RSSHub Radar for Chrome</a></p>
</li>
<li><p><a target="_blank" href="https://addons.mozilla.org/en-US/firefox/addon/rsshub-radar/">RSSHub Radar for Firefox</a></p>
</li>
</ul>
</li>
</ol>
<h3 id="heading-rsshub-radar-rss">使用 RSSHub Radar 生成 RSS 源</h3>
<ol>
<li><p><strong>访问你要监控的网页</strong>：</p>
<ul>
<li>打开浏览器并访问你想要生成 RSS 源的网页。</li>
</ul>
</li>
<li><p><strong>启动 RSSHub Radar</strong>：</p>
<ul>
<li>在网页加载完成后，点击浏览器工具栏上的 RSSHub Radar 图标。它会自动检测该网页是否支持 RSSHub 路由规则。</li>
</ul>
</li>
<li><p><strong>选择合适的路由规则</strong>：</p>
<ul>
<li>RSSHub Radar 会列出该网页支持的所有 RSSHub 路由规则。选择适合你的路由规则，点击生成对应的 RSS 源链接。</li>
</ul>
</li>
<li><p><strong>订阅生成的 RSS 源</strong>：</p>
<ul>
<li>复制生成的 RSS 源链接，并在你喜欢的 RSS 阅读器中订阅。</li>
</ul>
</li>
</ol>
<h3 id="heading-56s65l6l">示例</h3>
<p>假设你想监控某个新闻网站的特定栏目，可以按照以下步骤进行：</p>
<ol>
<li><p><strong>打开目标网站的栏目页面</strong>，例如 <a target="_blank" href="https://example.com/news/technology%E3%80%82"><code>https://example.com/news/technology</code>。</a></p>
</li>
<li><p><strong>点击 RSSHub Radar 图标</strong>，查看可用的路由规则。</p>
</li>
<li><p><strong>选择适合的路由规则</strong>，例如 <code>/example/news/:category</code>。</p>
</li>
<li><p><strong>复制生成的 RSS 源链接</strong>，例如 <a target="_blank" href="https://rsshub.app/example/news/technology%E3%80%82"><code>https://rsshub.app/example/news/technology</code>。</a></p>
</li>
<li><p><strong>在 RSS 阅读器中订阅该链接</strong>。</p>
</li>
</ol>
<h3 id="heading-rsshub">自定义 RSSHub 规则</h3>
<p>如果你发现 RSSHub 没有预定义的规则来监控你需要的网站，你可以考虑自己添加新的路由规则。以下是一个基本的步骤：</p>
<ol>
<li><p><strong>Fork RSSHub 仓库</strong>：</p>
<ul>
<li>访问 <a target="_blank" href="https://github.com/DIYgod/RSSHub">RSSHub GitHub 仓库</a> 并 fork 一份到你的账号下。</li>
</ul>
</li>
<li><p><strong>添加新路由规则</strong>：</p>
<ul>
<li><p>根据 <a target="_blank" href="https://docs.rsshub.app/en/">RSSHub 文档</a> 添加新的网站路由规则。</p>
</li>
<li><p>路由规则通常位于 <code>lib/routes/</code> 目录下。</p>
</li>
</ul>
</li>
<li><p><strong>测试你的规则</strong>：</p>
<ul>
<li>本地运行 RSSHub，确保你添加的规则工作正常。</li>
</ul>
</li>
<li><p><strong>提交 Pull Request</strong>：</p>
<ul>
<li>将你的改动提交回原始的 RSSHub 仓库，等待合并。</li>
</ul>
</li>
</ol>
<p>通过这些步骤，你可以轻松地利用 RSSHub 和 RSSHub Radar 来监控网页，并生成 RSS 源，比手动编写脚本要简单得多。</p>
<p>下面是一个详细的示例，展示如何为 RSSHub 添加自定义规则，以生成你需要的 RSS 源。</p>
<h3 id="heading-56s65l6l572r56uz">示例网站</h3>
<p>假设我们要为一个虚构的新闻网站 <a target="_blank" href="http://example.com"><code>example.com</code></a> 开发自定义 RSSHub 规则，该网站有以下页面结构：</p>
<ul>
<li><p><a target="_blank" href="https://example.com/news"><code>https://example.com/news</code></a> - 新闻主页，包含最新新闻列表</p>
</li>
<li><p><a target="_blank" href="https://example.com/news/:category"><code>https://example.com/news/:category</code></a> - 特定分类的新闻列表，例如：<a target="_blank" href="https://example.com/news/technology"><code>https://example.com/news/technology</code></a></p>
</li>
</ul>
<h3 id="heading-5bya5ael5bya5yr">开始开发</h3>
<ol>
<li><p><strong>Fork 和 Clone RSSHub 仓库</strong></p>
<p> 首先，fork <a target="_blank" href="https://github.com/DIYgod/RSSHub">RSSHub 仓库</a> 并将其克隆到本地：</p>
<pre><code class="lang-bash"> git <span class="hljs-built_in">clone</span> https://github.com/&lt;your-username&gt;/RSSHub.git
 <span class="hljs-built_in">cd</span> RSSHub
</code></pre>
</li>
<li><p><strong>安装依赖</strong></p>
<p> 安装项目依赖：</p>
<pre><code class="lang-bash"> npm install
</code></pre>
</li>
<li><p><strong>创建新路由文件</strong></p>
<p> 在 <code>lib/routes/</code> 目录下为你的目标网站创建一个新的目录，例如 <code>example</code>，并在其中创建一个 <code>news.js</code> 文件：</p>
<pre><code class="lang-bash"> mkdir lib/routes/example
 touch lib/routes/example/news.js
</code></pre>
</li>
<li><p><strong>编写路由规则</strong></p>
<p> 编辑 <code>news.js</code> 文件，添加以下内容：</p>
<pre><code class="lang-javascript"> <span class="hljs-keyword">const</span> got = <span class="hljs-built_in">require</span>(<span class="hljs-string">'@/utils/got'</span>);
 <span class="hljs-keyword">const</span> cheerio = <span class="hljs-built_in">require</span>(<span class="hljs-string">'cheerio'</span>);
 <span class="hljs-keyword">const</span> { parseDate } = <span class="hljs-built_in">require</span>(<span class="hljs-string">'@/utils/parse-date'</span>);

 <span class="hljs-built_in">module</span>.exports = <span class="hljs-keyword">async</span> (ctx) =&gt; {
     <span class="hljs-keyword">const</span> category = ctx.params.category || <span class="hljs-string">'latest'</span>;
     <span class="hljs-keyword">const</span> url = <span class="hljs-string">`https://example.com/news/<span class="hljs-subst">${category}</span>`</span>;
     <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> got(url);
     <span class="hljs-keyword">const</span> $ = cheerio.load(response.data);

     <span class="hljs-keyword">const</span> list = $(<span class="hljs-string">'.news-item'</span>).map(<span class="hljs-function">(<span class="hljs-params">_, item</span>) =&gt;</span> {
         item = $(item);
         <span class="hljs-keyword">const</span> title = item.find(<span class="hljs-string">'.news-title'</span>).text();
         <span class="hljs-keyword">const</span> link = item.find(<span class="hljs-string">'.news-title a'</span>).attr(<span class="hljs-string">'href'</span>);
         <span class="hljs-keyword">const</span> pubDate = parseDate(item.find(<span class="hljs-string">'.news-date'</span>).text());

         <span class="hljs-keyword">return</span> {
             title,
             link,
             pubDate,
         };
     }).get();

     ctx.state.data = {
         <span class="hljs-attr">title</span>: <span class="hljs-string">`Example News - <span class="hljs-subst">${category}</span>`</span>,
         <span class="hljs-attr">link</span>: url,
         <span class="hljs-attr">item</span>: list,
     };
 };
</code></pre>
<p> 这里我们使用 <code>got</code> 来获取网页内容，使用 <code>cheerio</code> 来解析 HTML，并提取新闻标题、链接和发布日期。</p>
</li>
<li><p><strong>注册路由</strong></p>
<p> 编辑 <code>lib/router.js</code> 文件，添加你的新路由：</p>
<pre><code class="lang-javascript"> <span class="hljs-built_in">module</span>.exports = <span class="hljs-function">(<span class="hljs-params">router</span>) =&gt;</span> {
     router.get(<span class="hljs-string">'/example/news/:category?'</span>, <span class="hljs-built_in">require</span>(<span class="hljs-string">'./routes/example/news'</span>));
 };
</code></pre>
</li>
<li><p><strong>本地运行 RSSHub</strong></p>
<p> 启动 RSSHub 以测试你的新路由：</p>
<pre><code class="lang-bash"> npm start
</code></pre>
<p> 在浏览器中访问 <a target="_blank" href="http://localhost:1200/example/news/technology%EF%BC%8C%E5%BA%94%E8%AF%A5%E5%8F%AF%E4%BB%A5%E7%9C%8B%E5%88%B0%E7%94%9F%E6%88%90%E7%9A%84"><code>http://localhost:1200/example/news/technology</code>，应该可以看到生成的</a> RSS 源。</p>
</li>
<li><p><strong>提交代码并创建 Pull Request</strong></p>
<p> 如果你的自定义规则工作正常，可以将更改提交并推送到你的 fork 仓库：</p>
<pre><code class="lang-bash"> git add .
 git commit -m <span class="hljs-string">"Add custom RSS rule for example.com news"</span>
 git push origin master
</code></pre>
<p> 然后到 GitHub 上为原始的 RSSHub 仓库创建一个 Pull Request。</p>
</li>
</ol>
<h3 id="heading-5a6m5pw05luj56cb56s65l6l">完整代码示例</h3>
<p><strong>lib/routes/example/news.js</strong></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> got = <span class="hljs-built_in">require</span>(<span class="hljs-string">'@/utils/got'</span>);
<span class="hljs-keyword">const</span> cheerio = <span class="hljs-built_in">require</span>(<span class="hljs-string">'cheerio'</span>);
<span class="hljs-keyword">const</span> { parseDate } = <span class="hljs-built_in">require</span>(<span class="hljs-string">'@/utils/parse-date'</span>);

<span class="hljs-built_in">module</span>.exports = <span class="hljs-keyword">async</span> (ctx) =&gt; {
    <span class="hljs-keyword">const</span> category = ctx.params.category || <span class="hljs-string">'latest'</span>;
    <span class="hljs-keyword">const</span> url = <span class="hljs-string">`https://example.com/news/<span class="hljs-subst">${category}</span>`</span>;
    <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> got(url);
    <span class="hljs-keyword">const</span> $ = cheerio.load(response.data);

    <span class="hljs-keyword">const</span> list = $(<span class="hljs-string">'.news-item'</span>).map(<span class="hljs-function">(<span class="hljs-params">_, item</span>) =&gt;</span> {
        item = $(item);
        <span class="hljs-keyword">const</span> title = item.find(<span class="hljs-string">'.news-title'</span>).text();
        <span class="hljs-keyword">const</span> link = item.find(<span class="hljs-string">'.news-title a'</span>).attr(<span class="hljs-string">'href'</span>);
        <span class="hljs-keyword">const</span> pubDate = parseDate(item.find(<span class="hljs-string">'.news-date'</span>).text());

        <span class="hljs-keyword">return</span> {
            title,
            link,
            pubDate,
        };
    }).get();

    ctx.state.data = {
        <span class="hljs-attr">title</span>: <span class="hljs-string">`Example News - <span class="hljs-subst">${category}</span>`</span>,
        <span class="hljs-attr">link</span>: url,
        <span class="hljs-attr">item</span>: list,
    };
};
</code></pre>
<p><strong>lib/router.js</strong></p>
<pre><code class="lang-javascript"><span class="hljs-built_in">module</span>.exports = <span class="hljs-function">(<span class="hljs-params">router</span>) =&gt;</span> {
    router.get(<span class="hljs-string">'/example/news/:category?'</span>, <span class="hljs-built_in">require</span>(<span class="hljs-string">'./routes/example/news'</span>));
};
</code></pre>
<p>通过这个示例，你可以学习到如何为一个特定的网站添加自定义的 RSS 规则。你可以根据不同网站的结构和需求调整代码，以满足你具体的需求。</p>
]]></content:encoded></item><item><title><![CDATA[专栏预告：打造持续高效的个人输入/输出工作流系统]]></title><description><![CDATA[开篇语
在这个信息爆炸的时代，我们每天都在被无数的资讯包围，微博、微信、博客、书籍……我们不停地输入，却常常感到迷茫和焦虑，觉得自己在知识的海洋中迷失了方向。你是否也曾在书本中找到灵感，却难以转化为实际行动？你是否也曾在脑海中闪现无数创意，却无法将其变成有影响力的作品？
欢迎来到《打造持续高效的个人输入/输出工作流系统》的专栏。在这里，我们将一起探索如何将日常的阅读与学习转化为持续而有意义的输出，如何在信息的洪流中找到属于自己的方向，并最终实现个人成长和职业发展的突破。
1. 引言

专栏概述：...]]></description><link>https://blog.wuzhiguo.tech/effective-personsal-knowledge-management-system</link><guid isPermaLink="true">https://blog.wuzhiguo.tech/effective-personsal-knowledge-management-system</guid><category><![CDATA[持续输出]]></category><category><![CDATA[ 个人成长]]></category><category><![CDATA[ 输入/输出工作流]]></category><category><![CDATA[ 知识管理]]></category><category><![CDATA[时间管理]]></category><category><![CDATA[Personal growth  ]]></category><category><![CDATA[personal knowledge management]]></category><category><![CDATA[Time management]]></category><dc:creator><![CDATA[wuzhiguocarter]]></dc:creator><pubDate>Sun, 28 Jul 2024 14:25:42 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1722178586617/f27e29ff-128f-4c34-971e-2f31c684473f.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3 id="heading-5bya56h6kt">开篇语</h3>
<p>在这个信息爆炸的时代，我们每天都在被无数的资讯包围，微博、微信、博客、书籍……我们不停地输入，却常常感到迷茫和焦虑，觉得自己在知识的海洋中迷失了方向。你是否也曾在书本中找到灵感，却难以转化为实际行动？你是否也曾在脑海中闪现无数创意，却无法将其变成有影响力的作品？</p>
<p>欢迎来到《打造持续高效的个人输入/输出工作流系统》的专栏。在这里，我们将一起探索如何将日常的阅读与学习转化为持续而有意义的输出，如何在信息的洪流中找到属于自己的方向，并最终实现个人成长和职业发展的突破。</p>
<h3 id="heading-1">1. 引言</h3>
<ul>
<li><p><strong>专栏概述</strong>：介绍专栏的目标和读者能从中学到什么。</p>
</li>
<li><p><strong>持续输出的重要性</strong>：简述为什么持续输出对个人成长和职业发展至关重要。</p>
</li>
</ul>
<h3 id="heading-2">2. 为什么要持续输出？</h3>
<ul>
<li><p><strong>个人成长</strong>：通过持续输出，强化所学知识，提升技能。</p>
</li>
<li><p><strong>职业发展</strong>：建立个人品牌，增强影响力。</p>
</li>
<li><p><strong>内化知识</strong>：将学到的知识通过输出转化为自身的能力。</p>
</li>
</ul>
<h3 id="heading-3">3. 从输入到输出的挑战</h3>
<ul>
<li><p><strong>输入的多样性与碎片化</strong>：日常阅读的内容多样且碎片化，难以形成系统的知识体系。</p>
</li>
<li><p><strong>输出的高门槛</strong>：从阅读到产出高质量内容之间的难度较大，需要综合多种能力。</p>
</li>
<li><p><strong>时间管理</strong>：在繁忙的日常生活中，如何有效分配时间进行输入和输出。</p>
</li>
</ul>
<h3 id="heading-4-gap">4. 如何填补输入与输出之间的gap</h3>
<ul>
<li><p><strong>有目的的输入</strong>：选择与自己目标相关的内容进行阅读，避免盲目追求广度。</p>
</li>
<li><p><strong>笔记与总结</strong>：通过记笔记和定期总结，将零散的信息系统化。</p>
</li>
<li><p><strong>复盘与反思</strong>：定期回顾自己的学习和输出，找出不足之处，持续改进。</p>
</li>
<li><p><strong>实践与应用</strong>：将学到的知识尽快应用到实际项目中，通过实践检验和巩固。</p>
</li>
</ul>
<h3 id="heading-5">5. 高效输入策略</h3>
<ul>
<li><p><strong>主动阅读</strong>：带着问题去阅读，寻找答案，而不是被动接受信息。</p>
</li>
<li><p><strong>多渠道获取信息</strong>：书籍、博客、播客、在线课程等多种形式结合，丰富知识来源。</p>
</li>
<li><p><strong>知识管理工具</strong>：使用Evernote、Notion等工具整理和管理学习资料。</p>
</li>
</ul>
<h3 id="heading-6">6. 高效输出策略</h3>
<ul>
<li><p><strong>制定输出计划</strong>：明确自己的输出目标和计划，逐步实现。</p>
</li>
<li><p><strong>多样化输出形式</strong>：写作、演讲、制作视频等，多种形式相结合。</p>
</li>
<li><p><strong>时间管理技巧</strong>：利用番茄工作法、GTD等方法，提高时间利用率。</p>
</li>
</ul>
<h3 id="heading-7">7. 实践案例分享</h3>
<ul>
<li><p><strong>个人案例</strong>：分享自己或他人在打造个人输入/输出工作流系统中的成功经验和教训。</p>
</li>
<li><p><strong>工具推荐</strong>：介绍一些常用的生产力工具和技巧。</p>
</li>
</ul>
<h3 id="heading-8">8. 结语</h3>
<ul>
<li><p><strong>持续优化</strong>：工作流系统是动态的，需要不断调整和优化。</p>
</li>
<li><p><strong>激励与坚持</strong>：鼓励读者坚持下去，持续改进自己。</p>
</li>
</ul>
<p>通过这个结构，你可以系统地探讨如何建立一个高效、持续的个人输入/输出工作流系统，帮助读者提高生产力，实现个人和职业目标。</p>
<p>In this era of information explosion, we are surrounded by countless pieces of information every day—Weibo, WeChat, blogs, books... We keep absorbing information but often feel confused and anxious, feeling lost in the ocean of knowledge. Have you ever found inspiration in books but found it difficult to turn it into action? Have you ever had countless ideas flashing through your mind but couldn't turn them into impactful works?</p>
<p>Welcome to the column "Building a Sustainable and Efficient Personal Input/Output Workflow System." Here, we will explore together how to transform daily reading and learning into continuous and meaningful output, how to find your own direction in the flood of information, and ultimately achieve breakthroughs in personal growth and career development.</p>
<h3 id="heading-1-introduction">1. Introduction</h3>
<ul>
<li><p><strong>Column Overview</strong>: Introduce the goals of the column and what readers can learn from it.</p>
</li>
<li><p><strong>Importance of Continuous Output</strong>: Briefly explain why continuous output is crucial for personal growth and career development.</p>
</li>
</ul>
<h3 id="heading-2-why-continuous-output">2. Why Continuous Output?</h3>
<ul>
<li><p><strong>Personal Growth</strong>: Strengthen learned knowledge and improve skills through continuous output.</p>
</li>
<li><p><strong>Career Development</strong>: Build a personal brand and enhance influence.</p>
</li>
<li><p><strong>Internalize Knowledge</strong>: Transform learned knowledge into personal abilities through output.</p>
</li>
</ul>
<h3 id="heading-3-challenges-from-input-to-output">3. Challenges from Input to Output</h3>
<ul>
<li><p><strong>Diversity and Fragmentation of Input</strong>: The content of daily reading is diverse and fragmented, making it difficult to form a systematic knowledge system.</p>
</li>
<li><p><strong>High Threshold for Output</strong>: The difficulty of producing high-quality content from reading requires a combination of various abilities.</p>
</li>
<li><p><strong>Time Management</strong>: How to effectively allocate time for input and output in a busy daily life.</p>
</li>
</ul>
<h3 id="heading-4-how-to-bridge-the-gap-between-input-and-output">4. How to Bridge the Gap Between Input and Output</h3>
<ul>
<li><p><strong>Purposeful Input</strong>: Choose content related to your goals for reading, avoiding blindly pursuing breadth.</p>
</li>
<li><p><strong>Note-taking and Summarizing</strong>: Systematize scattered information through note-taking and regular summarization.</p>
</li>
<li><p><strong>Review and Reflection</strong>: Regularly review your learning and output, identify shortcomings, and continuously improve.</p>
</li>
<li><p><strong>Practice and Application</strong>: Apply learned knowledge to actual projects as soon as possible, testing and consolidating through practice.</p>
</li>
</ul>
<h3 id="heading-5-efficient-input-strategies">5. Efficient Input Strategies</h3>
<ul>
<li><p><strong>Active Reading</strong>: Read with questions in mind, seeking answers rather than passively accepting information.</p>
</li>
<li><p><strong>Multi-channel Information Acquisition</strong>: Combine various forms such as books, blogs, podcasts, and online courses to enrich knowledge sources.</p>
</li>
<li><p><strong>Knowledge Management Tools</strong>: Use tools like Evernote and Notion to organize and manage learning materials.</p>
</li>
</ul>
<h3 id="heading-6-efficient-output-strategies">6. Efficient Output Strategies</h3>
<ul>
<li><p><strong>Develop an Output Plan</strong>: Clarify your output goals and plans, and achieve them step by step.</p>
</li>
<li><p><strong>Diversified Output Forms</strong>: Combine various forms such as writing, speaking, and video production.</p>
</li>
<li><p><strong>Time Management Techniques</strong>: Use methods like the Pomodoro Technique and GTD to improve time utilization.</p>
</li>
</ul>
<h3 id="heading-7-practical-case-sharing">7. Practical Case Sharing</h3>
<ul>
<li><p><strong>Personal Cases</strong>: Share successful experiences and lessons learned in building a personal input/output workflow system.</p>
</li>
<li><p><strong>Tool Recommendations</strong>: Introduce some commonly used productivity tools and techniques.</p>
</li>
</ul>
<h3 id="heading-8-conclusion">8. Conclusion</h3>
<ul>
<li><p><strong>Continuous Optimization</strong>: The workflow system is dynamic and needs constant adjustment and optimization.</p>
</li>
<li><p><strong>Encouragement and Persistence</strong>: Encourage readers to persist and continuously improve themselves.</p>
</li>
</ul>
<p>Through this structure, you can systematically explore how to establish an efficient and sustainable personal input/output workflow system, helping readers improve productivity and achieve personal and career goals.</p>
]]></content:encoded></item><item><title><![CDATA[专栏预告：编程语言背后的编程范式]]></title><description><![CDATA[在编程的世界里，语言就像是工具箱中的各种工具，每一种都有其独特的用途和优势。为什么我们需要这么多不同的编程语言？它们背后隐藏着怎样的编程范式？在这个专栏中，我们将深入探讨编程语言的多样性、历史背景、相互交互以及未来的发展趋势。无论你是编程新手还是经验丰富的开发者，这个专栏都将为你揭开编程语言背后的奥秘，帮助你更好地理解和选择适合自己的编程工具。准备好了吗？让我们一起踏上这段编程语言的探索之旅吧！
引言

专栏介绍

目标读者与预期收益

编程语言的重要性与多样性


第一章：为什么不能只有一门编...]]></description><link>https://blog.wuzhiguo.tech/the-programming-paradigm-behind-programming-languages</link><guid isPermaLink="true">https://blog.wuzhiguo.tech/the-programming-paradigm-behind-programming-languages</guid><category><![CDATA[编程语言]]></category><category><![CDATA[编程范式]]></category><category><![CDATA[编程思想]]></category><category><![CDATA[programming thinking]]></category><category><![CDATA[Programming paradigms]]></category><category><![CDATA[programming languages]]></category><category><![CDATA[transpiler]]></category><dc:creator><![CDATA[wuzhiguocarter]]></dc:creator><pubDate>Sun, 28 Jul 2024 03:55:21 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1722167414923/f2d9ae92-f529-4fde-a048-25b0f806b2e8.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><img src="https://static001.geekbang.org/resource/image/9d/8d/9d6ac4820cc070a6b567d3f514d9ea8d.png?wh=1502*1125" alt /></p>
<p>在编程的世界里，语言就像是工具箱中的各种工具，每一种都有其独特的用途和优势。为什么我们需要这么多不同的编程语言？它们背后隐藏着怎样的编程范式？在这个专栏中，我们将深入探讨编程语言的多样性、历史背景、相互交互以及未来的发展趋势。无论你是编程新手还是经验丰富的开发者，这个专栏都将为你揭开编程语言背后的奥秘，帮助你更好地理解和选择适合自己的编程工具。准备好了吗？让我们一起踏上这段编程语言的探索之旅吧！</p>
<h4 id="heading-5byv6kia">引言</h4>
<ol>
<li><p>专栏介绍</p>
</li>
<li><p>目标读者与预期收益</p>
</li>
<li><p>编程语言的重要性与多样性</p>
</li>
</ol>
<h4 id="heading-56ys5lia56ug77ya5li65lua5lmi5lin6io95yq5pyj5lia6zeo57yw56il6kt6kia77yf">第一章：为什么不能只有一门编程语言？</h4>
<ol>
<li><p><strong>多样性与专门化</strong></p>
<ul>
<li><p>语言的多样性如何促进创新与效率</p>
</li>
<li><p>不同语言为不同领域和问题提供优化解决方案</p>
</li>
</ul>
</li>
<li><p><strong>历史背景与技术限制</strong></p>
<ul>
<li><p>早期编程语言的诞生与发展</p>
</li>
<li><p>硬件、操作系统与编程语言的关系</p>
</li>
</ul>
</li>
</ol>
<h4 id="heading-56ys5lqm56ug77ya6io95zcm5bcg5oma5pyj57yw56il6kt6kia55qe5lyy54k55pw05zci5yiw5lia6zeo57yw56il6kt6kia5lit77yf">第二章：能否将所有编程语言的优点整合到一门编程语言中？</h4>
<ol>
<li><p><strong>编程范式概述</strong></p>
<ul>
<li><p>过程式编程</p>
</li>
<li><p>面向对象编程</p>
</li>
<li><p>函数式编程</p>
</li>
<li><p>逻辑编程</p>
</li>
</ul>
</li>
<li><p><strong>编程语言的发展简史</strong></p>
<ul>
<li><p>早期编程语言（如FORTRAN、COBOL）的出现</p>
</li>
<li><p>面向对象编程语言的崛起（如C++、Java）</p>
</li>
<li><p>函数式编程语言的发展（如Lisp、Haskell）</p>
</li>
<li><p>现代编程语言的多范式特点（如Python、Scala、 Rust）</p>
</li>
</ul>
</li>
<li><p><strong>能否将所有编程范式整合到一门编程语言中？</strong></p>
<ul>
<li><p>多范式编程语言的出现（如Scala、Rust）</p>
</li>
<li><p>优势与挑战</p>
</li>
</ul>
</li>
</ol>
<h4 id="heading-56ys5lij56ug77ya5lin5zcm55qe57yw56il6kt6kia5aac5l2v5lqk5lqs77yf">第三章：不同的编程语言如何交互？</h4>
<ol>
<li><p><strong>什么是图灵完备性？</strong></p>
<ul>
<li><p>图灵完备性定义</p>
</li>
<li><p>图灵机与计算理论基础</p>
</li>
</ul>
</li>
<li><p><strong>图灵完备的语言具有什么特性？</strong></p>
<ul>
<li><p>控制结构（如循环、条件分支）</p>
</li>
<li><p>数据操作（如变量、函数）</p>
</li>
</ul>
</li>
<li><p><strong>不同编程语言如何交互？</strong></p>
<ul>
<li><p>语言互操作性的重要性</p>
</li>
<li><p>现有工具与框架（如FFI、语言桥接工具）</p>
<ul>
<li><p>序列化与反序列化（如JSON、XML）</p>
</li>
<li><p>API和库的使用</p>
</li>
</ul>
</li>
</ul>
</li>
</ol>
<h4 id="heading-56ys5zub56ug77ya5lin5zcm57yw56il6kt6kia55qe5rqq5luj56cb5aac5l2v55u45lqs6l2s5o2i77yf">第四章：不同编程语言的源代码如何相互转换？</h4>
<ol>
<li><p><strong>编程语言的源代码可以互相转换吗？</strong></p>
<ul>
<li><p>源代码转换的概念</p>
</li>
<li><p>语言间的语法和语义差异</p>
</li>
<li><p>编译器与解释器的角色</p>
</li>
</ul>
</li>
<li><p><strong>如何转换？</strong></p>
<ul>
<li><p>语法树和中间表示</p>
</li>
<li><p>转换过程中的挑战和解决方案</p>
<ul>
<li>实例演示与案例分析（如使用LLVM、Transpiler）</li>
</ul>
</li>
</ul>
</li>
</ol>
<h4 id="heading-56ys5lqu56ug77ya6kab5bya5yr5lia6zeo5paw55qe57yw56il6kt6kia5zcx77yf">第五章：要开发一门新的编程语言吗？</h4>
<ol>
<li><p><strong>什么时候需要开发一门新的编程语言？</strong></p>
<ul>
<li><p>现有语言的局限性</p>
</li>
<li><p>新需求与新技术的推动</p>
</li>
<li><p>实践中的成功案例（如Go、Rust）</p>
</li>
<li><p>开发过程中常见的挑战与解决方案</p>
</li>
</ul>
</li>
<li><p><strong>如何开发一门新的编程语言？</strong></p>
<ul>
<li><p>设计原则与步骤</p>
</li>
<li><p>设计语言语法和语义</p>
</li>
<li><p>实现编译器或解释器</p>
</li>
<li><p>社区和生态系统的建设</p>
</li>
</ul>
</li>
</ol>
<h4 id="heading-kirnu5porroqkg"><strong>结论</strong></h4>
<ol>
<li><p>专栏总结</p>
</li>
<li><p>编程语言未来的发展趋势</p>
</li>
<li><p>对读者的建议与期望</p>
</li>
</ol>
<h4 id="heading-kirpmytlvzuqkg"><strong>附录</strong></h4>
<ol>
<li><p>参考文献与推荐阅读</p>
</li>
<li><p>术语表</p>
</li>
<li><p>常见问题解答 (FAQ)</p>
</li>
</ol>
<p>Column Preview: The Programming Paradigms Behind Programming Languages</p>
<p>Introduction</p>
<ol>
<li><p>Column Introduction</p>
</li>
<li><p>Target Audience and Expected Benefits</p>
</li>
<li><p>The Importance and Diversity of Programming Languages</p>
</li>
</ol>
<p>Chapter 1: Why Can't There Be Just One Programming Language?</p>
<ol>
<li><p><strong>Diversity and Specialization</strong></p>
<ul>
<li><p>How the diversity of languages promotes innovation and efficiency</p>
</li>
<li><p>Different languages provide optimized solutions for different fields and problems</p>
</li>
</ul>
</li>
<li><p><strong>Historical Background and Technical Limitations</strong></p>
<ul>
<li><p>The birth and development of early programming languages</p>
</li>
<li><p>The relationship between hardware, operating systems, and programming languages</p>
</li>
</ul>
</li>
</ol>
<p>Chapter 2: Can All the Advantages of Programming Languages Be Integrated into One Language?</p>
<ol>
<li><p><strong>Overview of Programming Paradigms</strong></p>
<ul>
<li><p>Procedural Programming</p>
</li>
<li><p>Object-Oriented Programming</p>
</li>
<li><p>Functional Programming</p>
</li>
<li><p>Logic Programming</p>
</li>
</ul>
</li>
<li><p><strong>A Brief History of Programming Languages</strong></p>
<ul>
<li><p>The emergence of early programming languages (such as FORTRAN, COBOL)</p>
</li>
<li><p>The rise of object-oriented programming languages (such as C++, Java)</p>
</li>
<li><p>The development of functional programming languages (such as Lisp, Haskell)</p>
</li>
<li><p>The multi-paradigm characteristics of modern programming languages (such as Python, Scala, Rust)</p>
</li>
</ul>
</li>
<li><p><strong>Can All Programming Paradigms Be Integrated into One Language?</strong></p>
<ul>
<li><p>The emergence of multi-paradigm programming languages (such as Scala, Rust)</p>
</li>
<li><p>Advantages and challenges</p>
</li>
</ul>
</li>
</ol>
<p>Chapter 3: How Do Different Programming Languages Interact?</p>
<ol>
<li><p><strong>What is Turing Completeness?</strong></p>
<ul>
<li><p>Definition of Turing Completeness</p>
</li>
<li><p>Turing Machine and the foundation of computation theory</p>
</li>
</ul>
</li>
<li><p><strong>What Characteristics Do Turing Complete Languages Have?</strong></p>
<ul>
<li><p>Control structures (such as loops, conditional branches)</p>
</li>
<li><p>Data operations (such as variables, functions)</p>
</li>
</ul>
</li>
<li><p><strong>How Do Different Programming Languages Interact?</strong></p>
<ul>
<li><p>The importance of language interoperability</p>
</li>
<li><p>Existing tools and frameworks (such as FFI, language bridging tools)</p>
<ul>
<li><p>Serialization and deserialization (such as JSON, XML)</p>
</li>
<li><p>Use of APIs and libraries</p>
</li>
</ul>
</li>
</ul>
</li>
</ol>
<p>Chapter 4: How Can Source Code of Different Programming Languages Be Converted?</p>
<ol>
<li><p><strong>Can Source Code Be Converted Between Programming Languages?</strong></p>
<ul>
<li><p>The concept of source code conversion</p>
</li>
<li><p>Syntax and semantic differences between languages</p>
</li>
<li><p>The role of compilers and interpreters</p>
</li>
</ul>
</li>
<li><p><strong>How to Convert?</strong></p>
<ul>
<li><p>Syntax trees and intermediate representations</p>
</li>
<li><p>Challenges and solutions in the conversion process</p>
<ul>
<li>Demonstrations and case studies (such as using LLVM, Transpiler)</li>
</ul>
</li>
</ul>
</li>
</ol>
<p>Chapter 5: Should You Develop a New Programming Language?</p>
<ol>
<li><p><strong>When Is It Necessary to Develop a New Programming Language?</strong></p>
<ul>
<li><p>Limitations of existing languages</p>
</li>
<li><p>New demands and technological advancements</p>
</li>
<li><p>Successful cases in practice (such as Go, Rust)</p>
</li>
<li><p>Common challenges and solutions in the development process</p>
</li>
</ul>
</li>
<li><p><strong>How to Develop a New Programming Language?</strong></p>
<ul>
<li><p>Design principles and steps</p>
</li>
<li><p>Designing language syntax and semantics</p>
</li>
<li><p>Implementing a compiler or interpreter</p>
</li>
<li><p>Building a community and ecosystem</p>
</li>
</ul>
</li>
</ol>
<p>Conclusion</p>
<ol>
<li><p>Column Summary</p>
</li>
<li><p>Future Trends in Programming Languages</p>
</li>
<li><p>Suggestions and Expectations for Readers</p>
</li>
</ol>
<p>Appendix</p>
<ol>
<li><p>References and Recommended Reading</p>
</li>
<li><p>Glossary</p>
</li>
<li><p>Frequently Asked Questions (FAQ)</p>
</li>
</ol>
]]></content:encoded></item><item><title><![CDATA[我为什么开始坚持写作？]]></title><description><![CDATA[一、自我提升
首先，写作可以记录自己的所闻、所做、所思、所想。
其次，写作在真实记录的基础上，给我一个能够回顾和反思的机会。
然后，经过反思再加工，能够将零散的记录层次化、结构化、系统化。
最后，写作不是一次性写完就放在那了，而是随着时间推移和阅历更加丰富、想法更加成熟，以前写的文章可以进一步修改、完善，这恰好构成了自我提升整个闭环。
二、提升影响力
影响力的本质在于利他。通过对自身经历和认知的抽象总结，可以评估其对他人的帮助程度。借助互联网的传播媒介，我们能够更好地探究这一点。然而，提升影响力...]]></description><link>https://blog.wuzhiguo.tech/why-do-i-start-keep-writing</link><guid isPermaLink="true">https://blog.wuzhiguo.tech/why-do-i-start-keep-writing</guid><category><![CDATA[writing]]></category><category><![CDATA[Self Improvement ]]></category><category><![CDATA[influence]]></category><dc:creator><![CDATA[wuzhiguocarter]]></dc:creator><pubDate>Sun, 28 Jul 2024 02:54:11 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/y02jEX_B0O0/upload/ad6a7005f6444e261d5be7e46537d444.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-5lia44cb6ieq5oir5oq5y2h">一、自我提升</h1>
<p>首先，写作可以记录自己的所闻、所做、所思、所想。</p>
<p>其次，写作在真实记录的基础上，给我一个能够回顾和反思的机会。</p>
<p>然后，经过反思再加工，能够将零散的记录层次化、结构化、<strong>系统化</strong>。</p>
<p>最后，写作不是一次性写完就放在那了，而是随着时间推移和阅历更加丰富、想法更加成熟，以前写的文章可以进一步修改、完善，这恰好构成了<strong>自我提升整个闭环</strong>。</p>
<h1 id="heading-5lqm44cb5oq5y2h5b2x5zon5yqb">二、提升影响力</h1>
<p>影响力的本质在于利他。通过对自身经历和认知的抽象总结，可以评估其对他人的帮助程度。借助互联网的传播媒介，我们能够更好地探究这一点。然而，提升影响力的前提是实现自我提升。如果自身问题尚未解决，所写内容难以令人信服，读者也不会愿意阅读。</p>
<p>当自身问题得到有效解决，并总结出一套经验方法时，公开写作和分享将成为检验这些思想方法是否具有利他价值的试验田。此外，面对不同背景的读者和听众，还能检验自己的语言表达是否存在不足之处。</p>
<p>当你的经验方法被广泛认可和复用，帮助他人解决实际问题时，影响力自然会逐步建立，进而成为某一小众领域的行业权威或意见领袖，并建立个人品牌。此时，可以尝试将自己的输出商业化。</p>
<h1 id="heading-5lij44cb5a6e546w5zwg5lia5lu35yc8">三、实现商业价值</h1>
<p>三步实现你的商业价值：博客写作、建立咨询业务、出版书籍。这三步之间的关系是什么呢？</p>
<h2 id="heading-31">3.1 博客写作</h2>
<p>首先，博客写作，作为例行日常输出，可以快速发布并及时得到反馈和快速迭代。将博客内容免费提供给读者，可以为个人品牌持续引流。这一步不仅能吸引潜在客户，还能帮助你不断完善自己的观点和方法。</p>
<p>内容吸引客户，创造更多内容吸引更多客户，形成无限循环。这有效是因为90-9-1规则：90%的用户是潜伏者，9%点赞和评论，1%创建内容。写文章让你成为前1%的内容创作者，自然成为领导者。</p>
<p><img src="https://www.luxiangdong.com/images/zixun/4.png" alt="img" /></p>
<h2 id="heading-32">3.2 建立咨询业务</h2>
<p>接下来，咨询业务，通过实践不断打磨和泛化自己的方法论。通过与客户的实际互动，你可以验证和改进自己的理论，并积累更多的实际案例和经验。这一步是将理论付诸实践的重要环节。</p>
<p>建立咨询业务需要有一个顾问的身份，如果自己还不是顾问如何建立自己的咨询业务呢？</p>
<p>顾问就是一个领域的专家，创办咨询公司有助于品牌建设，确立权威地位。幸运的是，这比想象中简单，因为有一套可遵循的剧本：</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1722135080316/81fa32b7-5097-4c74-86a1-2364c8a66c96.png" alt class="image--center mx-auto" /></p>
<p>通过以上步骤，你可以逐步建立起自己的品牌，成为行业内的权威，并实现商业价值。</p>
<h2 id="heading-33">3.3 出版书籍</h2>
<p>最后，出版书籍可以将理论和实践系统化输出，扩大受众面，巩固你的专业地位，并覆盖那些对价格敏感的客户，他们可能负担不起咨询服务，但仍然需要你的建议。</p>
<p><img src="https://substackcdn.com/image/fetch/w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3abc400e-f54a-4ae0-b10c-baafe335fca0_686x542.png" alt /></p>
<p>咨询能让你意识到自己的知识和经验的价值，尽管费用高且难以规模化，但书籍作为补充收入，可以覆盖更多客户。通过书籍和咨询，你可以在价格-需求曲线上获得多个收入点，平衡收入的可变性。</p>
<h1 id="heading-5yc6icd">参考</h1>
<ol>
<li><a target="_blank" href="https://medium.com/@_michaellin/stop-building-startups-start-consulting-instead-8c3980d6a214">https://medium.com/@_michaellin/stop-building-startups-start-consulting-instead-8c3980d6a214</a></li>
</ol>
<p>Why did I start writing?</p>
<ol>
<li>Self-Improvement</li>
</ol>
<p>First, writing allows me to record what I hear, do, think, and feel.</p>
<p>Second, writing provides an opportunity to review and reflect on these records.</p>
<p>Then, through reflection and reworking, I can organize scattered records into a more structured and systematic form.</p>
<p>Finally, writing is not a one-time task to be left aside. As time passes and my experiences grow richer and my thoughts mature, I can further revise and improve my previous writings, thus completing the entire cycle of self-improvement.</p>
<ol start="2">
<li>Enhancing Influence</li>
</ol>
<p>The essence of influence lies in benefiting others. By abstracting and summarizing my experiences and insights, I can assess how helpful they are to others. With the help of the internet as a medium, we can better explore this aspect. However, the prerequisite for enhancing influence is achieving self-improvement. If personal issues remain unresolved, the content written will be unconvincing, and readers will be unwilling to read it.</p>
<p>When personal issues are effectively resolved and a set of experiences and methods is summarized, public writing and sharing become a testing ground to see if these ideas and methods have altruistic value. Additionally, facing readers and audiences from different backgrounds can help identify any shortcomings in my language expression.</p>
<p>When your experiences and methods are widely recognized and reused, helping others solve practical problems, influence naturally builds up. You can then become an authority or opinion leader in a niche field and establish a personal brand. At this point, you can try to commercialize your output.</p>
<ol start="3">
<li>Realizing Commercial Value</li>
</ol>
<p>Three steps to realize your commercial value: blogging, establishing a consulting business, and publishing books. What is the relationship between these three steps?</p>
<p>3.1 Blogging</p>
<p>First, blogging, as a routine daily output, allows for quick publication, timely feedback, and rapid iteration. Providing blog content for free to readers can continuously attract traffic to your personal brand. This step not only attracts potential clients but also helps you continuously refine your views and methods.</p>
<p>Content attracts clients, creating more content attracts more clients, forming an infinite loop. This is effective because of the 90-9-1 rule: 90% of users are lurkers, 9% like and comment, and 1% create content. Writing articles makes you part of the top 1% of content creators, naturally becoming a leader.</p>
<p><img src="https://www.luxiangdong.com/images/zixun/4.png" alt="img" /></p>
<p>3.2 Establishing a Consulting Business</p>
<p>Next, consulting business, through practice, continuously refines and generalizes your methodology. Through actual interaction with clients, you can verify and improve your theories and accumulate more practical cases and experiences. This step is crucial for putting theory into practice.</p>
<p>Establishing a consulting business requires having the identity of a consultant. If you are not yet a consultant, how do you establish your consulting business?</p>
<p>A consultant is an expert in a field. Starting a consulting company helps in brand building and establishing authority. Fortunately, this is simpler than imagined because there is a script to follow.</p>
<ul>
<li><p>Step-1 Start a newsletter</p>
</li>
<li><p>Step-2 Get potential clients on your email list</p>
</li>
<li><p>Step-3 Write 10 articles on the topic you want to consult on.</p>
</li>
<li><p>Step-4 Use those articles to sell consulting services</p>
</li>
<li><p>Step-5 Use learnings from your work experience or (ideally) past engagements as content for future articles.</p>
</li>
<li><p>Step-6 Rinse and repeat steps 3-5.</p>
</li>
</ul>
<p><img src="https://substackcdn.com/image/fetch/f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5cdd19e5-ad1e-4584-a2b3-b15b1c3a847a_540x281.png" alt /></p>
<p>Through the above steps, you can gradually build your brand, become an authority in the industry, and realize commercial value.</p>
<p>3.3 Publishing Books</p>
<p>Finally, publishing books can systematically output theory and practice, expand the audience, consolidate your professional status, and cover those price-sensitive clients who may not afford consulting services but still need your advice.</p>
<p><img src="https://substackcdn.com/image/fetch/w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3abc400e-f54a-4ae0-b10c-baafe335fca0_686x542.png" alt /></p>
<p>Consulting makes you aware of the value of your knowledge and experience. Although it is expensive and difficult to scale, books as supplementary income can cover more clients. Through books and consulting, you can achieve multiple income points on the price-demand curve, balancing the variability of income.</p>
]]></content:encoded></item><item><title><![CDATA[专栏预告：系统性能优化系列]]></title><description><![CDATA[本专栏一共包含6个专题，每个专题都涵盖了实际业务中常见的性能优化需求：
专题一：服务器硬件与基础设施优化

硬件升级与选择：讨论不同服务器硬件（CPU、内存、磁盘等）的选择及其对性能的影响。

负载均衡：介绍负载均衡的基本原理、常见方案（如Nginx、HAProxy），以及如何配置和优化。

网络优化：讲解网络延迟、带宽、拓扑结构的优化，以及如何利用CDN提升性能。

操作系统和内核调优：包括Brendan Gregg在操作系统和内核调优方面的研究和实践。


专题二：应用架构设计与优化

分布...]]></description><link>https://blog.wuzhiguo.tech/guide-to-performance-optimization</link><guid isPermaLink="true">https://blog.wuzhiguo.tech/guide-to-performance-optimization</guid><category><![CDATA[性能优化]]></category><category><![CDATA[系统设计]]></category><category><![CDATA[Performance Engirneering]]></category><category><![CDATA[Performance Optimization]]></category><category><![CDATA[System Architecture]]></category><category><![CDATA[System Design]]></category><category><![CDATA[Architecture Design]]></category><category><![CDATA[架构设计]]></category><dc:creator><![CDATA[wuzhiguocarter]]></dc:creator><pubDate>Sun, 28 Jul 2024 02:49:14 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1722148979629/e9752e56-ebd5-4fef-87d6-d8ccfdf0a1ca.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>本专栏一共包含6个专题，每个专题都涵盖了实际业务中常见的性能优化需求：</p>
<h3 id="heading-5lit6aky5lia77ya5pyn5yqh5zmo56gs5lu25lio5z656ga6k65pa95lyy5yyw">专题一：服务器硬件与基础设施优化</h3>
<ol>
<li><p><strong>硬件升级与选择</strong>：讨论不同服务器硬件（CPU、内存、磁盘等）的选择及其对性能的影响。</p>
</li>
<li><p><strong>负载均衡</strong>：介绍负载均衡的基本原理、常见方案（如Nginx、HAProxy），以及如何配置和优化。</p>
</li>
<li><p><strong>网络优化</strong>：讲解网络延迟、带宽、拓扑结构的优化，以及如何利用CDN提升性能。</p>
</li>
<li><p><strong>操作系统和内核调优</strong>：包括Brendan Gregg在操作系统和内核调优方面的研究和实践。</p>
</li>
</ol>
<h3 id="heading-5lit6aky5lqm77ya5bqu55so5p625p6e6k66k6h5lio5lyy5yyw">专题二：应用架构设计与优化</h3>
<ol>
<li><p><strong>分布式系统与微服务架构</strong>：分析分布式系统和微服务架构的优势与挑战，及其对性能的影响。</p>
</li>
<li><p><strong>缓存策略</strong>：介绍常见缓存技术（如Redis、Memcached），以及如何合理使用缓存提高性能。</p>
</li>
<li><p><strong>数据库优化</strong>：讲解数据库的分片、索引、查询优化等技术。</p>
</li>
</ol>
<h3 id="heading-5lit6aky5lij77ya5luj56cb5lyy5yyw5lio5pya5l2z5a6e6le1">专题三：代码优化与最佳实践</h3>
<ol>
<li><p><strong>代码审查与重构</strong>：讨论如何通过代码审查发现性能瓶颈，并通过重构优化代码。</p>
</li>
<li><p><strong>高效的并发与异步编程</strong>：介绍并发和异步编程模型，及其在性能优化中的应用。</p>
</li>
<li><p><strong>内存管理</strong>：分析内存泄漏、内存抖动等问题，并提供优化内存使用的技巧，结合C++的内存管理和性能优化。</p>
</li>
<li><p><strong>性能分析与调优工具</strong>：介绍Brendan Gregg的性能分析工具和方法，如DTrace和Flame Graphs。</p>
</li>
</ol>
<h3 id="heading-5lit6aky5zub77ya5ocn6io955ur5o6n5lio5yig5p6q">专题四：性能监控与分析</h3>
<ol>
<li><p><strong>性能监控工具与技术</strong>：介绍常见的性能监控工具（如Prometheus、Grafana、New Relic）及其使用方法。</p>
</li>
<li><p><strong>日志管理与分析</strong>：讲解如何通过日志分析定位性能瓶颈。</p>
</li>
<li><p><strong>性能测试</strong>：讨论性能测试的基本方法和工具（如JMeter、Locust），以及如何设计有效的测试方案。</p>
</li>
</ol>
<h3 id="heading-5lit6aky5lqu77ya5a6j5ywo5lio5ocn6io955qe5bmz6kgh">专题五：安全与性能的平衡</h3>
<ol>
<li><p><strong>安全策略与性能影响</strong>：分析常见安全措施（如加密、认证授权）的性能开销，并提出优化建议。</p>
</li>
<li><p><strong>防火墙与DDoS防护</strong>：介绍防火墙配置和DDoS防护技术对性能的影响及其优化方法。</p>
</li>
<li><p><strong>漏洞修复与补丁管理</strong>：探讨在不影响性能的前提下，如何高效地进行漏洞修复和补丁管理。</p>
</li>
</ol>
<h3 id="heading-5lit6aky5ywt77ya5lqr6k6h566x5lio5a655zmo5yyw5oqa5pyv">专题六：云计算与容器化技术</h3>
<ol>
<li><p><strong>云计算资源管理</strong>：讲解如何合理利用云计算资源（如AWS、Azure）进行性能优化。</p>
</li>
<li><p><strong>容器化与编排</strong>：介绍容器技术（如Docker、Kubernetes）对性能的影响及其优化方法。</p>
</li>
<li><p><strong>无服务器架构</strong>：分析无服务器架构的优势与局限，以及在实际应用中的性能表现。</p>
</li>
</ol>
<p>这些专题涵盖了从硬件到软件、从设计到实施的各个层面的性能优化策略，可以帮助读者全面了解和提升服务器端的性能。</p>
<p>Column Preview: System Performance Optimization Series</p>
<p>This column consists of six topics, each covering common performance optimization needs in actual business scenarios:</p>
<h3 id="heading-topic-1-server-hardware-and-infrastructure-optimization">Topic 1: Server Hardware and Infrastructure Optimization</h3>
<ol>
<li><p><strong>Hardware Upgrades and Selection</strong>: Discuss the selection of different server hardware (CPU, memory, disk, etc.) and their impact on performance.</p>
</li>
<li><p><strong>Load Balancing</strong>: Introduce the basic principles of load balancing, common solutions (such as Nginx, HAProxy), and how to configure and optimize them.</p>
</li>
<li><p><strong>Network Optimization</strong>: Explain the optimization of network latency, bandwidth, and topology, and how to use CDN to improve performance.</p>
</li>
<li><p><strong>Operating System and Kernel Tuning</strong>: Include Brendan Gregg's research and practices in operating system and kernel tuning.</p>
</li>
</ol>
<h3 id="heading-topic-2-application-architecture-design-and-optimization">Topic 2: Application Architecture Design and Optimization</h3>
<ol>
<li><p><strong>Distributed Systems and Microservices Architecture</strong>: Analyze the advantages and challenges of distributed systems and microservices architecture, and their impact on performance.</p>
</li>
<li><p><strong>Caching Strategies</strong>: Introduce common caching technologies (such as Redis, Memcached) and how to use caching effectively to improve performance.</p>
</li>
<li><p><strong>Database Optimization</strong>: Explain techniques such as database sharding, indexing, and query optimization.</p>
</li>
</ol>
<h3 id="heading-topic-3-code-optimization-and-best-practices">Topic 3: Code Optimization and Best Practices</h3>
<ol>
<li><p><strong>Code Review and Refactoring</strong>: Discuss how to identify performance bottlenecks through code review and optimize code through refactoring.</p>
</li>
<li><p><strong>Efficient Concurrency and Asynchronous Programming</strong>: Introduce concurrency and asynchronous programming models and their application in performance optimization.</p>
</li>
<li><p><strong>Memory Management</strong>: Analyze issues such as memory leaks and memory jitter, and provide tips for optimizing memory usage, combined with C++ memory management and performance optimization.</p>
</li>
<li><p><strong>Performance Analysis and Tuning Tools</strong>: Introduce Brendan Gregg's performance analysis tools and methods, such as DTrace and Flame Graphs.</p>
</li>
</ol>
<h3 id="heading-topic-4-performance-monitoring-and-analysis">Topic 4: Performance Monitoring and Analysis</h3>
<ol>
<li><p><strong>Performance Monitoring Tools and Techniques</strong>: Introduce common performance monitoring tools (such as Prometheus, Grafana, New Relic) and how to use them.</p>
</li>
<li><p><strong>Log Management and Analysis</strong>: Explain how to locate performance bottlenecks through log analysis.</p>
</li>
<li><p><strong>Performance Testing</strong>: Discuss the basic methods and tools of performance testing (such as JMeter, Locust), and how to design effective test plans.</p>
</li>
</ol>
<h3 id="heading-topic-5-balancing-security-and-performance">Topic 5: Balancing Security and Performance</h3>
<ol>
<li><p><strong>Security Policies and Performance Impact</strong>: Analyze the performance overhead of common security measures (such as encryption, authentication, and authorization) and provide optimization suggestions.</p>
</li>
<li><p><strong>Firewall and DDoS Protection</strong>: Introduce the impact of firewall configuration and DDoS protection technology on performance and their optimization methods.</p>
</li>
<li><p><strong>Vulnerability Patching and Management</strong>: Explore how to efficiently perform vulnerability patching and management without affecting performance.</p>
</li>
</ol>
<h3 id="heading-topic-6-cloud-computing-and-containerization-technology">Topic 6: Cloud Computing and Containerization Technology</h3>
<ol>
<li><p><strong>Cloud Resource Management</strong>: Explain how to use cloud computing resources (such as AWS, Azure) for performance optimization.</p>
</li>
<li><p><strong>Containerization and Orchestration</strong>: Introduce the impact of container technologies (such as Docker, Kubernetes) on performance and their optimization methods.</p>
</li>
<li><p><strong>Serverless Architecture</strong>: Analyze the advantages and limitations of serverless architecture, and its performance in practical applications.</p>
</li>
</ol>
<p>These topics cover performance optimization strategies from hardware to software, from design to implementation, helping readers comprehensively understand and improve server-side performance.</p>
]]></content:encoded></item><item><title><![CDATA[专栏预告：系统架构设计系列]]></title><description><![CDATA[各位读者朋友们，大家好！
我们非常激动地向大家宣布，即将推出全新专栏——“架构设计系列”。这个系列专栏的目标是为软件开发者、系统架构师以及对架构设计感兴趣的专业人士提供一个全面而深入的学习平台。无论你是经验丰富的资深架构师，还是刚刚踏入这一领域的新手，本专栏都将为你提供宝贵的见解与实用的指导。
在“架构设计系列”中，我们将探讨软件架构设计的核心概念、最佳实践以及最新趋势。通过每周更新的文章，我们将涵盖以下主要内容：
系统设计原理

系统设计原理：了解系统设计的基本原则，如何进行需求分析和系统建模...]]></description><link>https://blog.wuzhiguo.tech/system-architecture-design-series</link><guid isPermaLink="true">https://blog.wuzhiguo.tech/system-architecture-design-series</guid><category><![CDATA[Evolutionary Architecture]]></category><category><![CDATA[System Design]]></category><category><![CDATA[System Architecture]]></category><category><![CDATA[Architecture Design]]></category><category><![CDATA[DDD]]></category><category><![CDATA[Microservices]]></category><category><![CDATA[event-driven-architecture]]></category><dc:creator><![CDATA[wuzhiguocarter]]></dc:creator><pubDate>Sat, 27 Jul 2024 14:28:18 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1722167611553/7664d85c-c2bd-451f-ba1c-36a74a32b710.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>各位读者朋友们，大家好！</p>
<p>我们非常激动地向大家宣布，即将推出全新专栏——“架构设计系列”。这个系列专栏的目标是为软件开发者、系统架构师以及对架构设计感兴趣的专业人士提供一个全面而深入的学习平台。无论你是经验丰富的资深架构师，还是刚刚踏入这一领域的新手，本专栏都将为你提供宝贵的见解与实用的指导。</p>
<p>在“架构设计系列”中，我们将探讨软件架构设计的核心概念、最佳实践以及最新趋势。通过每周更新的文章，我们将涵盖以下主要内容：</p>
<h3 id="heading-57o757uf6k66k6h5y6f55cg">系统设计原理</h3>
<ul>
<li><p><strong>系统设计原理</strong>：了解系统设计的基本原则，如何进行需求分析和系统建模。</p>
</li>
<li><p><strong>系统设计层次</strong>：从高层的企业架构到低层的技术实现，层次分明设计出可靠、易维护的系统。</p>
</li>
</ul>
<h3 id="heading-kirmnrbmnotorr7orqhmlrnms5xorroqkg"><strong>架构设计方法论</strong></h3>
<ul>
<li><p><strong>领域驱动设计 (DDD)</strong>：深入解析领域驱动设计的方法论，包括如何识别领域、设计领域模型和实现领域驱动的系统。</p>
</li>
<li><p><strong>面向服务架构（SOA）</strong>：深入解析SOA的基本架构模式与应用场景。</p>
</li>
<li><p><strong>微服务架构</strong>：探讨微服务的设计原则、实现技巧以及如何进行服务拆分和部署。</p>
</li>
<li><p><strong>事件驱动架构（EDA）</strong>：介绍EDA的概念、优势以及在实际项目中的应用案例。</p>
</li>
</ul>
<h3 id="heading-57o757uf5p625p6e6k66k6h5lit55qe5bya5rqq57ue5lu2">系统架构设计中的开源组件</h3>
<p>在系统设计中，开源组件的应用非常广泛，以下是一些常见的应用场景：</p>
<ul>
<li><p><strong>API 网关</strong>：API 网关作为系统的单一入口点，处理所有的API请求。它可以执行请求路由、协议转换、负载均衡、身份验证和授权等功能。常见的开源API网关包括Kong、Tyk和API Gateway。</p>
</li>
<li><p><strong>内容分发网络（CDN）</strong>：CDN通过将内容缓存到靠近用户的边缘服务器上来减少延迟、提高加载速度，并提供负载均衡和安全防护。常见的CDN服务提供商包括Cloudflare、Akamai、Amazon CloudFront和Fastly等。通过使用CDN，开发者可以显著提升用户体验，确保内容快速、安全地传递给全球用户。</p>
<ol>
<li><p><strong>内容缓存</strong>：将静态内容（如图像、视频、CSS、JavaScript文件等）缓存到靠近用户的边缘服务器上，以减少延迟和提高加载速度。</p>
</li>
<li><p><strong>负载均衡</strong>：通过将用户请求分配到多个服务器上，CDN可以有效地分散流量，防止单点故障，提高系统的可用性和可靠性。</p>
</li>
<li><p><strong>安全性</strong>：CDN提供DDoS防护、Web应用防火墙（WAF）等安全功能，保护网站免受恶意攻击。</p>
</li>
<li><p><strong>带宽优化</strong>：通过压缩和优化传输内容，CDN可以减少带宽消耗，提高传输效率。</p>
</li>
</ol>
</li>
<li><p><strong>缓存</strong>：缓存用于临时存储频繁访问的数据，以提高系统的响应速度和性能。常见的开源缓存解决方案包括Redis和Memcached。</p>
</li>
<li><p><strong>数据库</strong>：数据库用于存储和管理数据。开源数据库有很多种类，包括关系型数据库（如MySQL、PostgreSQL）和非关系型数据库（如MongoDB、Cassandra）。</p>
</li>
<li><p><strong>消息队列（MQ）</strong>：消息队列用于在分布式系统中传递消息，解耦生产者和消费者，提高系统的可扩展性和可靠性。常见的开源消息队列包括RabbitMQ、Apache Kafka和ActiveMQ。</p>
</li>
<li><p><strong>容器化与编排</strong>：容器化技术（如Docker）和编排工具（如Kubernetes）用于部署和管理应用程序，提供高效的资源利用和自动化的运维管理。</p>
</li>
<li><p><strong>监控与日志管理</strong>：开源监控工具（如Prometheus、Grafana）和日志管理系统（如ELK Stack）用于实时监控系统性能和分析日志数据，帮助快速定位和解决问题。</p>
</li>
</ul>
<p>通过合理应用这些开源组件，开发者可以构建高效、可靠、可扩展的系统架构，满足不同的业务需求和技术挑战。</p>
<h3 id="heading-5pya5l2z5a6e6le15lio5qgi5l6l5yig5p6q">最佳实践与案例分析</h3>
<ul>
<li><p><strong>领域驱动设计 (DDD) 案例分析</strong>：通过实际项目案例，展示如何应用DDD进行系统设计，从识别领域模型到实现领域服务的全过程。</p>
</li>
<li><p><strong>微服务架构最佳实践</strong>：通过具体案例，分享如何设计和维护高效、可靠的微服务体系。</p>
</li>
<li><p><strong>演进式架构设计</strong>：探讨如何通过渐进和连续的改进来设计和优化系统架构，以应对不断变化的需求和技术环境。</p>
</li>
</ul>
<h3 id="heading-kirmnidmlrdotovlirkui7mnkrmnaxlszxmnjsqkg"><strong>最新趋势与未来展望</strong></h3>
<ul>
<li><p><strong>架构演进与技术趋势</strong>：洞察架构设计领域的最新趋势和技术发展，了解未来可能的发展方向。</p>
</li>
<li><p><strong>云架构与无服务器计算</strong>：分析如何利用云计算平台和无服务器技术构建高效、可扩展的系统，包括具体的实施案例。</p>
</li>
</ul>
<p>每篇文章不仅包含理论知识，还会结合实际案例与专家见解，帮助你将所学知识应用于实际工作中。准备好了吗？让我们一起踏上架构设计的探索之旅吧！</p>
]]></content:encoded></item><item><title><![CDATA[代码重构与高效家庭收纳]]></title><description><![CDATA[上个月，老婆带着幼宝谦谦回福建沿海老家，我本人潇洒快活地过了将近一个月的“单身”生活。然而，这段美好的时光即将结束。为了在老婆孩子回来之前给他们一个温馨、整洁、干净的小窝，我开始了我的自我修养，一个家庭收纳师的自我修养。
在有了幼宝之前，家里这些大大小小的家务基本上都是老婆一个人在承担，实在惭愧。话说“一屋不扫，何以扫天下”，在收纳了客厅的一角，小有成就的我开始了职业的复盘反思：怎么才能更高效地收纳呢？我心想，码了这么多年的代码，有什么方法论可以复用么？在和擅长收纳的领导交流完经验之后，发现还真...]]></description><link>https://blog.wuzhiguo.tech/the-self-cultivation-of-a-family-organizing-consultant</link><guid isPermaLink="true">https://blog.wuzhiguo.tech/the-self-cultivation-of-a-family-organizing-consultant</guid><category><![CDATA[family organizer]]></category><category><![CDATA[收纳]]></category><category><![CDATA[重构]]></category><category><![CDATA[架构设计]]></category><category><![CDATA[code refactoring]]></category><category><![CDATA[Architecture Design]]></category><dc:creator><![CDATA[wuzhiguocarter]]></dc:creator><pubDate>Sat, 22 Jun 2024 04:08:47 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1722174214554/9b86325a-baa1-42ee-88b6-2009c1f01b76.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>上个月，老婆带着幼宝谦谦回福建沿海老家，我本人潇洒快活地过了将近一个月的“单身”生活。然而，这段美好的时光即将结束。为了在老婆孩子回来之前给他们一个温馨、整洁、干净的小窝，我开始了我的自我修养，一个家庭收纳师的自我修养。</p>
<p>在有了幼宝之前，家里这些大大小小的家务基本上都是老婆一个人在承担，实在惭愧。话说“一屋不扫，何以扫天下”，在收纳了客厅的一角，小有成就的我开始了职业的复盘反思：怎么才能更高效地收纳呢？我心想，码了这么多年的代码，有什么方法论可以复用么？在和擅长收纳的领导交流完经验之后，发现还真有！</p>
<h1 id="heading-5a625bqt5ps257qz5lml6ygt">家庭收纳之道</h1>
<ol>
<li><p>合并同类项 （抽象与封装、提高代码的复用度）</p>
<ul>
<li>在编程中，我们常常通过抽象和封装来提高代码的复用度。同样，在家庭收纳中，我们可以将相似的物品归类存放。例如，将所有的清洁用品放在一个专门的储物箱中，这样不仅方便查找，还能节省空间。</li>
</ul>
</li>
<li><p>断舍离 （解耦核心逻辑与非核心逻辑，开闭原则）</p>
<ul>
<li>断舍离的核心在于舍弃不必要的物品，保留真正需要的东西。这与编程中的开闭原则类似，即对扩展开放，对修改关闭。通过断舍离，我们可以减少家中的杂物，提升生活质量。</li>
</ul>
</li>
<li><p>充分利用纵向空间（提升代码的Scale能力）</p>
<ul>
<li>在编程中，提升代码的扩展能力是非常重要的。同样，在家庭收纳中，充分利用纵向空间可以大大增加储物容量。例如，使用高层的储物架或挂钩，可以有效利用墙面空间。</li>
</ul>
</li>
<li><p>方便取用 （不能只优化存储空间，不管查询性能）</p>
<ul>
<li>在编程中，优化查询性能与优化存储空间同样重要。在家庭收纳中，我们不仅要考虑如何最大化利用空间，还要确保物品取用方便。例如，将常用物品放在容易拿到的地方，而不常用的物品可以放在较高或较低的位置。</li>
</ul>
</li>
</ol>
<h1 id="heading-5a625bqt5ps257qz5lml5pyv">家庭收纳之术</h1>
<ol>
<li><p>如何选择合适的收纳工具？（IDE, refactor）</p>
<ul>
<li>就像选择合适的编程工具（如IDE）和重构工具一样，选择合适的收纳工具也非常重要。不同的收纳工具有不同的用途，例如，抽屉分隔板可以帮助我们更好地组织小物件，而储物箱则适合存放较大的物品。</li>
</ul>
</li>
<li><p>如何对大件合理布局？（设计类协作关系）</p>
<ul>
<li>在编程中，设计类与类之间的协作关系是关键。同样，在家庭收纳中，对大件物品的合理布局也至关重要。例如，沙发、书柜等大件家具的摆放位置需要经过仔细考虑，以确保空间的最大化利用和整体的美观性。</li>
</ul>
</li>
</ol>
<p>通过这些方法和技巧，我不仅成功地将家里收拾得井井有条，还从中获得了不少乐趣和成就感。希望这些经验能够对你有所启发，让你的家庭收纳也变得更加高效和有趣。</p>
<p>Last month, my wife took our young child Qianqian back to her hometown on the coast of Fujian, and I enjoyed nearly a month of carefree "single" life. However, this wonderful time is about to end. To give my wife and child a warm, tidy, and clean home before they return, I began my self-cultivation, the self-cultivation of a home organizer.</p>
<p>Before we had our child, my wife was the one who mostly handled all the household chores, which makes me feel quite ashamed. As the saying goes, "If you can't clean a room, how can you clean the world?" After organizing a corner of the living room and feeling a sense of accomplishment, I started to reflect professionally: How can I organize more efficiently? I thought, having coded for so many years, is there any methodology I can reuse? After exchanging experiences with my wife, who is good at organizing, I found that there indeed is!</p>
<h1 id="heading-the-way-of-home-organization">The Way of Home Organization</h1>
<ol>
<li><p>Merge Similar Items (Abstraction and Encapsulation, Improve Code Reusability)</p>
<ul>
<li>In programming, we often use abstraction and encapsulation to improve code reusability. Similarly, in home organization, we can categorize and store similar items together. For example, putting all cleaning supplies in a dedicated storage box not only makes them easy to find but also saves space.</li>
</ul>
</li>
<li><p>Declutter (Decouple Core Logic from Non-Core Logic, Open-Closed Principle)</p>
<ul>
<li>The core of decluttering is to discard unnecessary items and keep only what is truly needed. This is similar to the open-closed principle in programming, which is open for extension but closed for modification. By decluttering, we can reduce household clutter and improve the quality of life.</li>
</ul>
</li>
<li><p>Make Full Use of Vertical Space (Enhance Code Scalability)</p>
<ul>
<li>In programming, enhancing code scalability is very important. Similarly, in home organization, making full use of vertical space can greatly increase storage capacity. For example, using tall storage racks or hooks can effectively utilize wall space.</li>
</ul>
</li>
<li><p>Easy Access (Optimize Both Storage Space and Query Performance)</p>
<ul>
<li>In programming, optimizing query performance is as important as optimizing storage space. In home organization, we need to consider not only how to maximize space utilization but also ensure easy access to items. For example, placing frequently used items in easily accessible places, while less frequently used items can be placed higher or lower.</li>
</ul>
</li>
</ol>
<h1 id="heading-the-techniques-of-home-organization">The Techniques of Home Organization</h1>
<ol>
<li><p>How to Choose the Right Storage Tools? (IDE, Refactor)</p>
<ul>
<li>Just like choosing the right programming tools (such as IDEs) and refactoring tools, choosing the right storage tools is also very important. Different storage tools have different uses. For example, drawer dividers can help us better organize small items, while storage boxes are suitable for storing larger items.</li>
</ul>
</li>
<li><p>How to Arrange Large Items Reasonably? (Design Class Collaboration)</p>
<ul>
<li>In programming, designing the collaboration between classes is key. Similarly, in home organization, the reasonable arrangement of large items is crucial. For example, the placement of large furniture such as sofas and bookshelves needs to be carefully considered to ensure maximum space utilization and overall aesthetics.</li>
</ul>
</li>
</ol>
<p>By using these methods and techniques, I not only successfully organized my home neatly but also gained a lot of fun and a sense of accomplishment. I hope these experiences can inspire you and make your home organization more efficient and enjoyable.</p>
]]></content:encoded></item></channel></rss>