PixelMage

PixelMage 查看完整档案

填写现居城市  |  填写毕业院校  |  填写所在公司/组织填写个人主网站
编辑
_ | |__ _ _ __ _ | '_ \| | | |/ _` | | |_) | |_| | (_| | |_.__/ \__,_|\__, | |___/ 个人简介什么都没有

个人动态

PixelMage 赞了文章 · 2020-08-17

思否独立开发者丨@敬文:打造一款神器解放 Ctrl - CV 工程师的双手

FastClip

目前工作状态(在职/独立开发):在职

独立项目名称: FastClip- Endless Clipboard

思否社区ID:@敬文


敬文在学校的时候做的是 ACM,毕业后想找一份 C/C++ 相关的工作,却阴差阳错入了 OC 的坑,并成为了国内首批 iOS 开发者,后来他有幸参与开发了支付宝(现在的蚂蚁金服)第一个手机版本研发,并积累了很多经验。

两年后他跟着当时的老板出来创业,现在他负责这家公司的技术团队。虽然管理时间会占比重较多,但他还是闲不住喜欢编码,业余时间他开发了一款可以让经常 CV(复制粘贴)小伙伴将效率提升 30% 以上的神器。

FastClip

设计思考

项目最早开始于 19 年 10 月份,起初只是因为 Alfred 收费,自己又是 Snippets 和剪贴板历史记录功能的重度用户,就顺手写了一个简陋版本自己用。使用一段时间后觉得 FastClip 确实提高自己平时工作的效率。于是就上了 Mac AppStore。

项目面向的群体主要是对工作效率有着极致追求,又有着繁重的文字搬运工作(Ctrl - CV程序员和运维同学等等)

现在 FastClip 有四大优点:

  • 无尽剪贴板

FastClip 会将剪贴板中的内容通过特有的算法和文件结构建立索引,所以 FastClip 可以记录一切你复制的内容。

  • 印象搜索

除了通过设置别名来保存有用的片段。因为 FastClip 保存了你所有的剪贴板,只要输入您有印象的一些关键词,FastClip 将会快速的检索出你想要的。

  • 预览模式

FastClip 不仅保存了去除样式的数据, 你可以通过激活预览模式(快捷键 Shift+Enter)来浏览记录的富文本格式信息。尤其对于网页或是 excel 表格,提供了更好的浏览体验。

  • Thinking Bar

当你输入检索关键字的,FastClip 不仅会检索剪贴板历史,更会根据你输入的内容进行一些预测,对历史记录进行增强处理。

当然在我的规划中 FastClip 不单单只是承接复制粘贴操作的强化,更是希望 FastClip 能够成为输入增强器,去做为Mac用户的输入入口。

如果你在Mac系统中想要一款基于剪贴板的输入增强器,或是你注重应用的体验,希望在你的应用列表中的应用都足够的精致,那么请不要错过 FastClip。

由于 Mac AppStore 的竞争没有那么激烈,FastClip 算是效率类 Top 榜的常客。更重要的是

认识了很多很有想法的独立开发者。

FastClip

快问快答

1、如何定义“独立开发者”?为什么选择成为一名独立开发者?

除了是一名工程师,还需要一些特质,例如对于自己的应用追求极致,有着自己独特的产品规划与视角,用户第一。

其实严格来说我还不算一名独立开发者,在职并且平时的工作量还不小。基本都是用晚上和周末 因为本职工作晚上也比较晚 周末会更多些。

但是相对于一些独立开发同学经济压力较小,可以更细致的打磨产品(并且定价上做到物美价廉)。但也拖时也很严重。

2、可以推荐你最喜欢的一款产品 / 游戏 / App?并说明原因么?

Mac 桌面端,还是会推荐自己的应用,对于我来说使用的频率比较高,仅次于 IDE。

手机端的话更喜欢用快知这类通过机器人来筛选和提供自定义资讯的,我的下个手机端的独立应用也会是类似的。

3、如何看到剪切板泄露隐私问题?

这个还要看这些应用有没有做剪贴板数据的收集或者分析,但不论如何这种行为都会让用户很恐慌。作为一名剪贴板应用的开发者,个人的态度是必须把用户的隐私放在第一位。我的应用除了会上传用户是否激活过应用,用户剪贴板任何的信息都只会在用户机器上,即使是 iCloud 或者一些第三方的存储我都不会去用,未来电脑与手机的剪贴板同步也只会通过蓝牙来做本地同步。不会去传输任何用户的剪贴板信息。

4、同类产品对比有哪些优势和不足?

功能上相对 alfred 还是会简陋一些,但是 alfred 的功能在门槛上不算太高,后续会逐步添加更多的核心功能。 alfred 算是一个 launch。剪贴板属于他的二级功能,但是 FastClip 所有的扩展都是基于剪贴板的内容,并且可以快速的定制 snippets。FastClip 的目标是通过输入增强提高效率。

5、 近阶段项目有哪些更新,未来会做什么变动?

未来FastClip将会加入淘宝,知乎等等的搜索功能,尝试的去帮助用户做为输入入口。

开放Thinking Bar的接入,并且会通过蓝牙打通手机端,手机端的定位是 Mac 端数据同步和成为手机端launcher。

接入知乎淘宝这类的搜索,主要是为了拓展FastClip的使用场景,在没有复制操作时,可以用FastClip来进行特定场景的搜索,对于知乎和豆瓣等这些高质量的资讯社区由FastClip来融合搜索结果。

对于淘宝,拼多多这些电商平台,会由FastClip融入查券功能给用户实际的收益。当然alfred也有通过workflow来进行这些的扩展,但是对于FastClip将会是官方的并且持续迭代的功能。 开放thinking bar类似与FastClip可以像Alfred一样可以让用户自己来开发workflow,但是FastClip的thinking bar定位是轻量的,轻用户干预的,在不经意的使用中提高用户效率。

蓝牙打通手机端,主要的目的还是用户的 Mac 的生态(或者说是安装的FastClip桌面版和手机版的用户),能够高效的传输和处理,手机端和桌面端需要共同处理的文件,可以让大家摆脱通过 IM 中转来传输文件(所有的内容不会经过云端,极大的保护了用户隐私)。在功能上这块在后续会有更详细的规划。

最后说一句对于FastClip来说,永远是用户第一,用户提出的不错的建议,都会尽量在下个版本安排上。

小编对FastClip评价

简单易用容易上手。唯一的缺点是默认显示最新的是只有20个,如果能够自定义显示的数量就更好了(有时我记不住复制过啥)。不过我觉得对于剪贴板管理器来说,Fastclip的解决方案要比butler/alfred/paste都要出色。并且价格很低 Fastclip 只要 1 块钱。

下面说下优缺点:

1.我尝试复制图片,但是只能复制文本

2.我非常喜欢 thinking bar 的功能, 特别是我输入“now” 可以获取当前的时间,很方便。

3.同时我发现他也可以快速的打开应用,这个在功能描述里面没有提到。但是感觉比 spotlight 检索更快。

4.“now”指令没法自定义,特别是有时候我只需要日期。

5.状态栏上的 icon 颜色我也希望是黑白的 和应用大多数统一。

总的来说 1 块钱的买断价格非常的划算,期待 Fastclip 能够完善更多的功能。


独立开发者支持计划-1.png

