Giter Club home page Giter Club logo

blog's People

Contributors

e2tox avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

blog's Issues

Serverless + TypeScript:独立开发者的神兵利器

一个人开发

困扰独立开发者的第一个巨大问题就是目前的项目架构过于复杂,超出了一个人的能力范围。那么有没有一种方法,能够在普通人的能力范围之内,独立完成并交付一个项目呢?

第二个巨大问题就是写了那么多有意思的项目,结果没地方展示出来?心有不甘!买一个服务器?可是我的月浏览量只有10多个!!!

答案就是:Serverless + TypeScript

TypeScript是目前唯一的端到端(前端到后端,还有小程序)开发语言,而 Serverless 则可以帮你完成繁琐的 DevOps 的工作。掌握了这两个技能,你就拥有了造物主的能力。 可以把所有精力集中到功能的开发上面去。

全端开发框架

AgentFramework 将这种能力发挥得淋漓尽致,也是世界上第一个全端开发框架。

建设中的 https://agentframework.com/ 是一个 100% 建立在Lambda上的Web应用程序,可以适配Vue, Angular等任何前端框架,特点是:持续发布、永远在线、不需要维护。

我忘记什么时候发布了,至少1年了把,没有任何维护,它居然一直运行的好好的!

关键是,它不用花1分钱。

简直爽呆了!

Screen Shot 2020-09-03 at 1 00 00 AM

数据大师开篇:Mongodb的数据类型真的是JSON吗?

前言

大家都知道使用 Mongodb 来查询数据返回的结果是JSON对象,很多框架又给这些对象加上 JSON Schema 来验证这个对象是不是符合定义,这样搞来搞去,那不就搞成MySQL了吗?这样来使用NoSQL数据和SQL数据库又有什么差别呢?你是不是有这样的疑问?带着这些疑问我们看下面一个例子

引子

我们要设计一个账单系统,需要包含:电费账单、水费账单、宽带费账单一共3种账单,每种账单都有不同的属性,字段也不一样,但是,都包含有账单名称、账单金额和最后缴费期限三个字段。你该如何设计这个数据库?是用MySQL好呢?还是用Mongodb好呢?

当然林老师这里肯定就不会用MySQL了,要不然标题就不叫Mongodb了

先看看interface是怎么设计的

interface Invoice {
  name: string
  amount: number
  dueDate: Date
}

interface ElectricityInvoice extends Invoice {
  kwh: number
}

interface WaterInvoice extends Invoice {
  ton: number
}

interface HomeBroadbandInvoice extends Invoice {
  bandwidth: number
}

那么接下来的问题是:

是建一个Collection包含全部账单还是三个Collection分别包含一种账单?

如果说建三个Collection,那还不如用MySQL。

正确的做法是建1个Collection同时储存3种账单

那么问题又来了:

如何判断这个JSON对象的类型?

很多人说,加个type就行啦,代码可以这样写

if (invoice.type === 'Electricity') {
   // 处理电费账单
} else if (invoice.type === 'Water') {
   // 处理水费账单 
} else if (invoice.type === 'HomeBroadband') {
   // 处理宽带账单
}

但是这个invoice对象是第三方系统传递过来的,压根就没有type字段

那这样写总行把

