<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Posts on 我的个人主页</title>
    <link>https://hyy-yu.space/posts/</link>
    <description>Recent content in Posts on 我的个人主页</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>zh-CN</language>
    <lastBuildDate>Thu, 24 Feb 2022 22:18:39 +0800</lastBuildDate><atom:link href="https://hyy-yu.space/posts/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>如何低成本的搭建一个真实的Kubernetes集群</title>
      <link>https://hyy-yu.space/posts/low_k8s/</link>
      <pubDate>Thu, 24 Feb 2022 22:18:39 +0800</pubDate>
      
      <guid>https://hyy-yu.space/posts/low_k8s/</guid>
      <description>引言：kubernetes作为当前事实上的容器编排标准，其势头可谓是如日中天，然而，kubernetes一直以来被人诟病的就是其复杂的搭建成本，作为个人，除了用miniKube等工具在个人电脑上模拟一个集群，或者通过虚拟机模拟一个集群，但终归，真实集群和虚拟集群是不同的。我一直在想，如今云服务器已经十分成熟，难道就不能作为搭建kubernetes平台的基础设施吗？
 一、架构规划 其实对于现在的云服务来说，各家竞争激烈，价格也打得比较低，但是存在一个问题：为了吸引新用户，云服务厂商一般都对产品首单、新用户首次下单时进行特别大的折扣，入坑后才发现，续费或者购买新服务器动辄上千元💰！实在不是我等普通程序员愿意支出的一笔消费😭。好在我了解到，各云厂商现在在主推一种新的云服务器（可以称之为云服务器的阉割版），比如腾讯云叫“轻量应用服务器”，阿里云肯定也有对应的产品。这种阉割过的服务器，价格实惠，正适合购买来做个人集群。
那么假如我们是新用户（新用户其实很简单，以前注册过的，换个手机号注册就是了，反正一个身份证一般都能绑多个账号，各个云厂商都差不多政策的。），我们以首单优惠买个阉割版服务器，再通过首单优惠买个云服务器，有两个服务器不就能搭一个真正的Kubernetes集群吗？😏 为了方便选择，我也做了一个价格表，目前阿里云、腾讯云都在搞活动，正是入手的好时机：
   云厂商 轻量服务器最低配置 云服务器最低配置 活动链接     腾讯云 2核2G 200/3年 2核2G 298/3年 点击查看   阿里云 2核2G 99/年 1核2G 261/3年 点击查看   华为云 - 1核2G 158 /1年 （新用户可买3台） 点击查看    以上这个表格应该对比的很清晰了，都是各厂商活动页首推的配置，应该是最便宜的了。个人感觉华为云最不实惠，不推荐。 腾讯云别看总价是498，点击这个连接领取新人优惠券，我算下来，差不多373元拿下两个云服务器，3年呐，！简直是买不了吃亏，买不了上当，感觉厂商都要亏本！ 贴上我以前做活动时买的，都是1核2G的配置，轻量买了1年（我那时候怕轻量和云服务器不可以在kubernetes集群中互联互通），云服务器买了3年，都要269元，这样一算，2核2G两个3年才373，我简直血亏😭。