该内容栏目为「SFIDSP - 思否独立开发者支持计划」。为助力独立开发者营造更好的行业环境, SegmentFault 思否社区作为服务于开发者的技术社区,正式推出「思否独立开发者支持计划」,我们希望借助社区的资源为独立开发者提供相应的个人品牌、独立项目的曝光推介。

有意向的独立开发者或者独立项目负责人,可通过邮箱提供相应的信息(个人简介、独立项目简介、联系方式等),以便提升交流的效率。

联系邮箱:pr@segmentfault.com

开发者支持计划-2.png

查看原文

赞 4 收藏 1 评论 0

PixelMage 赞了文章 · 2020-07-28

思否独立开发者丨物理学专业的我卖过鞋垫做过米雕,现在「沦落」成独立开发者

闪点清单.jpeg
目前工作状态(在职/独立开发):独立开发

独立项目名称:闪点清单

思否社区ID:@lanistor


10年前,@lanistor 因为想做网站从一个物理系的学生悄然转型到 IT。在这之后的10年里,@lanistor 做了不少项目,其中包括:二手交易、校园微博、基于LBS的轻咨询平台、开源框架React-Keeper、甚至还有会呼吸的鞋垫(你没看错就是脚上穿的鞋垫)。

细细讲起 @lanistor 的故事也算是丰富中带着坎坷,高中时他是名副其实的学霸,最强项的是物理、化学和数学,不过比起学习他始终更想做一些有意义的事,高二时在山东高压教育之下,他用整整一年做了一款呼吸鞋垫,后来这款鞋垫还有幸申请到了发明专利。

考上大学后,@lanistor一边学习自己的专业知识——理论物理,一边开起了实体店,店铺里有各种新奇的礼品,为了吸引顾客他还自学米雕,并在店铺中出售。

闪点清单.png

△原谅那个年代像素不行

再后来他关掉店铺,用赚来的这些钱迈入了计算机的世界。@lanistor 觉得学校需要一个二手交易网站,随即在暑假开始自学Java等技术,并开始找人一块做网站「校易网」,团队最大的时候达到了7个人,为了做好网站 @lanistor 还休学了一年,不过网站最后没运营成功并「光荣闭站」,最终一盘算域名倒是卖了点钱。

迈入社会后,@lanistor成为了转职 Java开发,在工作的这几年他做个好多个独立项目,也正是因为这些独立项目,让 @lanistor 顺利成章的「沦落」为一名独立开发者。


这个让 @lanistor 毅然决然成为独立开发者的产品,是一款不一样的悬浮清单软件——闪点清单。

闪点清单.jpeg

作为时间管理工具重度依赖者,他几乎尝试过了绝大部分时间管理软件,最常用的有某某清单,也经常配合Apple提醒事项、备忘录、云笔记等软件一起用。由于每天需要记录的事情太多,经常会正在聚精会神地做一件事儿,突然来了一个其他事,就先记录下来,设定好时间定时提醒。

这个操作多了,他发现了三大难点:

  • 切换桌面与APP总感觉浪费时间;
  • 而且切换到其他软件工作时,看不到代办事项;
  • 还有提醒的形式也不太灵活。

了解到自己的这些需求后,他开始在市面上寻找符合的产品,但找了一圈也没有找到想要的软件。作为一个易过敏型人格的人,他觉察到这可能是个机会,于是在搜索引擎搜相关内容,果然看到很多人提出了类似的需求。

那不如就自己来做!

第一步当然先确定是不是伪需求,还有需求量是不是足够大,然后我便开始收集需求。收集需求的方案,本来考虑做个效果图,然后到处发发问卷,看大家反响;但PS只懂点皮毛的人,还是写代码来的快。于是我便用2个星期的时间,写出了第一个Demo,然后跟一些比较专业的产品、技术朋友聊了聊,大家反应基本是:感觉还可以,但是总感觉我还有A、B、C方案可以实现这个效果,为啥非要这样?

这个问题我也给不出答案,于是我又开发了近2个多月,基础功能差不多能正式用了(但其实还是很Low,跟竞品完全没有竞争力),我便准备投放出去了,看市场的反应。我当时的考虑:我只宣传这一个点,如果功能这么Low都有人喜欢用,就说明这个需求点是把握得很准的。

然后,一个关系比较好的运营朋友便帮我发了出去(她后来成为了我的合伙人),只发了一篇帖子,当天引来了100多个下载量,还有很多好评。又持续测试了一个月,整体的测试结果远超出我的预期,从结果数据和反响来看:这个点、很多用户很需要。

然后就有了后来的产品:闪点清单,后面也有了闪点工作室。

@lanistor 说项目目前还没有明显的成绩,但收获了几千名忠实粉丝。目前盈利点还没有开放,一直是纯投入。不过和用户的反复沟通,也打开了他们的思路,让他们有了很多好的产品 Idea,这些 Idea 后面会陆续加入到产品中;用户也一直在给他们正向的反馈,表示用了他们的产品后其他清单软件已经都卸载了,也希望他们能继续做下去;甚至很多用户着急让他们开放盈利点,或者打赏他们,因为担心他们没有盈利方式会死掉,用户们不想看到这样优秀的产品死掉。

闪点清单.gif
△悬浮窗功能

闪点清单.gif
△PC端一隅

快问快答

1、你如何定义“独立开发者”?又为什么选择成为一名独立开发者?

  • 能独立用自己的想法和作品解决业界问题的人。
  • 我成为独立开发者有两方面原因:

第一是看到很多行业存在很多问题,这些问题还没有完美的方案能够解决得像自己期望的那么好,这时候很希望能用自己的力量解决这些问题。

第二是,一直有一个产品梦,一直希望创造一款流行于世界的产品。

2、 独立开发过程中遇到过哪些困难?最难搞定的是什么?

主要有两个困难:

  • 第一是团队

我们是工作室的形式,而有些同学是兼职来做开发,这样就会有输出时间问题,毕竟要和当前的工作、生活来抢夺时间。解决这个问题,我们首先从理念上达成共识:肯定要牺牲掉生活质量,生活需要家人来支持;然后是我们定了一个规则:兼职的同学每周输出时间不能小于25小时,基本是工作3天的工时,这样来保证产品的开发进度。

  • 第二是增长

第二个难题是增长,我们没有同学从0运营过产品,但是这个过程也必须趟过。考虑到增长是创业产品的核心能力,具备这些能力的人又很难找,我们决定自建增长能力。所以我现在基本是全职增长,这个问题是在解决的路上,会一直伴随产品全生命周期。

3、推荐你最喜欢的一款产品 / 游戏 / App?并说明原因

应该是《纪念碑谷》吧。看到这个产品就已经惊艳了我,玩游戏的过程中,细腻的产品体验、惊奇的机关设计、还有产品背后的故事,都很让我兴奋。工匠精神说来容易做好很难,我们在做的产品,也一直努力在细节上吹毛求疵。

4、分享一下你的技术栈? 分享一下你日常的工作流?

  • 我的技术栈

一般是用到什么学什么,之前在大厂经历过专职Java和专职Web,其他技术栈比如:Node、Flutter、C++、LLVM都懂一些,Android、iOS开发也略懂一点,Unity3D搞过,被历史湮没的Flash AS也搞过。

  • 我的工作流

产品开发比如:需求收集、开会讨论、产品开发、功能自测、打包上线、线上运维,作为创业小团队,每个人都要懂全流程。

运营工作比如:用户沟通、渠道沟通、软文产出、品牌宣传、基础运营杂活等等。

5、日常兴趣爱好

