玩二手电脑组装的人,在想要满足需求的情况下,往往是预算不足,只好淘旧的硬件来自行组装,在性价比,稳定性,扩展性之间平衡和妥协。写代码这件事上,往往也是预算不足,充满了平衡和妥协。
脱离需求谈技术实现,就和装一台2万块的电脑天天用来刷贴吧一样。
以上,摘自《代码与二手电脑装机艺术》还没写(划掉)。
序
微服务、微服务、微服务,从我刚加入这个行业开始,这个词就就到处都在出现。高可用、易扩容、能容灾、高并发,微服务大概就像手机届里的苹果,看到的第一印象就是高雅,牛逼。
而三年前刚刚入行的我,就像一个青涩小学生,自然是:
—— 摸都没摸过。
兴趣是最好的老师。
第一年里补充计算机里着各种知识概念,写着丑陋的代码,享受了SSM构架下的一堆XML配置文件。
很快就有了机会自己整项目,SpringBoot从零开始,前端、后端、CDN、域名、 Linux、Nginx、Docker,全都自己来,从第一个文件建立到上线。
对我而言是里程碑式的一件事:
拥有了掌握项目一切的自信。
为什么我要使用微服务
如果你有构建SpringBoot的经验,起一个SpringBoot只需要几分钟,你就做好了Controller层,很快连上了数据库,一个Demo就出来了。如果没有构建SpringBoot的经验,你可能需要几天时间,简单了解下SpringBoot 构建自己的SpringBoot项目,总之不会需要太久。
项目需要快速的迭代且服务不能中断,长期以往,你可能会像我一样拆分出多个SpringBoot程序,之间用HTTP工具类调用,代码变的混乱和不可复用,依赖越来越乱,所有服务是单实例的,个个程序都有自己的缓存,升级必须重启,想改变又因为各种限制...
总之结果就是看上去简单又复杂一坨代码。
这个时候又要做新的项目并且还要和旧的项目交互,我觉得我需要微服务了。
写第一行代码前
为了理解和学习微服务,我做了什么?
需要在了解SpringBoot的前提下,熟悉几代SpringCloud各种组件的停更/升级/替换等。了解注册中心,配置中心,消息总线,路由网关,负载均衡调用器,服务接口调用工具,分布式事务,断路器,熔断,限流等概念。
项目构建需要多理解项目构建工具一些,例如Maven中锁版本,包的层级依赖,各个服务间公用代码的包的抽取和打包,项目总体上会更碎一些。
一开始真的是被各种名词唬住,怕怕的,但是其实本质上并不是什么复杂的东西,然后的确要一些时间。
学习参考了:
在尚硅谷看了一些微服务基本概念和功能。
很多人都知道的开源微服务项目,优点是文档很厉害,如果是新手,很容易看懂各个部分,快速上手。 缺点就是比较Demo级别,直接用这个构架作为生产环境不现实,完全不够用。
pig4cloud
https://gitee.com/log4j/pig
https://www.yuque.com/pig4cloud/pig
商用级别的,上手后很值得参考的项目,缺点可能是开源做的不是很好。
开源微服务项目,值得参考。
人月神话?
两个人之前需要沟通2次,3个人就需要6次,写代码的沟通成本是非常高的。
软件开发的进度难以用人天衡量。
如果项目不是成百上千万并发的需求或者复杂度,后端一人或者两人可能是最高效的,前端同理。
开发时,对功能要问是什么? 为什么? 有了此功能有什么意义? 谁在用? 真的有用到吗? 等等.. 理解透彻才能做好,话语的传递总是有偏差,人和人的沟通总是充满偏差。
以上,我的一些经验。
起步前的情况
-
前端一人负责,因为此项目为一个尽可能自动化处理业务的系统,只有查看运行情况和无法自动化处理的异常情况才需要人去处理,所以前端的工作相对较少。
-
后端一人(我) 负责后端大部分代码、环境、上线、运维。我没有构建过微服务项目,实践没有经验,需要从零开始实践到上线。
-
测试和产品算一人。
-
预期第一版为3个月左右的时间。
起步
构架上,一步到位还是循序渐进?
出于人力和时间和当前自身水平,第一个版本我选择循序渐进,单实例,不分库,明确清晰的 (有点做菜放适量盐的感觉) 服务直接拆分。
第一个版本,要考虑多实例吗?
考虑但没有直接实现多实例。
同一个服务起多个实例,之前难免需要共享缓存和多线程共享的缓存,虽然我第一版没有打算起多实例,缓存层和共享资源也要抽取好,方便后期改造进Redis之类的地方去。
第一个版本,需要考虑分库吗?
考虑但不直接分库。
例如A库有 C、D、E 表,B库有 F、G 表,如果把这些表都放在一个库,也是能跑的,但是要在逻辑上做好区分,不要耦合,方便后期拆库。
多实例,带来了什么问题
-
避免单点故障: 每个服务都由起码两个实例构成,随意挂掉一个节点都不会造成系统故障。
-
容易的扩容: 可随意扩展实例的数量到多个。
-
合理的拆分: 有利于升级和多次快速迭代。
如果要全部实现以上3点,需要付出巨大的代价。
定时任务会跑多次怎么办?
A B实例中同一刻的定时任务,往往只需要跑一遍,有一些定时任务框架,大体上也是抽取出来订单任务单独跑个单例最方便,现在需求不是很多,后期可能要抽取下定时任务。
WebSokcet和Socket怎么多实例呢?
这方面的资料挺少的,核心就是依赖客户端优秀的重连机制实现。
特意去V站发帖咨询:
订单号生成,这也要新建个服务吗?
A B实例需要生成不可重复的订单号,有长度限制并且还要包含时间信息和其他信息只有3 - 5位 保证不可重复性,之前的单机策略是1毫秒下最多滚999个订单号,加锁保证唯一,多实例下要去同一个地方取订单号保证唯一性,单独新建个服务代价太大,还没想好怎么做。
微信公众号的访问权限获取
微信公众号接口的策略大概是两个小时获取一次Token,凭借此Token访问微信相关接口,还有其他一些微信接口的封装做为了一个模块,多实例存在一个获取和存储Token的问题,重复获取Token如何解决,还没想好,暂时还是单例。
多实例共享缓存
服务A的两个实例 B C 如果共享资源只能依赖第三个进程,如果第三个进程是单例的那也就很不微服务了,比如一般用的Redis如果要起集群就是3个实例。
代码层也要改造,所有的共享缓存之类的全部丢进Redis中。
庞大的内存
一个SpringBoot需要约500M内存。如果需要多实例,难免就要Redis集群(起码3个Redis),注册中心集群(Nacos3个),MySQL起码两个双主,普通的服务起码2个实例,内存和服务器数量的需求相对单例求是可怕的。
分布式事务
一个事务A服务保存,B服务也要保存,成了跨进程的事务,这可怎么办?
笨办法手动提交也算能解决,也会很多分布式锁的解决方案,我也没去了解。
现在的手段就是尽可能避免需要分布式事务,还没有遇到非要处理的情况,有需求了才会去处理这种情况。
部署和运维
微服务,彻底的前后端分离,两份前端,八个后端进程,占了5个G的内存,如果考虑多实例,约要准备总计15G内存,分别散布起码3台服务器上,考虑到后期还要拆分和增加服务。
不使用云服务器,自行维护一切的尝试
拉了20M的专线,购买了UPS电源,自行在硬件上安装系统,成功跑起来了第一版,为了维护服务,相比云服务器,我需要自行应付断电,服务器要有ECC内存,硬盘要用起码企业级,服务器有双电源保障,硬盘RAID10保证数据安全和可用性,异地容灾后期也成了必须品...
第一次不用云服务器,才知道云服务器给我做了多少工作!
自建硬件可以拥有近乎无限的性能和硬件扩展,但是也带来了大量的运维工作还有异地容灾相当麻烦。
集群部署 —— Docker
集群部署,DockerFile 和 DockerCompose就满足不了了,需要Docker集群,自然就用DockerStack,如果实例太多太多,还需要K8S这种管理集群了。
尾
彻底贯彻微服务,相比单例服务更高的运维成本,前期开发成本高,但是带来的优点也是显而易见的,如果需求足够大,贯彻微服务总体降低开发成本,运维,容灾,升级都更容易。
云服务器需要付出大量的钱,硬件较贵(硬盘、CPU、内存),但是提供了很多运维能力。如果自行维护机房服务器,没有了云服务器提供的运维能力,要付出相当高的建立和维护成本。
本文由 考拉 创作,采用 知识共享署名4.0
国际许可协议进行许可
本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名
最后编辑时间为: May 12,2022