回归主题！当我们以低成本拿到两个服务器后，就可以规划准备搭建集群了，这里我先放个架构图：
假设 Node1 是我们买的CVM云服务器， Light Node1 是我们买的轻量应用服务器，它们位于不同的网段，我们需要做好网络规划，让两个网段能互联互通即可。
搭建步骤 1. 各服务器上安装docker、kubelet kubectl kubeadm 要搭建kubernetes集群，首先集群中的每个节点都需要安装好以上这些软件，docker怎么安装网络上教程一大把，我这里就不多介绍了，只是要注意修改/etc/docker/daemon.json的配置：
{ &amp;#34;registry-mirrors&amp;#34;: [ &amp;#34;https://mirror.ccs.tencentyun.com&amp;#34; ], &amp;#34;bip&amp;#34;: &amp;#34;10.47.0.1/16&amp;#34;, &amp;#34;exec-opts&amp;#34;: [&amp;#34;native.cgroupdriver=systemd&amp;#34;] } 这里我修改了docker的网段地址，把cgroupdriver改成了systemd（kubernetes要求）。修改docker网段地址是因为：我们要保证节点网络、docker内部网络、kubernetes网络地址CIDR段不要冲突，冲突不好搞的，在规划时就要区别开。这里你要根据你的节点的实际网络地址，配置一个网段，不要从我的示例json中直接复制。</description>
    </item>
    
    <item>
      <title>Go 服务端开发总结</title>
      <link>https://hyy-yu.space/posts/my-first-post/</link>
      <pubDate>Fri, 21 Jan 2022 09:56:39 +0800</pubDate>
      
      <guid>https://hyy-yu.space/posts/my-first-post/</guid>
      <description>服务端开发一般是指业务的接口编写，对大部分系统来说，接口中CURD的操作占了绝大部分。然而，网络上总有调侃“CURD工程师”的梗，以说明此类开发技术并不复杂。但我个人认为，如果仅仅为了找个框架填充点代码完成任务，确实是简单，但是人类贵在是一根“会思考的芦苇”，如果深入的思考下去，在开发过程中还是会碰到很多通用的问题的。我们就用go的开发框架举例子，它有两种分化形式： 一种以beego为代表的，goframe继续发扬广大的框架类型，它们的特点就是大而全，提供各种各样的功能，你甚至不需要做多少选择，反正按照文档使用就是了。它们的问题也就在于此，很多时候因为封装的太好了，很多问题都已经被无形地解决了（但不一定是最适合的解决方式）。 另一种则以gin、go-mirco等框架为代表，它们只解决特定一部分问题，使用它们虽然还有很多额外的工作要做，但是在之中也能学到更多的东西。 接下来，详细地看看go的服务端开发可能会碰到哪些问题：
1. 项目结构 无论是大项目还是小管理系统，万里长征第一步，都是如何组织自己的项目结构。在项目结构这方面，go其实没有一个固定的准则，因此可以根据实际情况，灵活的组织。但我觉得，还是需要知道一些需要注意的点：
1. 包名简单，但要注意见名知意 这点在这篇文章中已经提到过了，用精炼的缩写代替冗长的包名，并且go中也经常出现fmt、strconv等常用缩写包，还有pkg、cmd等。但是我觉得，相比于简单，见名知意更重要。举个例子，我曾接手一个项目，它的根目录下就有一个mdw包，我开始还不知道这是干嘛的，看到里面放着一些 gin 的中间件才知道原来是middleware的缩写。 所以尽管go官方是推荐用一些约定俗成的、简洁的包名，但是应该要加个前提，那就是在注释中说明一下本包的作用，而注释却是在国内环境中，非常缺少的。所以与其生造一些缩写，又不写注释，那还不如把包名写的清楚一些。
2. 使用 internal 使用 internal 有助于强制人思考，什么应该放在公共包，什么应该放在私有包，从而是项目结构更加清晰。而且go本身提供的包访问权限没有java那么详细，只有公开和私有这两种状态，更应该用internal来补充一下。
3. 不要随便使用 init 说实话，我对为什么没有对init做任何限制还是有些疑虑的，这也就是说，你依赖的某些库可以先于你的程序代码运行，你也不知道它会做什么事（任何代码都可以在init中执行）。这在那种依赖非常多，又有很多间接依赖的大型项目中体现的很明显。尽管go官方要求不要在init中执行任何复杂的逻辑，但是这没有任何约束力。 最简单的例子就是单元测试，我有时候跑单元测试经常会碰到panic跑不起来，究其原因就是某些依赖库init中做了一些骚操作。但问题是：我是依赖的依赖（间接依赖）了这个库，我也没法控制它的代码（没有修改权限）。碰到这种情况，也只能在单元测试中完成它的要求才能继续运行。 所以把代码放在init中，一定要三思。就我来看，很多用init的代码确实在做初始化，但它们内部隐式依赖了文件、路径、资源等。这种情况要想一想，是不是可以用 NewXX() \ InitXX() 这种函数来替代。
4. 慎用 util \ common 这种包名 这种一般是java程序员转过来的用的比较多，但其实在go中，是推荐有意义的包名来替代这种无意义的包名的。比如：util.NewTimeHelper() 就不好，应该写成time_helper.New() 这样可读性强一点。 但是我觉得具体情况还得具体分析，所以标题是慎用，而不是不用。因为有些时候，你的 util \ common 也就几个帮助函数，没多少东西。再细分成几个包感觉有点得不偿失了，等util \ common 再攒多一点再重构也不迟。所以还是回到开头提到的，多思考，灵活处理。 但是这里又要注意了，如果是那种被很多人依赖的公共 util \ common，最好还是早点拆分，不然后期可能拆不动了。
2. 代码结构 代码结构上能说道的东西就更多了，这可能是见软件设计功底的地方，我在这方面也是初学者，所以总结出来的可能对，可能不对，仅供参考。
1. c \ s \ d 层的划分 得益于MVC的流行，即使现在已经普及了前后端分离的架构，大部分项目也仍然在内部存在 controllerorhandler、serviceorsvc、daoorrepository这样的划分。用于隔离数据展示、逻辑处理、数据存取的逻辑。这里记录下我对这三层划分的理解： controller： 一般是入口控制器，做参数接收、转换，返回值处理、协议处理等工作。这一层一般不会太厚，也就是不会有太多的逻辑。这里要注意其与网关（Gateway）的区别，网关要做的事和能做的事会比它多很多。然后就是有些项目会把参数校验放在这一层，个人认为参数校验应该使用一些框架如validator来做，不要重复造轮子，如果需要访问数据库来校验参数，就应该放在service层做。 service：这层可能会比较重，也是很考验设计功力的地方，一不留神，就容易把这层变得耦合性极高。我也曾见过在service层中直接写sql查询的操作，十分让人头疼。总的来说，因为这一层承上启下，尽量让它成为一个粘合剂，而不是全能选手。 dao：这层就是跟数据相关了，其实就是把service层对数据的直接操作（操作数据库、redis），变成对方法的调用。以屏蔽数据库的差异，同时也可以做一些统一的数据处理。一般来说我们的项目会使用orm，这层也可以对orm进行一次封装，从而更易使用。由于这层更多的是对数据的通用化处理，所以一般通过代码生成器生成比较方便，比如：gormt。
2. 依赖的传递 这里的依赖指的是controller、service、dao层三者的依赖，一般来说，controller需要调用service，service需要调用dao。最忌讳的事是，因为上层需要下层，所以在上层中调用创建下层的代码，比如在controller的构造函数（就是NewXX，Go中没有专门设置构造函数）中调用NewService，这显然不符合单一职责的设计原则。所以一般有两种处理方式： 一、 设立全局变量</description>
    </item>
    
    <item>
      <title>凤凰架构读书笔记</title>
      <link>https://hyy-yu.space/posts/%E5%87%A4%E5%87%B0%E6%9E%B6%E6%9E%84%E8%AF%BB%E4%B9%A6%E7%AC%94%E8%AE%B0/</link>
      <pubDate>Fri, 21 Jan 2022 09:56:39 +0800</pubDate>
      
      <guid>https://hyy-yu.space/posts/%E5%87%A4%E5%87%B0%E6%9E%B6%E6%9E%84%E8%AF%BB%E4%B9%A6%E7%AC%94%E8%AE%B0/</guid>
      <description>演进中的架构笔记：
 我理解的架构之道，一定是在了解架构发展的历史基础上扩展，非历史而不能明真理。
 最先和最初的单体架构，老而弥坚。很赞同作者说的单体并不是反例，实际上我们很多系统刚开始就是单体架构，单体只意味着：
 1. 随时间维度增长带来的维护困难
 2. 技术栈的单一
 3. 一荣俱荣一损俱损
 对一些小系统而言，单体无疑是最简单正确的选择。同时，单体不意味着维护困难，这点要格外注意。只有在时间增长带来的系统复杂度增长的情况下，才会出现维护困难。同时，技术栈单一也不一定是缺点，任何公司，都不可能允许大面积百花齐放，这样带来的只有混乱和无序。一荣俱荣则说明单体的特点是单进程，无论代码分割的多么合理、设计模式用的多么高端，最后如果都在一个进程中（一个单机中），都会存在相互影响的问题。
 SOA架构：
 单体系统经过发展，一定会出现拆分需求，然而，如何拆分就成了一个大问题，直至今日，都是后端程序员需要重点了解和解决的问题。
 1. 孤岛式架构
 这就是单体的变种而已，各个系统成为孤岛，你不必知道我，我也不必知道你。这种架构根据康威定律，一定是非常少的，因为一个组织下的子组织，一定是要有信息交互和联络的。
 2. 微内核架构
 这种架构是很常见的，以微内核为中心，各系统、功能作为插件集成。它的缺点和孤岛式架构一样，组织之间是必然有信息交互和联络的，而插件之间还是孤立的。但它适合在特定场景（灵活拓展）下使用。
 3. 事件总线架构
 这种应该是以前的程序员们常接触的，通过一个ESB总线来协调通讯，各子系统通过ESB交换信息。进而衍生出管理、安全、封装、序列化协议等一系列今天依然耳熟能详的概念。总之，ESB希望能打通软件从需求到上线的全部步骤。这也就是它的短板：太大而全。所以它学习曲线陡峭，所以它用的人少，更关键的是，根据二八定律，百分之八十的功能大部分人都用不到。
 微服务架构：
 每个知道“微服务”这三个字的人，都会自然的产生这个疑问：微服务到底要拆的多细？作者通过分析微服务的九大核心特征告诉我们，它不是细不细的问题。
 1. 围绕业务能力构建：这是在强调康威定律，什么样结构的团队就会产生什么样结构的产品，而团队结构适应着市场需求。所以微服务拆多细，怎么拆，每个团队都是不一样的。
 2. 分散治理：这体现的是微服务的开放性，因为团队下各子团队的人员不同，思想不同，各个子团队负责治理自己旗下的产品。
 3. 通过服务来实现独立自治的组件：这是典型的 富应用 概念的反例，也即是说，不要通过实现类库的方式提供功能，而要通过服务的方式。这是一种解耦的要求。
 4. 产品化思维：这感觉跟分散治理说的理念差不多，因为子团队负责治理自己旗下的产品，当然要有产品化思维（从需求到上线到维护到支持等各方面）。单体系统因为其内部的庞大和复杂，只能细分为开发、运维、支持等人员分工，各管一块。
 5. 数据去中心化：本来把系统拆分成几个服务，分割的好好的。如果服务间还是共用一个数据库，那服务A免不了会忍不住去直接访问服务B的表（这效率多快啊）。懒惰是人类的原罪，这是无法避免的。所以数据的分散是必然的，避免了直接调用。（也就带来了分布式事务的问题）
 6. 强终端而弱管道：这句话一定要看原文（Smart Endpoint and Dumb Pipe），我理解就是服务要提供出来接口，数据的流入流出都是通过自己的接口，凡事靠自己，而不是通过ESB之类的传输。（这是在抨击ESB啦）
 7. 容错性设计、演进式设计：这两个应该放在一起，我感觉这两个是微服务流行的最大原因。为什么？拿人类社会做对比，古代人总想追求不生病，追求永生，现在我们知道，人不可能不生病，DNA决定了复制一定会有概率出错；人也不可能永生，就像没有永动机一样。那凭什么要求程序不出错、程序一直能运行？初学程序者，最爱的就是比谁的程序报错的少😄，可能这也是人与生俱来的一种美好愿望吧。对人体而言，DNA复制出错有免疫系统处理；对种群而言，一代代人的生老病死维持着整个种群的健康，不会产生你不知道怎么称呼你太太太太爷爷这种问题。那对程序而言，完善的容错设计和接受程序是演进式发展的观念，也是发展的必然。
 8. 基础设施自动化：我觉得这说的是拆分下的统一，统一的是什么，就是基础设施。比如CICD、Kubenetes、Docker这些。拆分后，有些东西可以任选，但有些东西，必须要用它，而且要高效自动化的使用。
 列出了这么多原则、要求。如果真正理解了，就会发现，这玩意真是复杂。作者也说了：“微服务所带来的自由是一把双刃开锋的宝剑”。一方面代表开放、自治，一方面代表复杂（不同于单体架构的复杂）。这也是架构师的难点，如果说微服务只是理论上的概念，那么要真正落地真的还有许多许多路要走。不可否认，微服务真正的落地后，对广大后端程序员而言是友善的福音。</description>
    </item>
    
  </channel>
</rss>