爱好比较广泛,喜欢的运动有网球、足球、乒乓球、游泳等(大学还有个水水的足球颠球校园吉尼斯纪录),曾经喜欢象棋,唱歌麦霸。现在的爱好就只有写代码了,准确来说,是只有写代码的时间了。现在想想,好像这10年一直是一个作息,大部分时间都是每天写代码到1点以后,2、3点也是经常的事情。

除了上面讲的爱好,还有个癖好,就是喜欢看荒山。曾经大学校园在山区,后面有三千亩的荒山,最喜欢的事情,就是一个人去爬山,然后坐在山顶上听着轻音乐看长长的山谷,经常一坐就是一下午。那应该是一个能让人静下心来向远处看的神秘山谷。

带你去爬山.jpeg

6、对开发者和编程初学者和怀抱梦想对年轻人有什么建议

开发者牛人很多,建议实在不敢多说,就说一点吧:

鼓励大家多做独立项目,不仅能开拓技术视野,也能学习从多维度思考产品和技术,还有可能真给业界带来很好的产品。

对于年轻人来说我的建议分为三个方面:

  • 成长方面

学习编程的人有的基于过程成长、有的是基于目标成长,建议是基于目标成长为主,然后配合过程成长,这样成长得更快,也更容易触及一个领域的边缘,更容易做出成绩。先给自己找个目标。

  • 项目方面

前几个项目基本都要失败,基本都是源于在某一项能力上有欠缺。多尝试,多发现自己的短板,然后花精力把它补齐,下次离成功就会更近一点。

  • 产品增长

产品增长是一项非常重要的能力,需要的能力点也很杂,但是很多技术人员很容易忽视这一点能力。这个难点基本是所有项目的成功必备的能力,也是大部分独立项目夭折的地方,一定要虚心学习、灵活运用。

7、近阶段项目有哪些更新,未来会做什么变动

近阶段我们重点打造了移动端,移动端刚上线4个月,功能和体验质量已经都比较高了。

后面短期内我们的工作主要有这些点:

  1. PC端UI大改版
  2. 移动端小部件开发
  3. 支持更灵活的多层级任务管理
  4. 融入番茄工作法到产品中
  5. 数据报表、富文本等功能开发

长期的规划暂时还需要保密。

闪点清单.jpeg

@lanistor 现在在思否社区持续更新「闪点清单」技术文章欢迎大家浏览点赞哦!

从0开始设计Flutter独立APP | 第三篇: 一劳永逸解决全局BuildContext问题

从0开始设计Flutter独立APP | 第二篇: 完整的国际化语言支持

从0开始设计Flutter独立APP | 第一篇: 数据库与状态管理

独立开发者支持计划-1.png


该内容栏目为「SFIDSP - 思否独立开发者支持计划」。为助力独立开发者营造更好的行业环境, SegmentFault 思否社区作为服务于开发者的技术社区,正式推出「思否独立开发者支持计划」,我们希望借助社区的资源为独立开发者提供相应的个人品牌、独立项目的曝光推介。

有意向的独立开发者或者独立项目负责人,可通过邮箱提供相应的信息(个人简介、独立项目简介、联系方式等),以便提升交流的效率。

联系邮箱:pr@segmentfault.com

开发者支持计划-2.png

查看原文

赞 11 收藏 1 评论 2

PixelMage 关注了用户 · 2020-07-28

lanistor @lanistor

“闪点清单”独立开发者,唯一一款悬浮清单软件。

关注 48

PixelMage 发布了文章 · 2019-12-22

《微服务:从设计到部署》总结笔记

英文原文出自:https://www.nginx.com/blog/introduction-to-microservices/
笔记首发于我的语雀,有空来帮我点个稻谷呀。

port_by_arsenixc-d90p0xb.jpg

1 简介

monolithic app(都写在一起)的劣势

image.png

  • 代码依赖极其复杂
  • 难以理解
  • 启动时间变长
  • CPU密集型逻辑和内存消耗型逻辑无法拆开优化,浪费云计算资源
  • 可靠性变差:一处内存泄漏,全家升天
  • 难以做架构升级,例如更换语言或框架

微服务

image.png

  • 把你的巨型应用拆解成小型的独立的互联的服务们
  • 服务之间互相之间提供服务和消费服务
  • 客户端通过API网关来调用服务们
  • 运行时的一组服务可以是多台物理机上的多个container
  • 服务拥有自己的独立的数据库存储,这意味着服务可以选择自己最适合的数据库类型。

微服务的优势

  • 拆解了复杂的应用,单个服务更好迭代和维护。
  • 每个服务可以自由地选择最合适的技术栈。
  • 服务可以分开部署,可以更加自由地进行持续集成。

微服务的劣势

  • 必须要开发服务间通信机制
  • 需要经常处理“部分失败”的情况,因为一个请求现在是是一组服务的调用。
  • 数据库结构设计和操作,例如跨表操作,数据一致性(事务)问题等。
  • 测试更加困难,因为要测试你的服务,你必须先启动其他服务。
  • 在维护或更新时,你通常需要更新多个服务。
  • 服务数量众多时,部署也是一个难题。

2 构建微服务:使用API网关

  • 【背景】例如在做一个电商宝贝详情时,你客户端需要调:购物车服务、订单服务、类目服务、评价服务、库存服务、发货服务、推荐服务....

不使用API网关,挨个调过去

  • 客户端通过移动网络发送N个网络请求,是非常不靠谱的
  • 服务可能用的并非是web友好的协议,例如thrift,无法提供服务。
  • 让重构微服务们变得困难,因为它们被客户端直接依赖了

使用API网关

  • API网关可以调用多个微服务, 然后提供一个“item/detail?id=xxxx”的统一接口
  • API可以顺便做负载均衡、监控、授权和认证等等多种统一功能
  • 【优】封装了应用的内部结构设计,客户端只需要和API网关通信
  • 【优】可以通过服务,自由组合出最适合客户端的API
  • 【劣】你需要单独开发、部署、管理API网关
  • 【劣】API网关可能成为开发的瓶颈,例如开发者暴露新的服务时要更新到API网关

实现API网关

  • 为了API网关的性能和可扩展性,应该支持异步NIO。
  • 在JVM上你可以使用Netty、Vertx、Spring Reactor等NIO框架
  • 在非JVM上你可以使用node.js来实现NIO
  • 你还可以使用Nginx Plus(要钱的)

使用Reactive Programming

  • 对于互不相关的服务,应该同时一起调用。有先后顺序的服务可能要定义好前置和后置。
  • 使用传统的异步+回调的方式来书写组合服务的代码会让你很快陷入回调地狱。
  • Java、Scala、JS中都有响应式的方案,你还可以使用ReactiveX来书写这类代码。

服务调用:

通常有两种调用方式

  • 异步——消息队列
  • 同步——HTTP或者Thrift等

服务发现

  • 过去你通常手动控制服务的ip地址,但是在微服务体系中,你无法做到。
  • 由于各个服务的随时扩容和升级,它们的地址都是在动态变化的。
  • 所以API网关需要有服务注册,服务发现的能力。不论是server-side发现,还是client-side发现。

处理部分失败

  • API网关不可以因为下游的失败而block住,它要根据场景来决定如何处理错误。

    • 例如只是商品推荐服务挂了,商品详情页接口应该仍然返回其他所有数据
    • 如果是商品基础信息挂了,商品详情页接口应该反馈错误给到客户端。
  • 可以返回硬编码打底数据,或者缓存数据。(API网关做, 服务无感知)
  • 安利了一下Netflix Hystrix, 但是似乎已经处于维护状态不再更新了。