if (typeof invoice.kwz !== 'undefined') {
   // 处理电费账单
} else if (typeof invoice.ton !== 'undefined') {
   // 处理水费账单 
} else if (typeof invoice.bandwidth !== 'undefined') { {
   // 处理宽带账单
}

可以的!

第二天老板说:这边还有1000多种类型的订单,全部都给加上

…………

那到底我们又该如何验证这个对象,并且在储存时格式化成符合相关的定义呢?

如果你对这些问题感兴趣,那就一定不要错过林老师的《数据大师》系列文章

无服务器计算:虚拟机、容器、无服务器计算解决的问题及痛点

xaas-faas-696x437

只想写代码

IaaS你除了写代码,还要管理好虚拟机
CaaS你除了写代码,还要管理好容器
PaaS你除了写代码,还要管理好应用程序

可是我只想好好写我的代码!!!

现实很骨感

Q: 你为什么要用IaaS?
A: 老板或者客户要求

Q: 你为什么不用CaaS?
A: 没空学Kubernetes, Docker Swarm, SDN

Q: 你为什么不用PaaS?
A: 没空学AppEngine, Heroku, Apex

Q: 你为什么不用FaaS?
A: 没空学……要学什么都不知道

哈哈哈哈,觉得痛了吗?

如何说服老板或者客户使用(PaaS, FaaS)?

  1. 把专业的事情交给平台去做可以做的更好,除非你的团队有DevOps,或者客户愿意请DevOps
  2. 长期来讲系统会更稳定
  3. 可以缩短开发周期和减少开发经费?这个凭实力吹吧

如何学习FaaS?

  1. 了解FaaS是什么
  2. 了解有哪些FaaS平台
  3. 了解有哪些语言可以使用
  4. 选择一个你看的顺眼的FaaS平台编写一个Hello world小函数

祝大家编程愉快

如何使用正确的姿势让 Ansible 访问有密码保护的 ssh private key?

如果 ssh key 用了密码保护,那么 ansible 在运行的时候,如果有inventory有5个主机,那么就会是这样子

ansible-playbook -i hosts play.yml
Enter passphrase for /root/.ssh/id_rsa: 
Enter passphrase for /root/.ssh/id_rsa: 
Enter passphrase for /root/.ssh/id_rsa: 
Enter passphrase for /root/.ssh/id_rsa:
Enter passphrase for /root/.ssh/id_rsa:

每多一个服务器,都多输入一次 ssh 密码😵

但我只想输入一次密码,怎么搞?答案是 ssh-agent

首先是前戏:

eval "$(ssh-agent)"

然后将受密码保护的 ssh key 增加到 ssh-agent 中,如果有多个,就把每个用到的 key 都 ssh-add 一遍。

ssh-add ~/.ssh/id_rsa

此时运行 ansible 或者 ansible-playbook 就不会再出现密码提示了😎

参考: SSH-Agent-Forwarding

无服务器计算: 如何绕开无服务器计算的计费陷阱

目前主流无服务器计算平台的计费方式最小单位是100毫秒,听起来很美妙是不是?如果只看到这里一定会开心的不得了,为了不破坏对Lambda的美好印象,我建议大部分玩家不要继续往下阅读

没有图大家都不喜欢看,那么接下来以一个部署在Lambda的web应用来举例,下面这个是打开这个网站所需要的时间,我们可以看到,大部分都在100毫秒内完成了,虽然有点不好的预感,但是这个数字勉强能安慰一下自己,网站打开越快越好,越快越好
website-on-lambda-2
(这里炫耀一下,列表中spdy协议是走了共享cdn的资源,免费的,只有h2协议的是走了收费Lambda服务)

接下来点开了其中的一个200毫秒的请求,因为做了服务器端计时,看到Server timing的那一刻,整个人都觉得不好了
website-api-server-timing-2

怀着最后一丝希望,颤抖的打开AWS控制台看看究竟
aws-console-report

这个函数只花了1毫秒不到就完成了,AWS却计入4.76毫秒(也有可能AWS加入了nodejs启动部分的计时),并且按照了100毫秒来计费,也就是说整整是100倍的价格!!!心痛到无法呼吸

因为AWS坚决不改为按1ms计费,为了避免荷包蒙受损失,博主开始了对现有系统的改造,具体过程枯燥且繁琐,这里先讲讲思路,以后如果有足够的动力,我会单独做一个专题讲座。

  1. 将系统从REST改为WebSocket。按照Event driven architecture来设计。
  2. 使用双队列架构,一个队列触发Lambda函数,另外一个队列处理客户端请求。
  3. Lambda触发后,从第二个队列取出合适数量的任务,尽量保证在100毫秒内完成。

通过以上设计,可以充分利用100毫秒的时间处理多个请求,大大减少了账单的费用,换个通俗的说法,改造后的账单打0.5折!!!我会在后续的博客中谈谈事件驱动的应用程序架构设计的几个需要特别关注的地方。如果你有其他的绕开100毫秒计费陷阱的办法,也可以在下面留言,我们一起讨论

祝大家编程愉快~

IoT时代的网络防火墙

简介

F5、Paloalto为数据中心而生,每一台都价格不菲,在IoT时代,你到底还需不需要购买多少个防火墙?如果不部署防火墙,那么如何为你的边缘计算增加安全策略?

《如何为边缘计算增加网络安全策略》

本文属收费咨询服务,请在林老师微信小程序中查看

无服务器计算: AWS 发布的 Firecracker 究竟是什么?

Firecracker (官方介绍 | GitHub) 是AWS在2018年的reInvent大会上首次被提及。它和docker不一样的地方在于Firecracker是完全针对函数式计算平台来设计的,所以在性能、安全和功能的平衡取舍中选择了性能和安全。

Firecracker和KVM的虚拟机类似,但是Firecracker却仅仅提供了几个设备:1个网络设备,1个磁盘设备,1个计时器,1个控制台,还有1个只有一个按键的键盘。比起KVM和Docker简直简单的不能再简单。所以Firecracker受到攻击的面比较窄,比KVM和Docker要更加安全。

在函数计算平台上面,每个函数必须是隔离的,并且要能够快速的启动。在没有Firecracker的时候,AWS的Lambda是通过一个ec2实例来运行函数的,所以首次启动的时候会比较慢,扩容也会有一定的延迟,这个延迟对于用户体验来说有不小的影响。使用了Firecracker之后,Lambda的启动几乎就是瞬间完成了,简直不要太快。因此在一个对实时性要求高,但是不常使用的函数是非常的适合,比如:报警

下面开始我的天马行空:

如果将完整的Web应用部署到Lambda上,可以得到的好处是:Lambda有免费额度,小网站基本不要钱,免去了每月ec2实例的固定费用。访问静态内容比S3还要便宜。如果爆款,Lambda自动扩容,也不用操心扩容问题,简直就是小程序后台的神器。

更新:AWS Lambda增加了Websocket的支持,那么接下来就可以把IoT服务端搬到Lambda上了,我会在后续的博客中谈谈IoT和Lambda的相关实践

巧用ES系列3: 性能优化的利器CodeGen

什么是CodeGen?

很多文章都提到过CodeGen,但是搜遍NodeJS文档都没有任何CodeGen的内容,这是因为CodeGen是一个概念,它的主要两个API就是函数本身 Function 和 AsyncFunction

CodeGen如何提升性能?

在JavaScript中,函数需要接受参数,并且根据参数在执行相应的代码,参数可以从函数调用过程中传递,也可以通过闭包传递,这些传递参数的过程远远比硬编码要慢。因此,我们在知道所有参数的前提下,可以通过硬编码来提高函数的执行效率,这个硬编码就是CodeGen,也就是在函数第一次执行的时候动态的生成硬编码函数,以后每次调用,都可以达到最大性能。

怎么使用CodeGen

Function在JavaScript标准中存在,所以可以直接通过Function构造器构造一个函数

const sum = new Function('a', 'b', 'return a + b');

console.log(sum(2, 6));
// expected output: 8

AsyncFunction在JavaScript标准中不存在,所以必须做一点额外操作来获取AsyncFunction对象

const AsyncFunction = Object.getPrototypeOf(async function(){}).constructor;

const sum = new AsyncFunction('a', 'b', 'return a + b');

sum(2, 6).then(result => {
    console.log(result);
});

如何学习CodeGen

首先要找出程序中影响性能的部分,其次对其进行分析,看看能不能通过硬编码进行改善,如果可以,那就使用CodeGen进行动态硬编码,最后通过调用生成的动态硬编码函数来改善程序性能。

目前 ajv (Another Json Validator) 是CodeGen的一大代表作,是目前最快的JSON Scheme验证器,其就在JSON Schema背后硬编码了验证的逻辑,所以获得巨大的性能优势。

注: 如果运行时允许,WebAssembly 技术可以对 JavaScript 的性能进行更大幅度的提升

祝大家编程愉快

巧用ES系列1: 代码中的三个点 ... 是怎么回事?

本系列文章是主要介绍ES6的各种新特性,并且之后会加入ES7和ES8的内容,以及TypeScript的各项新特性,因为大家时间都很宝贵,所以文章不长,全是干货。每周更新,欢迎小伙伴们订阅。

在阅读JS或者TS脚本的时候,可能会遇到连续的三个点 ... 这种情况,搞得一头雾水,这个其实是ES6新特性:展开运算符 Spread Operator 在ES9中增加了对象的支持

下面是一些经典用例

  1. 一次取到所有 剩余 参数, 这个时候使用arguments会很麻烦,因为要从arguments里面剔除前面已经定义的参数 [评论]
    function register(name: string, age: number, ...args: Array<string>) {
       console.log(name, args)
    }
  1. 修改一个对象但又不想影响原始对象 [评论]
    const origin = { name: 'Jim', role: 'User' }
    //这里注意要修改的属性必须放在 ... 之后,因为新对象的赋值顺序是从左到右
    const altered = { ...origin, role: 'Admin' }
  1. 处理Vue里面的computed属性简直就是神器 [评论]
    computed: {
        ...mapGetters(['CurrentUser']),
        ...mapState(['metadata','users'])
    }
  1. 拼接数组,尤其是要穿插一些奇怪的item的时候 [评论]
    const a = [1,2,3];
    const b = [4,5,6];
    console.log([...a, 99, 100, ...b, 1000]);
  1. 数组降维,把二维数组降维成一维数组 [评论]
    const array2d = [[1,2,3],[4,5,6],[7,8,9]]
    console.log([].concat(...array2d))
    // 数组降维的另外一种方式, nodejs 11+ 支持
    console.log(array2d.flatMap(x=>x))

暂时先写这几个,大家下去多多练习,如果你有其他巧妙的用法,也可以留言,我们可以一起讨论。

祝大家编程愉快~

无服务器计算:IoT时代负载均衡的正确打开方式

前言

智能DNS解决了传统的负载均衡和推荐最优服务器的功能,但是在IoT时代则显得力不从心,因为DNS服务器无法高效的处理上百万的无服务器后端地址。那么如何来设计IoT时代的负载均衡的系统呢?

DNS 负载均衡的局限性

DNS的最重要属性就是缓存时间,在这里缓存却成为了IoT时代负载均衡的累赘,因为无服务器后端每次调用都可能是不同的地址,而DNS必须等到缓存失效才能获得新路由,最少是30秒。

Proxy 负载均衡的局限性

Proxy最大的局限性就是客户端必须创建到Proxy服务器的连接,Proxy服务器往往没有足够的计算能力和宽带处理如此大量的请求,而且客户端到Proxy的延迟也严重影响了客户体验,因此大部分网站都用DNS处理跨区域的负载均衡,然后用Proxy处理区域内的请求

基于 Linux Virtual Server 负载均衡的局限性

LVS技术可以实现高效的代理服务器,但是流量仍然要经过代理服务器的网络,在海量IoT设备流量面前,LVS仍然会遇到瓶颈

IoT时代负载均衡的难点

IoT应用往往使用 Edge Computing,这将会导致数百万的后端服务地址,即要为当前客户端从上百万动态更新的后端地址中挑选一个合适的地址,又要避免多余的跳转及延迟。这就需要一种全新的架构来实现这个需求。

《基于边缘计算的负载均衡系统架构》

此为付费课程,需登录林老师微信小程序查看

无服务器计算: AWS的Lambda新增WebSocket的支持

websockets-chat-app

Lambda 增加 WebSocket 有些什么好处?

AWS官方说明

  1. 服务器端MQTT协议是可以选择在WebSocket上运行的,这样的话可以使用传统的应用开发流程来开发IoT服务器
  2. 可以开发支持海量客户端,并且需要控制客户端的应用程序
  3. WebSocket比HTTP要快,并且支持双向通信

AWS IoT 也是相同的架构,但是 AWS IoT明显比起Lambda来说要更难开发一些

祝大家编程愉快~

巧用ES系列5: 你并不需要moment.js

前言

曾几何时,我任何新建的Web前端项目,首先添加的库便是moment.js,如今随着Chrome 71的横空出世,TC39的新标准 RelativeTimeFormat 被实现了,于是乎便开始了我的代码清理之路,为了避免故局重演,这一次我专门写了一个Vue Component来实现这个功能

Intl.RelativeTimeFormat 介绍

从Chrome 71 开始支持,之前的版本没有这个对象

这个类用来将相对时间格式化成容易阅读的格式,如:1天前,昨天,15分钟前。并且支持多语言,你只用在构造的时候传入语言代码即可,如:

const english = new Intl.RelativeTimeFormat('en');
const chinese = new Intl.RelativeTimeFormat('zh');
const simplified_chinese = new Intl.RelativeTimeFormat('zh-Hans');
const traditional_chinese = new Intl.RelativeTimeFormat('zh-Hant');
const japanese = new Intl.RelativeTimeFormat('ja');

顺便说一下中文简体zh-Hans,繁体中文zh-Hant,这2个是IANA标准zh-CN, zh-SG是微软标准。

拿到对象之后只用传入相对时间和单位即可输出人类阅读的格式

chinese.format(-15, 'minute')
// 15分钟前

chinese.format(15, 'minute')
// 15分钟后

chinese.format(-15, 'day')
// 15天前

chinese.format(15, 'day')
// 15天后

是不是很简单?下面给出一个Vue的组件源代码,已经将这个函数封装了,没有任何依赖,复制就可以用

Vue组件源代码:

MyTimeAgo.vue

<template>
  <span>{{ text }}</span>
</template>
<script>
const SCALES = [60, 60, 24, 7, 4.34, 12];
const MAX_SCALE = SCALES.length;
const UNITS = ['second', 'minute', 'hour', 'day', 'week', 'month', 'year'];
const intl = new Intl.RelativeTimeFormat('en');

export default {
  name: 'MyTimeAgo',
  props: ['value'],
  computed: {
    text() {
      if (!this.value || !(this.value instanceof Date)) {
        return '-';
      }
      let i = 0,
        diff = (this.value.getTime() - Date.now()) / 1000;
      for (; Math.abs(diff) >= SCALES[i] && i < MAX_SCALE; i++) {
        diff /= SCALES[i];
      }
      diff = parseFloat(diff).toFixed(1);
      return intl.format(diff, UNITS[i]);
    }
  }
};
</script>

使用

在组件的value属性传入Date对象即可

<body>
   <my-time-ago :value="new Date(2013,1,4)"></my-time-ago>
</body>

结果

<body>
  <span>5.9 years ago</span>
</body>

这里起个抛砖引玉的作用,你可以增加更多的参数来支持多语言和Intl各种参数,如果你不嫌折腾的话甚至可以做出? year ? month ? days ? hours ? minutes ? seconds这种格式来。你还有什么问题,来一起讨论吧~

祝大家编程愉快

未来主流的JavaScript运行时有哪些?

Node

不用说了,这个大家一直在用,我在这里说说另外2个

Deno

由于TypeScript逐步进入企业系统开发,注意不是个人网站,是大型的企业后台系统。因此支持TypeScript并且有安全边界的运行时就显得非常重要,比如对文件和网络使用情况进行审计,Deno是在这个方面有得天独厚的优势,我们不需要过于深入,只需静观其发展即可

Chromium

由于WebWorker以及Service Worker的引入,Chromium正式成为JavaScript的运行时平台,而且增加了WebSocket使得我们可以将部分后端代码移到前端浏览器来执行,所以一个符合ES标准的程序将大大获益,并且由于浏览器是最后一个环节,所以Edge Computing的相关技术也会在这里大放异彩,最经典的实现就是在Service Worker中加入一个P2P网络,网站的请求全部通过P2P网络传输,Web服务器这里就真的仅仅是一个文件服务器而已了

预备工作

为了将来做准备,我们现在可以做的是:

  1. 使用ES标准的加密方法,比如WebCrypto,放弃使用require('crypto')
  2. 尽量不要使用Buffer,改用 UInt8Array
  3. 避免使用Node中的Stream
  4. 程序尽量不要访问本地文件系统,日志等信息通过WebHook等方式保存
  5. 能使用EventSource,就不要使用WebSocket

祝大家编程愉快~

tsmon - TypeScript 多场景开发必备利器

如果你是一个TypeScript的开发者,通常情况下会使用 ts-node 之类的工具来直接运行 .ts 文件。当然,我也是这样做的,直到有一天,ts项目已经庞大到每次编译都要10多秒的时候,我觉得,应该有所改变了。我尝试了世界上所有能尝试的东西,发现总有不如意的地方,于是 tsmon 就诞生了。

主要功能:

  1. 直接执行 ts 文件。
  2. 监测ts文件修改,后会自动重新编译并执行
  3. 无需额外配置,你只需要有基本的 tsconfig.json 文件即可。
  4. 支持增量编译,所以非常快!
  5. 内置类型检查,有问题一目了然,解决错误之后才会继续运行。
  6. 支持只包含interface的.ts文件
  7. 可以输入 rs 手动重载

安装使用方法如下

npm i -g tsmon
tsmon src/app.ts

巧用TypeScript系列:为 Reflect.construct 增加类型检查

起因

由于原生的Reflect.construct并没有类型检查,所以在日常使用中,一不小心,参数写错一个,都不会给出错误提示,项目后期如果因此引发问题,那么会浪费不少时间来定位和修复。

如何增加类型检查?

既然系统没有类型检查,那只能动手自己做一个了。把以下代码粘贴到你的TypeScript项目中就可以了:

// 定义一个基类
interface AbstractConstructor<T> extends Function {
  readonly prototype: T;
}

// 定义参数
type AgentParameters<T> = T extends new (...args: infer P) => any ? P : Arguments;

// 定义返回值
type Agent<T> = T extends AbstractConstructor<infer R> ? R : never;

// 将 Reflect.construct 包装一下,大功告成
class Domain {
  static construct<T extends Function>(target: T, params: AgentParameters<T>): Agent<T> {
    return Reflect.construct(target, params);
  }
}

例子

// 带有构造参数的强类型
class MyClass {
   constructor(public name: string) {
   }
}

// 将
Reflect.construct(Class, ["e2tox"])

// 替换为
Domain.construct(MyClass, ["e2tox"]);

// 这样的话使用 number 作为参数,就会被提示出错
Domain.construct(MyClass, [123]);

写更好的程序,做更好的自己。祝大家编程愉快!

无服务器计算: 谈谈影响企业落地无服务器计算障碍的应对方案

1_fq-njv3nwhqiorxn9pmmvg

非无服务器计算的最大痛点

传统应用程序一般的流程是:1.采购服务器。2.部署系统。3.用户增加。4.达到上限后扩容。但是从采购服务器到达到硬件处理能力上限是有时间的,而且一旦达到上限,系统必须扩容。所以从上面的图可以看出,当系统不在满负荷状态下运行,其多余的硬件资源都是被浪费掉了。也就是说,系统只有0个用户和100个用户,都必须支付同样的服务器费用。

无服务器计算解决了什么问题?

无服务器计算因为是按照请求数计费,因此是少用少花钱,不用不花钱。相对于服务器计算,可以就更低的起步价格,并且在遇到爆款的时候,系统会自动扩容来满足需要。

企业在无服务器转型中遇到的困难

  1. 从服务环境来说,在一些不能使用云服务器的应用来说需要购买本地FaaS服务器,因此违背了不用不花钱的原则,并没有发挥出无服务器计算的优势。
  2. 从系统架构来说,很多传统应用程序是基于内存状态的,而在无服务器环境下,内存状态是不可靠的,必须使用外部存储来存放数据,因此对应用程序的开发提出了更高的要求。
  3. 从编程框架来说,目前各大云服务商提供的函数式计算接口均不统一,后期要更换成本极高,因此企业无从下手,不知道选用那一个云服务商的无服务器开发接口。
  4. 由于无服务器函数的特殊性,在本地调试时有巨大障碍,因此开发无服务器应用的过程对开发人员来说非常不友好

应对方案

  1. 选用轻量的FaaS平台,最大限度减小对硬件的需求
  2. 开发不基于内存状态的应用
  3. 使用统一标准化的的无服务器开发框架
  4. 使用可以本地调试的无服务器开发框架

对以上问题都进行考虑之后就可以针对无服务器系统设计和开发了,祝大家编程愉快

利益相关声明:我是无服务器开发框架 AgentFramework 的作者

架构圣殿的倒塌

危机

出乎意料的是架构圣殿的崩塌并不是因为架构腐烂造成的,而是从朝圣者的中年失业开始。

这些朝圣者几乎穷尽一生的心血为架构的圣殿舔砖加瓦却逃不掉被驱逐出圣殿的命运。

朝圣者一旦离开圣殿,一身技艺便再无用武之地,无论是微服务治理,还是领域驱动开发,一瞬间变得毫无意义。

对朝圣者来说,能够看到第二天太阳的升起,便是一种恩赐。

在被驱逐出圣殿的朝圣者在荒野无助盲目的向圣殿相反的方向走去,谁也不知道迎接他们的是什么,但是所有人都知道,过去的圣殿已经不再存在了。

未完,待续

如何构建一个不会腐烂的架构?

前言

最近一位朋友向我推荐了多年前某技术专家讲述架构及代码腐烂的必然性,一篇好文,道出了无数程序员的心声。那如何避免架构腐烂呢?对于这个比肩如何让世界和平的终极问题,该文章作者给出的方案是微服务,看似最优解,可是多年后仍然会陷入服务发现、服务治理,以及如何搭建服务发现,如何管理服务治理的怪圈,虽然避免了代码上的腐烂,可是创造了新的基础设施的腐烂,基础设施的腐烂又慢慢侵蚀代码,最终又造成代码的腐烂,简直防不甚防。我在表达不一致的观点之后便立即遭到该专家的铁粉的围攻,因为这种言论挑战了他们心目中的偶像,无视了他们建造中的圣殿。正因为如此,我觉得更应该将我的观点表达出来,并且借助这个机会帮助更多人意识到:

防止架构腐烂的唯一办法就是没有架构。

圣殿

架构设计的初衷就是在软件的策划阶段考虑到未来尽可能多的应用场景,从而提前做好铺垫和应对。因此初期考虑的尽可能周全,依赖及框架尽可能的充分,培训尽可能的到位便是一个好架构。反之便是一个坏架构。于是乎各个技术大会和论坛便成为了人们讨论和分享各种架构演化的聚集地,并且乐在其中。在这个软件架构的圣殿里,教徒们在教主的带领下寻找着一个理想的、一个不存在的架构。

困境

架构的圣殿也无法经受BUG的侵蚀、依赖的更新和数据的膨胀,当再次面对新增需求这只巨兽的时候,就有可能变得不堪一击,曾经不可一世的圣殿在巨兽面前轰然倒塌。但是教徒们并不气馁,把失败的原因归结为环境的变化或者教主的错误判断,若是前者,便自我批评,若是后者便重新选举新的教主。完事之后,总结各种经验教训,又开始构筑更高,更坚固的圣殿。在不停的重复构建圣殿的过程中,圣殿越来越宏大壮观,教徒们纷纷沉浸在这种自我陶醉的状态中无法自拔。向外人展示自己的圣殿便成了一种炫耀和吸引新教徒手段,甚至成为一种和资本对话的外交工具。

新生

教徒中,有那么一群人,在那么一瞬间感觉到了圣殿的异样,但其中大部分认为只是**的不坚定,清除杂念之后,又继续投入到圣殿的建设中去。只有很少一部分人,坚定了自己的信念,试图打破圣殿的魔咒,毅然离开圣殿,并不顾一切投身到寻找属于自己的那一座圣殿的旅程……

随着金色夕阳的余晖逐渐斜照到在圣殿外墙下,看似某种激光灼刻的一行小字逐渐清晰起来

by Java SE Runtime Environment 7u80

未完,待续

我们需要标准化的云服务

目前AWS,Google,Azure,阿里云,腾讯云,华为云各自为阵,互相不兼容。对于软件开发商来说是一种灾难。

比如:一旦基于了AWS S3开发,那就意味着不支持Azure Storage和 Google Storage,重新适配花费大量时间精力,导致软件开发商开发的软件服务被锁死在一个云。

因此我发起倡议,制定公有云标准,基于此标准的云应用,可以在各个云之间互相切换,避免被云服务商锁死。

后注:
真是天真,提这种倡议

巧用ES系列4: TypeScript中的问号 ? 与感叹号 ! 是什么意思?

什么是 ?(问号)操作符?

在TypeScript里面,有3 4个地方会出现问号操作符,他们分别是

三元运算符

// 当 isNumber(input) 为 True 是返回 ? : 之间的部分; isNumber(input) 为 False 时
// 返回 : ; 之间的部分
const a = isNumber(input) ? input : String(input);

参数

// 这里的 ?表示这个参数 field 是一个可选参数
function getUser(user: string, field?: string) {
}

成员

// 这里的?表示这个name属性有可能不存在
class A {
  name?: string
}

interface B {
  name?: string
}

安全链式调用

// 这里 Error对象定义的stack是可选参数,如果这样写的话编译器会提示
// 出错 TS2532: Object is possibly 'undefined'.
return new Error().stack.split('\n');

// 我们可以添加?操作符,当stack属性存在时,调用 stack.split。若stack不存在,则返回空
return new Error().stack?.split('\n');

// 以上代码等同以下代码, 感谢 @dingyanhe 的监督
const err = new Error();
return err.stack && err.stack.split('\n');

什么是!(感叹号)操作符?

在TypeScript里面有3个地方会出现感叹号操作符,他们分别是

一元运算符

// ! 就是将之后的结果取反,比如:
// 当 isNumber(input) 为 True 时返回 False; isNumber(input) 为 False 时返回True
const a = !isNumber(input);

成员

// 因为接口B里面name被定义为可空的值,但是实际情况是不为空的,那么我们就可以
// 通过在class里面使用!,重新强调了name这个不为空值
class A implemented B {
  name!: string
}

interface B {
  name?: string
}

强制链式调用

// 这里 Error对象定义的stack是可选参数,如果这样写的话编译器会提示
// 出错 TS2532: Object is possibly 'undefined'.
new Error().stack.split('\n');

// 我们确信这个字段100%出现,那么就可以添加!,强调这个字段一定存在
new Error().stack!.split('\n');

祝大家编程愉快

巧用ES系列2: Symbol 和 WeakMap 在框架开发中的妙用

在我们开发框架的过程中,有一些属于框架内部的变量或者函数,我们不希望用户能够接触到这些变量或者函数,在Java或者C#中有Private变量作用域,但是在JavaScript中是没有的,我们可以用 Symbol 和 WeakMap来达到同样的效果。

Symbol

Symbol是一种新的数据类型。typeof返回'symbol'。通过Symbol()Symbol.for(key)创建,前者全局生成全局唯一值,后者则不是。如果你对Symbol不太了解,可以把Symbol理解成一个GUID类型。

比如我们想创建私有函数和私有变量

const ask = Symbol();
const name = Symbol(); 

export class Helper {
  constructor() {
    this[name] = 'Helper'
  }

  [ask]() {
    //因为ask和name没有被导出,所以这个ask函数和name属性不会被用户访问到,除非用到反射
    console.log('called ask', this[name])
  }

  help() {
    return this[ask]
  }
}

WeakMap

WeakMap和Map很像,都是储存key-value的映射关系,唯一区别就是WeakMap的key不是强引用,必须使用Object类型,所以在WeakMap里面没有 WeakMap.keys()或者类似的方法来遍历所有值,好处就是key的对象不会增加对象的引用,一旦key对象被回收,那么value对象也可以从内存中释放。

前面的方法提到的私有变量仍然有办法访问,如果使用WeakMap就彻底不能被外部用户访问到了

const names = new WeakMap();

export class Pet {
  constructor() {
    names.set(this, 'Kitty');
  }

  name() {
    // names没有被导出,所以访问字符串'Kitty'的唯一方式就是调用`.name()`函数
    return names[this];
  }
}

以上就是通过Symbol和WeakMap给框架增加内容方法和变量,如果你有更好的办法,欢迎在下面留言

祝大家编程愉快~

物联网: Serverless, MQTT, Protobuf 物联网应用开发的基石

5b0e0fdd79b10cc02e0d6945

什么是物联网?

简单来说,物联网就是把一切与人生活有关的物体或设备通过网络进行通讯和控制。比如蔬菜大棚的温度计全部联网后就不需要人一个一个的去查看温度,而是统一的在一个软件系统内进行控制。因此物联网的提出,将巨幅增加网络中设备的数量,对现有体系的控制系统来说是巨大的挑战,并且对网络宽带和容量提出了更高的要求。最典型的列子是大部分家庭的无线路由器在连接了10几个设备后会经常断网或无响应。在物联网情况下,这个设备的数字会增加到几百个,如果要支持这样规模的设备,家庭路由器将必须做出改变。

除了硬件部分需要改进之外,软件部分又会有什么变化呢?

物联网对通讯协议的要求

由于物联网设备往往计算能力和电力有限,必须使用最轻量级别的协议,并且需要能够使用服务端来控制客户端的协议。这个情况下使用 http协议就显得比较臃肿,并且由于http是同步的,在不可靠网络下会遇到很多挑战。于是IBM提出了使用 MQTT 来作为物联网的通讯协议。

物联网对数据传输的要求

目前网站API常用的数据结构是JSON,但是JSON相对Protobuf来说,描述同样内容的数据,JSON比Protobuf要占用更多的字节和使用更多的CPU时间来进行序列化和反序列化。因此在物联网设备上更多使用的是Protobuf来传输数据。

物联网对服务器的要求

由于物联网设备众多,并且数据往往是实时变化的,比如当前温度,湿度,位置。所以中心化的服务器将无法承载海量的设备链接和数据传输,必须使用边缘计算来筛选数据,只将关键数据发送到中心服务器,因此无服务器计算将承载物联网设备大部分的流量,比如 Lambda@Edge

结合Serverless,MQTT,Protobuf可以开发出目前来说最理想的物联网系统

祝大家编程愉快~

2019 必学的三大关键技术

2019是5G年,所以在2019年必须掌握的技术是下面这3个

Serverless

专注写代码,不要再花时间维护服务器

Edge Computing

让代码尽可能的在靠近用户的地方运行,数据中心仅仅是数据,不再是计算中心

TypeScript

真正将JavaScript引入企业开发,也就是由2个人或更多人维护的企业项目,并且项目持续很多年

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.