3 构建微服务:微服务架构中的跨进程通信

  • 【背景】在monolithic应用中,组件之间互相通过语言级别的方法就可以进行调用,但是在微服务应用中,这些组件都被分布式地部署在不同的机器上的不同容器里。基本每个服务都是一个进程,所以服务们不得不使用跨进程通信(IPC)机制。

交互方式

  • 一对一通信 vs 一对多通信
  • 同步 vs 异步    

            Screen Shot 2019-12-19 at 2.32.43 PM.png

    • request/response: client发起请求然后同步等待响应结果。
    • notifications:client发出一个请求,但并不需要返回,也不等待。
    • request/async response: client发出一个请求,但响应是异步的,在等待响应的过程中,client并不阻塞。
    • publish/subscribe: client发出一条消息,被一个或多个感兴趣的服务消费。
    • public/async responses: client发出一个请求消息,然后等待一段时间来接收感兴趣的服务的返回。
    • 每个服务都可能用上述多种交互方式,例如下图image.png

    定义API

    • 服务的API是一种服务和它的客户端们之间的约定。
    • 使用某种接口定义语言(IDL)非常重要,例如Protobuf。
    • 你甚至可以使用API-first这种方式,也就是先定义API再实现它,来进行开发。
    • API定义依赖于你使用的IPC机制,例如使用消息那么API就需要消息通道和消息类型。

    更新API

    • 在monolithic的app里,你一般改了API后,去代码里直接改所有的调用处.
    • 在微服务体系里, 更新API会困难得多,你没办法让你服务的消费者挨个更新。你可能要增量地添加新版本的服务,线上可能同时存在两个版本的API,这是一种非常重要的更新策略。
    • 为了实现上述能力,一种可行的方式是添加版本号,让多个版本的API同时存在。

    处理部分失败

    • 在微服务体系中,部分失败是非常常见的,因为所有服务们都在不同的进程里。
    • 假设有一个场景,你的产品详情页里需要使用推荐服务,而此时推荐服务挂掉了:image.png

    如果你按照一直等待去设计,那么很有可能会消耗掉你所有的线程,导致产品详情服务彻底挂掉

    • 下面有4条由Netflix推荐的部分失败错误处理策略

      • 网络超时:永远不要一直等待,一定要有超时重试/超时失败机制。
      • 限制等待中请求数量:等待中的请求应该有一个上限值,一旦上限达到了,就不应该再处理请求,这些超出限额的请求应该立即失败。
      • 短路模式:当失败率达到一定程度时,后续的请求应该立即失败,不再请求。短路后,应该每隔一段时间重试,如果重试成功,那么就不再短路。
      • 提供降级:提供失败时的降级逻辑,例如获得缓存数据。

    IPC机制

    • 异步、基于消息的IPC机制

      • client向某服务发送一条消息,但并不等待它。如果这次调用需要返回,被调用服务会也异步通过消息返回给client。client完全基于异步,也就是不等待的方式来编写。
      • 消息一般由header和body构成,并且通过channel来交换。
      • 两种消息channel:1. 点对点 2. pub/sub
      • 案例:image.png
      • 出行服务发一条消息“一个新出行创建了!”到名叫“新的出行”的pub/sub型channel中,通知所有感兴趣的服务(比如派单服务)。派单服务找到了合适的司机以后,发送一条消息“司机接单了!”到一个名叫“派单”的pub/sub型channel中,通知所有感兴趣的服务。
      • 消息队列实现有非常多种:RabbitMQ、Kafka、ActiveMQ.....
      • 用消息机制的优点:

        • 把服务的consumer和provider通过消息解耦了。
        • 消息可堆积,比起实时调用有更高的容错率。
        • 调用方式也解耦了,consumer和provider之间只需要遵守消息约定即可。
      • 用消息机制的缺点:

        • 更高的运维复杂性,消息系统也是一个要维护的系统啊!
        • 要实现请求-响应这种同步请求会更加麻烦
        • 【作者补充】消息队列的高可用、不被重复消费、可靠性、顺序性都是非常复杂的课题。
    • 同步、请求/响应型的IPC

      • 通常来说,一个线程会在等待请求时阻塞。有些可能已经通过Future或者Rx Observables这种Ractive Pattern的东西把它变成了异步的方式。
      • 但是在这种类型的IPC里,client通常希望请求能够尽快及时地返回。
      • 常见的主要由两种协议:Rest、Thrift
      • 基于HTTP方式的协议(Rest)的好处:

        • 简单熟悉
        • HTTPAPI可以直接在浏览器、Postman、curl等多种环境下测试。
        • 直接支持 请求/响应 模式
        • 没有任何中间代理,系统架构简单
      • 基于HTTP方式的协议(Rest)的坏处:

        • 只支持 请求/响应 模式
        • provider和consumer都必须活着不能挂
      • 基于HTTP方式的一些IDL或平台:RAML、Swagger
      • Thrift

        • 使用一个C风格的IDL来定义API,并且使用Thrift编译器来生成客户端和服务端代码模板。
        • 支持C++、Java、Pyhton、Ruby、Erlang、Node.js
        • Thrift方法可以返回空值,也就是可以实现单向的通知,并不一定要返回。
        • 支持JSON/二进制等格式
    • 消息格式

      • 不管用什么方式和语言,最好选择语言无关的消息格式,你无法保证将来你不换语言。
      • 在文本和二进制中,tradeoff大概就是包大小or人类可阅读性。

    4 微服务架构中的服务发现

    为什么使用服务发现?

    • 你以前,你可能把要调用的IP放在配置里,然后直接调用
    • 但是在云时代的微服务应用中,你应该不太能这么做,看图:

    image.png

    • 你会发现,服务实例们都有着动态分配的网络位置,而且这些位置由于扩容、更新等等还在变化。
    • 目前主要由两种服务发现:client侧服务发现、server侧服务发现

    client侧服务发现

    image.png

    • 这种模式下,consumer决定了所调用服务的网络地址。所有的服务provider,都把自己的网络地址,注册到服务注册中心,consumer拿到了一坨ip地址之后,自己选择一个load-balancing策略,然后调用其中一个。
    • 服务Provider在启动时向注册中心注册服务,在结束进程时给注册中心注销服务。服务的健康通过心跳机制来进行保障。
    • Netflix OSS是一个client侧服务发现的好例子,Netflix Eureka是一个REST型服务注册中心。
    • Netflix Ribbon是一个IPC客户端,能够和Eureka合作,提供load-balancing。
    • 优点:1. 简单直接  2. 由于consumer决定了路由,可以做灵活的、应用特定的负载均衡策略
    • 缺点:耦合了consumer和服务注册中心,你必须给每个编程语言实现consumer侧的服务发现逻辑。

    server侧服务发现

    image.png

    • consumer通过一个load balancer来请求provider,load balancer要请求服务注册中心来获得所有可提供服务的实例以及它们的网络地址。也就是load-balancer决定了到底要请求谁。
    • 亚马逊的ELB就是一个server侧服务发现路由。ELB把服务注册直接做到了自己里面。
    • Nginx也可以充当server侧服务发现中的load balancer,比如这篇文章里,你可以使用Consul Template来动态更新nginx的反向代理。
    • 一些部署环境例如K8S或者Marathon,在集群里的每个宿主上都运行Proxy,这个Proxy就扮演了server侧服务发现中的load-balancer。如果你想给一个服务发请求,一个consumer必须通过proxy来调用。
    • 优点:

      • consumer和服务发现是完全解耦的,无脑请求load-balancer就好了。
      • 不用再给每个语言实现一套load-balancing机制了。
      • 有些部署环境甚至直接提供了这种load-balancing服务。
    • 缺点:如果没有提供好的load-balancing服务,你就要自己实现。

    服务注册中心

    • 概念详解

      • 它就是一个服务实例们网络位置的数据库。
      • 它必须高可用,并实时更新。
      • 它其实是一坨实例们,这些实例们要通过某种副本协议来保持一致性
    • 比如Netflix Eureka,它是基于REST的。它通过POST方法来注册服务,每30秒通过PUT方法刷新一次,通过DELETE方法删除服务,通过GET方法来获得一个可用的服务实例。
    • Netflix为了实现服务注册的高可用性,通过运行N个Eureka实例,使用DNS的TEXT记录来存储Eureka集群的配置,这个配置也就是一个可用区->一组网络地址的map。当一个新的Eureka启动,它就请求DNS来获得Eureka集群配置,并且给它自己一个新的IP。Eureka的clients,services就请求DNS来发现Eureka实例们的地址,并且会尽可能选相同可用区的Eureka实例。
    • 其他的服务注册中心们还有

      • etcd:K8S和Cloud Foundry用的它
      • consul
      • Zookeeper:大家最熟悉了
    • 在K8S、Marathon、AWS中并没有显式的、单独的服务注册中心,因为它们是内置的基础设置。

    服务注册的方式

    • 目前主要有两种方式来处理服务的注册和注销:自注册模式和三方注册模式。
    • 自注册模式image.png

      • 这种情况下,服务实例自己负责注册和注销它提供的服务,同时服务自己还需要不停地发送心跳包来阻止自己的注册过期。
      • Netflix OSS Eureka client是一个很好的自注册例子。Spring Cloud中也可以直接使用注解来实现注册方式。
      • 优点:简单直接、不需要其他系统组件。
      • 缺点:把服务实例和注册中心耦合起来了,你要实现各个编程语言的注册代码。
    • 三方注册模式image.png

      • 顾名思义,服务实例们要向一个注册管理者(registrar)来进行注册,而注册管理者也通过健康检查机制来跟踪服务实例们的情况,随时注销挂掉的服务实例。
      • 有一个开源的注册管理者叫做Registrator ,它能自动注册和注销以docker container方式部署的服务实例。Registrator支持etcd和Consul。
      • 还有一个有名的注册管理者是NetflixOSS Prana,它主要是为了非JVM语言设计的,它是一个sidecar应用,也就是说它跟着每一个服务实例运行。Prana和Eureka配合,向Eureka进行注册和注销服务。
      • 注册管理者,也是很多部署环境的内置基础设施,例如在AWS EC2和K8S中都是。
      • 优点:服务和服务注册中心解耦、你也不再需要去实现特定语言的注册逻辑。
      • 缺点:如果部署环境没提供注册管理者,那你就要自己实现。

    5 微服务中事件驱动的数据管理

    背景

    • 在一个monolithic的应用中,使用关系型数据库的一个好处是,你可以使用符合ACID原则的事务。
    • ACID原则

      • Atomicity 原子性: 变更要么都成功,要么都失败。
      • Consistency 一致性:数据库的状态永远是一致的。
      • Isolation 独立性:事务之间不会有交错执行的状态(因为可能会导致数据不一致)。
      • Durability 持久性:事务成功后,修改是持久的。
    • 另一个好处是你可以使用SQL,你可以轻松地进行多表操作,数据库帮你解决大部分性能问题。
    • 遗憾的是当切换到微服务架构以后,这些好处你就不再能够享受,因为所有的数据都被各自的微服务所拥有,也就是说他们拥有各自独立的数据库,数据的访问只能通过API层面来进行。
    • 来吧,更糟糕的是:不同的微服务可能还用了不同类型的数据库。例如NoSQL系列的,graph型的(例如Neo4j)。所以微服务架构中通常混用各种类型的数据库,我们称之为polyglot persistence 。

    挑战1:如何在多个微服务中实现事务

    • 假设有一个在线的B2B商店,“客户服务”维护了客户信息,“订单服务”管理订单们,并且保障一个新订单不会用完客户的余额。
    • 在过去的monolithic版的应用中,我们用一个事务,就能搞定“检查余额够不够+创建订单”这件事。
    • 但是在微服务体系中,我们的ORDER表和CUSTOMER表现在是私有的:image.png
    • 订单服务并无法直接访问CUSTOMER表,它只能通过客户服务提供的API来间接修改CUSTOMER表。也许你可以使用分布式事务,也叫two-phase-commit(2PC)来解决。但是在现代化的应用中,你很难使用2PC。著名的CAP theorem告诉我们,在ACID中你要抉择要C还是A,而一般更好的选择都是A。而且,在很多NoSQL的数据库中根本不支持2PC。

    挑战2:如何进行多表查询

    • 假设你的客户端需要展示客户的信息以及他所有的订单。
    • 如果订单服务提供了根据客户id查它订单的服务,那么你可以直接调这个服务。
    • 但是如果订单服务,没有提供这个服务,比如只支持按照订单id查询时,你该怎么办呢?

    事件驱动架构

    • 在大部分应用中,解决方案就是使用数据驱动架构。当一个值得注意的事情发生了以后,这个微服务发出一个事件,比如“它更新了某个entity”这件事。其他对此感兴趣的微服务订阅这些事件,当它们收到这件事情时,就做它们自己的业务逻辑,比如把自己对于这个entity的冗余字段也更新一下。
    • 你可以使用事件来实现跨越多个服务的事务,这样的一个事务,包括的许多步骤,每个步骤包括一个微服务更新自己的业务逻辑entity,并且发出一个事件通知下一些微服务。来看下面这个流程:

      • 图1:订单服务创建了一个新订单,发出一个“一个订单创建辣!!”的消息

            image.png

    • 图2:客户服务消费这个“一个订单创建辣!!”消息,并且给这个订单预留了余额,然后发送一个“已预留余额”事件

              image.png

    • 图3:订单服务消费“余额已预留”事件,并且把订单状态设为“创建成功”

    image.png

    - 这里面需要假设
    - 每个服务自动地更新数据库,并且发布事件
    - 消息代理必须保证事件至少都被交付了一次
    • 尽管如此你也只是实现了事务,没有实现ACID的事务,这仅仅是提供了弱保障,例如eventual consistency. 这样的事务模型被称为BASE model.
    • 【解决查询问题】你还可以使用事件来维护一个额外"物料化视图",这个视图包含的预先join好的,来自多个微服务的数据。例如可以专门有一个“客户订单视图”服务,来专门订阅相关事件(客户服务产生的事件、订单服务产生的事件等),然后更新这个视图。image.png

      • 你可以使用文档化数据库例如MongoDB来实现这个额外视图,并且给每一个客户都存一个document。这样当有一个客户来的时候,你可以光速地反馈这个客户的相关订单,因为你已经事先存好了。
    • 事件驱动架构的优点

      • 它使得跨多个服务的普通事务得以实现。
      • 它让应用可以通过“物料化视图”实现快速查询。
    • 事件驱动架构的缺点

      • 编程将更加更加复杂
      • 你必须得实现补偿事务(回滚等)来从应用级错误中恢复。例如:当你检查余额失败时,你应该取消订单。
      • 应用将要面对数据不一致的情况,例如“物料化视图”中的数据并非最新的。而且还要处理事件相关的各种问题,比如重复消费(幂等性),漏消费等问题(其实也就是消息队列常见问题系列)。

    实现原子性

    • 【背景】在事件驱动架构里,你还会遇到一个原子性问题

      • 假设订单服务要插入订单表,同时发出一个“订单创建辣!”事件,这两步操作必须要原子地完成。
      • 假设服务在插入了订单表,发出事件之前挂掉了,那么系统就会出现一致性问题。
      • 通常标准的做法是使用分布式事务,但是如上面所说(比如CAP theorem),这并不是我们想做的。
    • 使用本地事务完成发送事件

      • 这个操作有个术语叫做multi‑step process involving only local transactions
      • 借助本地事务,其实就是你要一个本服务的事件表,它的作用类似消息队列:image.png

        • 事务1:订单服务插入一个新订单,并且在事件表里插入一个新的订单创建事件。
        • 事务2:事件发送线程读取事件表找到未发送的事件,更新时间并标记事件已发送。
        • 【笔记】这样就保障了“插表+创未发事件”和“事件发送并更新事件状态”的原子性,首先这两个因为是事务所以一定全成功或者全失败,其次是万一在两者之间的时候挂掉了,重启以后事件发送线程还会继续事务性地读取未发事件并重新发送。
      • 优势:不依赖2PC(分布式事务)也能保障每次更新的原子性,发送的也是仍然是业务逻辑层面的事件。
      • 劣势:写代码容易漏写(??我反正没看懂原文啥意思,因为复杂就特么能漏写??)。当使用NoSQL型数据库时会很困难,因为它们的查询能力和事务性都比较差。
    • 挖掘数据库事务日志

      • 另一种不用2PC实现原子性的方法就是,有一个单独的线程去挖掘数据库事务或者commit日志。也就是数据库被更新了以后,就有日志,而这个挖日志线程就读日志,然后发消息给消息代理。image.png
      • 一种实现方式就是使用开源的LinkedIn Databus ,它可以挖掘Oracle事务日志并发送消息。LinkdeIn用它来保障多个数据存储的一致性。
      • 另一个例子是streams mechanism in AWS DynamoDB,是一种托管的NoSQL数据库,它有一种DynamoDB流,按照时间顺序记录了24小时内的增删改查。应用可以读这些变化来发送事件。
      • 优势:保障了每次更新都可以发送事件。事务日志也可以简化应用逻辑,因为把事件发送和应用业务逻辑拆分开来了。
      • 劣势:每个数据库的事务日志都不太一样,并且随着数据库版本变化,而且你还需要做高层业务逻辑到底层数据库日志的转换。
    • 使用数据溯源

      • 数据溯源是:不直接存储实体现在的状态,它则是存储数据变化的事件(是不是想到了Redux的Action和时间旅行?)。应用会回放所有的数据变化事件来更新实体的状态。相当于先事件再业务了,所以保障了原子性。
      • 举个🌰,按照传统的做法,一个ORDER实体对应数据库里ORDER表,但是在数据溯源方式里,表里存的都是状态变化:订单创建、确认、发货、取消等等。image.png
      • 事件都存储在了Event Store,这个Event Store其实就像架构里的事件代理。它提供了其他服务订阅这些事件的API。
      • 优势:

        • 顺便就实现了事件代理,一举两得。
        • 它用一种微服务的方式解决了数据一致性问题。
        • 由于是持久化事件而非实体,他基本避免了 object‑relational impedance mismatch problem
        • 业务逻辑和业务实体耦合程度低,这让它具备更好的迁移性。
      • 劣势:它是一种完全不一样的编程范式,有陡峭的学习曲线。Event Store只直接支持按主键查询业务实体。你必须使用Command Query Responsibility Segregation来实现查询。

    6 选择一种微服务部署策略

    动机

    • 部署monolithic应用时,你通常是在N台物理机(或虚拟机)上部署M个相同的服务实例。这种部署要比微服务要更直接、简单。
    • 微服务通常包括上百的服务,并且它们用了不用的语言和框架。为了让某个功能运行,你可能要起一坨服务才能work。每个服务都有自己单独的部署、资源消耗、扩容、监控的方式。所以微服务的部署虽然很困难,但是也必须要保障快速、可靠、低耗。

    每个宿主机多个服务实例模式

    • 这种模式就是,你在多台机器上部署多个不同的服务实例,不同的服务实例在不同的端口上。

    image.png

    • 这种模式还有很多变种,例如

      • 每一个服务实例是一个或一组进程

        • 部署一个Java服务实例作为一个web应用放在Apache Tomcat 上面。
        • 一个Node.js服务实例可能包含一个父进程和多个子进程。
      • 在同一个进程或进程组运行多个服务实例

        • 你可以在同一个Tomcat上运行多个java web应用
        • 在OSGI容器上运行多个OSGI的bundle
    • 优势

      • 资源利用相对合理有效,它们共享操作系统和服务器。例如:多web应用共享tomcat和JVM。
      • 部署非常快速,你只要把代码或者构建产物copy到机器上然后启动就行了。
      • 启动服务非常迅速,因为服务进程就是它自己,它就启动自己就好了。
    • 劣势

      • 服务实例之间没有太多隔离,就算你可以监控每个服务用了多少资源,你没办法限制每个服务实例能用多少。有一些服务也许可以消耗掉所有的内存和CPU。如果是同一个进程下的多个服务实例,就更加没有隔离了,他们可能共享比如JVM堆。
      • 运维团队必须知道部署你这个服务的细节,因为不同的应用实现方式都不一样,语言、框架、依赖、环境都可能不太一样。这会增加运维的风险。

    每个宿主机一个服务实例模式

    • 另一种方式就是,每个宿主机只有一个服务实例。这种模式下主要由两种子模式:每个虚拟机一个服务实例和每个容器一个服务实例
    • 每个虚拟机一个服务实例

      • 你把每一个服务都打成一个虚拟机镜像,例如 Amazon EC2 AMI。每个服务实例都是一个运行这个镜像的虚拟机image.png
      • Netflix就用这种方式来部署它的视频串流服务,它使用 Aminator来把每个服务打成AWS EC2 AMI,每个服务实例运行在一个EC2身上。
      • 还有很多其他工具你可以用来构建你自己的VM,你可以用一些持续集成工具(比如Jenkins)来调用Animator来打包成虚拟机镜像。Packer.io 也是一个不错的选择,它支持各种虚拟化技术,不仅只有EC2。
      • CloudNative有一个叫Bakery的服务,它是一个用来创建EC2 AMI的SaaS。你可以配置你的CI服务器来调用Bakery(当然前提是你过了你的测试),Bakery会帮你把你的服务打包成成一个AMI。
      • 优势

        • VM之间相互独立,拥有固定的CPU和内存,不会互相攫取资源。
        • 可以借助成熟的云计算基础设施,例如AWS,来快速扩张和部署。
        • 把你的服务封装成了VM以后,就是黑盒了,部署不需要关心细节。
      • 劣势

        • 资源利用更加低效,因为有时候服务并不能榨干虚拟机的性能,而虚拟机就会有性能剩余。
        • 基于上一点,很多云服务按照虚拟机数量收费,并不管你的虚拟机忙还是闲。
        • 当部署新版本的虚拟机时通常很慢,因为虚拟机大小通常都是比较大的,并且初始化,启动操作系统等等也需要时间。
        • 维护虚拟机本身也是一个很重的担子。
    • 每个容器一个服务实例模式

      • 每个服务实例运行在它自己的容器里。容器是一种 virtualization mechanism at the operating system level,你可以简单理解为更轻量级更厉害的虚拟机。一个容器包含了一个或多个运行在沙箱里的进程。你可以限制每个容器的CPU和内存等资源。常见的容器技术有DockerSolaris Zones.image.png
      • 为了使用这种模式,你要把你的服务打包成一个容器镜像,容器镜像包含了一个完整的linux文件系统,服务本身的代码,相关的依赖等,一切的目的都是为了让这单个服务跑起来。比如你要打包一个java应用的容器镜像,你可能就需要一个java运行时,一个Tomcat,以及你编译后的jar包。
      • 当你需要在一个机器上运行多个容器的时候,你可能就需要服务编排工具了,例如Kubernetes 或者 Marathon。它基于容器对资源的需求以及现在剩下的资源,来决定容器到底放哪里。
      • 优势

        • 和VM一样,隔离了你的每个服务实例。
        • 和VM一样,封装了你使用的技术,容器可以不关心细节就部署。
        • 不同于VM,容器更轻,构建也更快,启动也更快.
      • 劣势

        • 容器经常部署在按VM数量收费的IaaS上,也就是说,你可能要花额外的钱。
    • 容器和VM的边界正在慢慢消失,两者正在互相靠拢。

    Serveless部署

    • AWS Lambda就是一个非常典型serveless部署,他支持你用各种语言写代码,这些代码作为一个函数,可以直接响应请求或事件。AWS会帮你解决下面的机器、内存等物理需求,你只需要关心业务逻辑就好了。
    • 一个Lambda函数是一个无状态服务,它可以直接和AWS其他的服务交互,比如当S3插进来一个新东西的时候,可以让一个函数响应并做后处理。函数还可以调用其他三方服务
    • 你有这么些方法可以调用一个函数

      • 直接通过你的服务来请求。
      • 通过AWS其他服务产生的事件触发。
      • 提供给AWS的Api gateway来提供HTTP服务。
      • 周期性的运行,基于一种cron的时间表。
    • 你能看到,AWS Lambda是一种非常方便的部署微服务的方式,并且它还基于请求收费,你只需要为你的使用量付费。你也不用关心底层的IT基础设施.
    • 劣势

      • 它不适合用来做长时间运行的服务,比如要从某个消息代理持续消费消息.
      • 请求必须在300秒以内完成.(AWS的限制吧)
      • 服务必须无状态,而且上一次函数调用和下一次函数调用很可能不在一台机器上。

    7 从一个单应用重构为微服务

    • 你最好不要使用“Big Bang”策略,也就是完全重写你的服务。既危险又耗时。
    • 你可以增量性地重构你的应用,你可以逐渐地构建一个基于微服务的新应用,和你的原来应用同时运行。随着时间的推移,所有的功能都被慢慢的从原应用迁移到微服务。

    策略1 停止挖坑

    • 不要继续把这个monolithic的天坑继续挖了,如果要加新功能,不要加到这个大应用里。你把新需求用微服务的模式来做。image.png
    • 如图,你新加了一个request router,把新功能的请求路由到你的新微服务里,老功能路由到老monolithic应用里。有点像API网关。
    • 你还加了一坨胶水代码,其实就是为了新老服务之间互相调用,因为他们之间也可能有交互。你可以用RPC、直接访问数据库、访问老数据库同步过来的数据等方式来实现这种调用。
    • 策略优势:它阻止了原应用变得更加难以维护。新开发的服务可以独立地开发和部署。你可以立即开始享受微服务带给你的好处。
    • 但这个策略没有对原应用做任何优化,你需要看策略2来如何改造原应用。

    策略2 分离前后端

    • 这个策略主要思路是,帮你分离展示层和业务逻辑层以及数据访问(DAO)层,从而做到让原来的monolithic应用缩小一些。通常一个典型的企业级应用有这些组件层:

      • 展示层:处理HTTP请求和展示web界面的组件们。
      • 业务逻辑层:应用实现业务逻辑的核心组件们。
      • 数据访问层:应用访问数据和消息代理的基础组件们。
    • 有一种常见的做法,你可以把你的应用按照下图,拆分成两个子应用:image.png

      • 一层子应用包括了展示层。
      • 另一层子应用包含了业务逻辑和数据访问。
    • 策略优势

      • 它让你能够单独地部署和扩容两个应用,它们各自都可以快速迭代
      • 由于业务逻辑层和数据访问层单独抽离了一个应用,你的新微服务现在可以调用这坨UI无关的服务了。
    • 然而这个策略仍然只是一个部分解决方案,有可能拆分后两个应用还是会变成难以维护的monolithic应用,所以你还需要看策略3。

    策略3 抽取服务

    • 这个策略就是要把现有的在你原应用里的模块转换成单独的微服务。每次你抽出来一个新的微服务,原应用就变小了。只要你抽得足够多,原来的这个大应用就会消失或者干脆也变成一个微服务。
    • 转换成微服务的优先级

      • 首先你最好先抽象容易抽象的模块,这样你就能先积累抽象微服务的经验
      • 然后你应该优先抽取能给你带来最大收益的模块,所以你需要给你的模块排一个优先级。
      • 你还可以先抽象要特别的物理资源的模块,比如某个模块特别需要内存数据库,你可以先抽这个模块,然后把它放到内存比较大的环境里。
      • 抽象模块的粒度,可以按照这样一个简单原则:比如某个模块和其他的模块的交流都可以通过异步消息完成,那么这个模块就可以抽出来。
    • 如何抽取一个模块

      • 首先要定义抽出来的模块如何和系统进行交互,通常是一组双向的API。但通常都比较难,因为这种API会和系统耦合得比较多。用了Domain Model pattern 的就更难重构了。
      • 一旦你实现了粗粒度的接口,你就要把模块抽出来做一个单独的服务了。这时候为了同心,你还需要使用IPC机制。image.png
      • 在上面的例子中,模块Z是要被抽象出来的模块。它的组件被模块X和模块Y使用了,所以

        • 第一步就是要定义出一组粗粒的API来让X和Y通过API和Z交互。
        • 第二步就是把模块弄成单独的服务。这时候你需要IPC通信来完成他们之间的跨服务调用。
      • 你甚至可以按照新的API来重新写这个抽象的服务。你每抽出来一个服务,你就朝着微服务方向前进了一步,随着时间推移,你的原应用终将消散,而你就把它演进成了一套微服务。
    查看原文

    赞 1 收藏 0 评论 0

    PixelMage 关注了标签 · 2019-12-22

    java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的 Java 程序设计语言和 Java 平台(即 JavaSE, JavaEE, JavaME)的总称。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    Java编程语言的风格十分接近 C++ 语言。继承了 C++ 语言面向对象技术的核心,Java舍弃了 C++ 语言中容易引起错误的指針,改以引用取代,同时卸载原 C++ 与原来运算符重载,也卸载多重继承特性,改用接口取代,增加垃圾回收器功能。在 Java SE 1.5 版本中引入了泛型编程、类型安全的枚举、不定长参数和自动装/拆箱特性。太阳微系统对 Java 语言的解释是:“Java编程语言是个简单、面向对象、分布式、解释性、健壮、安全与系统无关、可移植、高性能、多线程和动态的语言”。

    版本历史

    重要版本号版本代号发布日期
    JDK 1.01996 年 1 月 23 日
    JDK 1.11997 年 2 月 19 日
    J2SE 1.2Playground1998 年 12 月 8 日
    J2SE 1.3Kestrel2000 年 5 月 8 日
    J2SE 1.4Merlin2002 年 2 月 6 日
    J2SE 5.0 (1.5.0)Tiger2004 年 9 月 30 日
    Java SE 6Mustang2006 年 11 月 11 日
    Java SE 7Dolphin2011 年 7 月 28 日
    Java SE 8JSR 3372014 年 3 月 18 日
    最新发布的稳定版本:
    Java Standard Edition 8 Update 11 (1.8.0_11) - (July 15, 2014)
    Java Standard Edition 7 Update 65 (1.7.0_65) - (July 15, 2014)

    更详细的版本更新查看 J2SE Code NamesJava version history 维基页面

    新手帮助

    不知道如何开始写你的第一个 Java 程序?查看 Oracle 的 Java 上手文档

    在你遇到问题提问之前,可以先在站内搜索一下关键词,看是否已经存在你想提问的内容。

    命名规范

    Java 程序应遵循以下的 命名规则,以增加可读性,同时降低偶然误差的概率。遵循这些命名规范,可以让别人更容易理解你的代码。

    • 类型名(类,接口,枚举等)应以大写字母开始,同时大写化后续每个单词的首字母。例如:StringThreadLocaland NullPointerException。这就是著名的帕斯卡命名法。
    • 方法名 应该是驼峰式,即以小写字母开头,同时大写化后续每个单词的首字母。例如:indexOfprintStackTraceinterrupt
    • 字段名 同样是驼峰式,和方法名一样。
    • 常量表达式的名称static final 不可变对象)应该全大写,同时用下划线分隔每个单词。例如:YELLOWDO_NOTHING_ON_CLOSE。这个规范也适用于一个枚举类的值。然而,static final 引用的非不可变对象应该是驼峰式。

    Hello World

    public class HelloWorld {
        public static void main(String[] args) {
            System.out.println("Hello, World!");
        }
    }

    编译并调用:

    javac -d . HelloWorld.java
    java -cp . HelloWorld

    Java 的源代码会被编译成可被 Java 命令执行的中间形式(用于 Java 虚拟机的字节代码指令)。

    可用的 IDE

    学习资源

    常见的问题

    下面是一些 SegmentFault 上在 Java 方面经常被人问到的问题:

    (待补充)

    关注 142201

    PixelMage 关注了标签 · 2019-12-22

    javascript

    JavaScript 是一门弱类型的动态脚本语言,支持多种编程范式,包括面向对象和函数式编程,被广泛用于 Web 开发。

    一般来说,完整的JavaScript包括以下几个部分:

    • ECMAScript,描述了该语言的语法和基本对象
    • 文档对象模型(DOM),描述处理网页内容的方法和接口
    • 浏览器对象模型(BOM),描述与浏览器进行交互的方法和接口

    它的基本特点如下:

    • 是一种解释性脚本语言(代码不进行预编译)。
    • 主要用来向HTML页面添加交互行为。
    • 可以直接嵌入HTML页面,但写成单独的js文件有利于结构和行为的分离。

    JavaScript常用来完成以下任务:

    • 嵌入动态文本于HTML页面
    • 对浏览器事件作出响应
    • 读写HTML元素
    • 在数据被提交到服务器之前验证数据
    • 检测访客的浏览器信息

    《 Javascript 优点在整个语言中占多大比例?

    关注 176427

    PixelMage 关注了标签 · 2019-12-22

    前端

    Web前端开发是从网页制作演变而来的,名称上有很明显的时代特征。在互联网的演化进程中,网页制作是Web 1.0时代的产物,那时网站的主要内容都是静态的,用户使用网站的行为也以浏览为主。2005年以后,互联网进入Web 2.0时代,各种类似桌面软件的Web应用大量涌现,网站的前端由此发生了翻天覆地的变化。网页不再只是承载单一的文字和图片,各种富媒体让网页的内容更加生动,网页上软件化的交互形式为用户提供了更好的使用体验,这些都是基于前端技术实现的。

    Web前端优化
    1. 尽量减少HTTP请求 (Make Fewer HTTP Requests)
    2. 减少 DNS 查找 (Reduce DNS Lookups)
    3. 避免重定向 (Avoid Redirects)
    4. 使得 Ajax 可缓存 (Make Ajax Cacheable)
    5. 延迟载入组件 (Post-load Components)
    6. 预载入组件 (Preload Components)
    7. 减少 DOM 元素数量 (Reduce the Number of DOM Elements)
    8. 切分组件到多个域 (Split Components Across Domains)
    9. 最小化 iframe 的数量 (Minimize the Number of iframes)
    10. 杜绝 http 404 错误 (No 404s)

    关注 194509

    PixelMage 关注了标签 · 2019-12-22

    python

    Python(发音:英[ˈpaɪθən],美[ˈpaɪθɑ:n]),是一种面向对象、直译式电脑编程语言,也是一种功能强大的通用型语言,已经具有近二十年的发展历史,成熟且稳定。它包含了一组完善而且容易理解的标准库,能够轻松完成很多常见的任务。它的语法非常简捷和清晰,与其它大多数程序设计语言不一样,它使用缩进来定义语句。

    Python支持命令式程序设计、面向对象程序设计、函数式编程、面向切面编程、泛型编程多种编程范式。与Scheme、Ruby、Perl、Tcl等动态语言一样,Python具备垃圾回收功能,能够自动管理存储器使用。它经常被当作脚本语言用于处理系统管理任务和网络程序编写,然而它也非常适合完成各种高级任务。Python虚拟机本身几乎可以在所有的作业系统中运行。使用一些诸如py2exe、PyPy、PyInstaller之类的工具可以将Python源代码转换成可以脱离Python解释器运行的程序。

    Python的主要参考实现是CPython,它是一个由社区驱动的自由软件。目前由Python软件基金会管理。基于这种语言的相关技术正在飞快的发展,用户数量快速扩大,相关的资源非常多。

    关注 137837

    PixelMage 关注了标签 · 2019-12-22

    spring

    Spring是于2003 年兴起的一个轻量级的Java 开发框架,由Rod Johnson 在其著作Expert One-On-One J2EE Development and Design中阐述的部分理念和原型衍生而来。

    关注 28507

    PixelMage 关注了标签 · 2019-12-22

    linux

    Linux是一种自由和开放源代码的类Unix计算机操作系统。目前存在着许多不同的Linux,但它们全都使用了Linux内核。Linux可安装在各种各样的计算机硬件设备,从手机、平板电脑、路由器和视频游戏控制台,到台式计算机,大型机和超级计算机。

    Linux家族家谱图,很全很强大!! 图中可以清楚的看出各个Linux发行版的血缘关系。无水印原图:http://url.cn/5ONhQb

    关注 79718

    认证与成就

    • 获得 1 次点赞
    • 获得 1 枚徽章 获得 0 枚金徽章, 获得 0 枚银徽章, 获得 1 枚铜徽章

    擅长技能
    编辑

    (゚∀゚ )
    暂时没有

    开源项目 & 著作
    编辑

    (゚∀゚ )
    暂时没有

    注册于 2019-12-22
    个人主页被 542 人浏览