前情提要 2023 年 6 月 6 日凌晨,苹果在 WWDC23 上发布了旗下首款 MR 产品 Apple Vision Pro,售价为 3499 美元。仅三个月后的 2023 年 9 月 28 日,Meta 在其召开的 Meta Connect 大会上发布了 Meta Quest 3 头显,售价 499 美元。二者都不约而同的强调 了自己在 MR(混合现实)方面的能力和表现,都希望自己可以将整个世界带入“空间计算”的时代。但和 Quest3 不同的是,Apple Vision Pro 直到 2024 年 2 月 2 日才正式在北美开售,如今各路评测视频都已经放出,笔者也购入了被大多数人誉为“Vision Pro 最佳平替”的 Meta Quest3,想借着自己实际的使用体验聊一聊“空间计算”这个全新的概念。喜欢的朋友不妨点个赞关注一下哦 😯
我为什么购买 Quest3 我为什么会购买 Quest3,说不是心血来潮肯定是有假,但是说一时兴起也不完全对。之前看过很多 Quest3 的测评,都说相较之前代有很大提升,直到这次 Vision Pro 正式开售,我又才重新关注起来。笔者本身就是一个数码爱好者,生活中也经常会和朋友们聊些这个,这也算是我第一次尝试写个简单的测评文章。
Quest3 实际使用简评 首先结论先行,Quest3 是一个很好的头显,画质很棒,影音效果也很棒,游戏体验不错,有一定的沉浸感,舒适度一般,带久了脖子难受,我最期待的 MR 能力形同虚设(这还是发布会上 Meta 重点宣传的内容)。说实话如果不是因为代购的,不能退货,以及价格确实还是可以接受的,不然肯定是会退货的。
首先硬件参数方面,已经发布大半年了,网上到处都能找到,我就不复述了。鉴于我之前没有体验过其他头显设备,和前代/其他厂商的对比这里也没办法给出,因此直接进入简评环节。...
想追女神?先学 Synchronized 吧
在之前的《从找对象到多线程》一文中我曾介绍了一些和多线程有关的知识,而谈到多线程,就一定离不开「锁」这个名词。在 Java 中,锁的使用主要有两种:Synchronized 关键字和 Lock 接口,本文将会换个角度来聊一聊 synchronized 中的锁。
Synchronized 用的锁是存在对象头里的,用来表明当前对象所持有的锁。在 Java SE1.6 之前,Synchronized 是作为重量锁出现的,一旦使用了 synchronized,就一定会阻塞到其他线程。而在 Java SE1.6 后,为了减少获得锁和释放锁带来的性能问题,引入了"偏向锁"和"轻量锁"的概念。由此可以得知,在新的 Java 中,锁一共有 4 种状态:无锁状态、偏向锁状态、轻量锁状态和重量锁状态。这几个状态会随着竞争不断升级且只能升级不能降级,即轻量锁只会升级到重量锁而不会降级到偏向锁。
以上的解释未免太过官方了,我们从一个小例子入手。
我们用女神来表示同步代码块,就好比女神有很多追求者,同步代码块也会被很多线程执行。有一天女神的微博状态变成了「单身」,此时她就处于无锁状态,于是这些追求者纷纷创建了一个名为**「找对象」的线程**,此时对于女神(对象)来说,还没有任何线程来访问她,所以当第一个男生小 A 试图邀请她看电影的时候**(获取锁)**,她会偏向小 A 的邀请,此时她就是处于「偏向锁」状态的。有了这次经历之后,小 A 就知道该怎么邀请女神而不用反复试探了,这就是「可重入锁」,即同一个线程可以多次访问同一代码块。
再后来女神发了一条微博,说今天和这个男生看电影很开心。这条微博被其他男生看见了,大家也都知道了女神这个对象的偏向状态了。可还是有男生小 B 想追女神,此时这两个男生各自「找对象」的线程就在女神这个对象上产生了竞争。
小 B 一直关注女神的微博动态,他心想着,只要小 A 被女神拒绝了,女神就会变成「无锁」状态,自己也就有机会被女神偏向了。女神也知道小 B 在追自己,为了找到最合适的另一半,女神也在暗中观察小 B,有两个竞争者同时竞争,这时候她就处于**「轻量锁」的状态。虽然女神明显更喜欢小 A,但在小 B 心里觉得小 A 除了比自己早点出现外根本不具有和自己竞争的能力,于是不断给女神献殷勤,保持关系,这就叫自旋,**不断的将自己的时间花费在获取锁上,逐渐成为一条舔 🐶。
虽然一开始女神也会偶尔答应小 B 的邀请,但当竞争者越来越多后,小 B 变得疯狂起来,追求逐渐变成了骚扰,女神也逐渐不耐烦起来。最终在小 A 的努力下,女神和小 A 确定了关系,并发了微博告知众人,此时她的状态就升级成为**「重量锁」状态**。这时,除了小 A,其他所有竞争者的「找对象」线程都没有办法再追求女神了。这样做的好处就是赶紧断了那些追求者的念头,让他们可以早日觅得其他良人,不要在一棵树上吊死。
从线程的角度来看,重量锁使除了拥有锁的线程外的其他所有线程都阻塞,这样可以有效防止 CPU 空转,避免造成资源的浪费。
在偏向锁和轻量锁阶段,女神还没有和任何人确定关系,只要给点甜头小 B 等其他追求者都会很开心,这是一种「乐观锁」。而一旦女神和小 A 确定了关系,自身状态升级为重量锁后,小 B 就很不开心了,对他来说这就是一种「悲观锁」。...
接口调度者—— API 网关
背景 我们知道在微服务架构风格中,一个大应用被拆分成为了多个小的服务系统提供出来,这些小的服务他们自成体系,也就是说这些小系统可以拥有自己的数据库,框架甚至语言等,这些小系统通常以提供 Rest Api 风格的接口来被 H5, Android, IOS 以及第三方应用程序调用。
在《浅入浅出消息队列》这一篇文章中,我提到了消息队列是方便服务与服务之间的通信解耦,如下图所示:
那么这时候问题来了,如果一个外部的应用(浏览器、App)要去访问这个大应用怎么办?
很简单啊,直接通过 HTTP 请求不就完了?
问题 真的这么简单吗?我们以淘宝的商品详情页为例:
如上图所示,这个页面包含了视频、库存、商品价格、商品评价等内容,这些数据都来自不同的微服务中,所以没办法像传统单体应用一样依靠数据库的 join 查询来得到最终结果,因此就需要多次调用以检索数据,如下图所示: 这就会引发几个严重的问题:
不同的客户端设备可能需要不同的数据。Web,H5,APP,需要单独写一套 API 多次客户端请求导致用户体验不佳。移动网络相较于服务于服务间的局域网,有更低的带宽和更高的延时,如果可以同时执行请求倒也还好,但如果客户端要按照顺序执行请求,就会让用户体验变得异常糟糕。 缺乏封装导致前后端不协调。过分的拆分 API,会导致客户端和服务端过度耦合,再加上移动端 APP 的新版本迭代到每个手机用户时需要很久,这样会使后端很难更改服务的 API。 这样显然是不好的设计,因此,本期的“天降猛男”就出现了——API 网关。
API 网关 在介绍 API 网关前,我们先来介绍一个设计模式——外观模式。
外观模式(Facade Pattern)它向现有的系统添加一个接口,来隐藏系统的复杂性。类图如下所示:
之所以要在说 API 网关前说一下外观模式,是因为二者的设计理念是类似的。
和外观模式类似,API 网关封装了应用程序的内部架构,并为其客户端提供 API,他还可能具有其他职责,如身份验证、监控、负载均衡、缓存、请求分片与管理、静态响应处理。下图展示了客户端、API 网关和服务之间的关系。
所有的客户端和消费端都通过统一的网关接入微服务,在网关层处理所有的非业务功能。其出现也是侧面贯彻了软件工程中**“高内聚,低耦合”**的思想。
核心作用 API 网关负责请求路由、API 组合和协议转换。来自外部客户端的所有 API 请求首先会先转到 API 网关,后者再将请求路由到相应的服务。API 网关使用 API 组合模式处理其他请求,调用多个服务并聚合结果。同时他还可以在客户端友好的协议(例如 HTTP)与客户端不友好的协议之间进行转换。
请求路由 当 API 网关收到请求时,随机会查询路由映射,该映射将指定请求路由到哪个服务。例如,路由映射可以将 HTTP 方法和路径映射到服务的 HTTP URL,这一点和 Nginx 提供的反向代理的功能是一样的,后面我们也会对其进行一个比较。...
你的系统可用性 5 个 9 了吗?
又是一年放榜日,众多考生满怀期待的点开招生网,结果输了信息才发现根本没办法查询——查询人数太多了,直接把系统打挂了!
这个时候,还没翻身的码农闰土被问到一个直击心灵的问题:这个系统可用性达到了多少个 9?
想要回答这个问题,我们得先有些前置知识。
可用性&可靠性 这两个词很相似,我也一直找不到一个很好的定义区分这两个词,直到后来在看分布式系统的时候,看到了一个解释:
可用性被定义为系统的一个属性,它说明系统已准备好,马上就可以使用。换句话说,高度可用的系统在任何给定的时刻都能及时地工作。 可靠性是指系统可以无故障地持续运行,是一个持续的状态。与可用性相反,可靠性是根据时间段而不是任何时刻来进行定义的。
举个例子,想要评估一个舔 🐶,可用性就是你找他的时候能不能找到,而可靠性就是你需要花钱的时候他出手大不大方。一个舔 🐶 如果随叫随到,但是花钱太抠,就是高可用、低可靠;而如果他经常找不到人,但出手很大方,就是低可用、高可靠。
类比到系统时,如果系统在每小时崩溃 1ms,那么它的可用性就超过 99.9999%,但是它还是高度不可靠。与之类似,如果一个系统从来不崩溃,但是每年要停机两星期,那么它是高度可靠的,但是可用性只有 96%。
百度百科对于系统可靠性的解释是:系统可靠性一般是指在规定的时间内和规定的工况下,系统完成规定功能的能力/概率。也就是系统的无故障运行概率。而在我们在评估一个系统的可用性和可靠性时,一般都会说三个 9,四个 9 之类的。这些一般都是说系统的**SLA(Service Level Agreement)**具体是几个「9」,以此,来表示该系统一年中具体宕机的时间。对于这几个 9 的解释,我会放到第三节来详细解释。
不过,在实际交流过程中,大多数人对这两个词的理解还是差不多的。况且咬文嚼字也并非本文的主题,接下来我们来看看可用性的计算方式。
可用性计算 通常我们用 A 表示一个系统的可用性,用以下几个指标来辅助计算:
相关指标 MTBF MTBF,即平均故障间隔时间,英文全称是“Mean Time Between Failure”。是衡量一个产品(尤其是电器产品)的可靠性指标。单位为“小时”。具体来说,是指相邻两次故障之间的平均工作时间,也称为平均故障间隔。
MTTR MTTR,全称是 Mean Time To Repair,即平均修复时间。是指可修复产品的平均修复时间,就是从出现故障到修复中间的这段时间。MTTR 越短表示易恢复性越好。
通过上述公式计算出单个组件的可用性后,我们便可以以此计算出整个系统的可用性,而系统可用性是通过将系统建模为串联和并联的组件来计算的。以下规则用于确定系统是串联的还是并联的:
如果组件的失效导致组合变得不可操作,则认为这两个部件是串联操作的 如果组件的故障导致另一部件接管故障部件的操作,则认为这两部件并行操作 串行可用性 如上图所示,两个组件 X 和 Y,如果有一个出问题导致整个组合都不可用,就认为 X 和 Y 这两个组件是串联的。只有组件 X 和组件 Y 同时可用时,整个组合才可用。由此可见,组合的可用性是这两部分的乘积,公式如下:
A = Ax Ay...
DO,VO,DTO 你知道吗?
作为后端最常用的编程语言之一,Java 已经有很多年的历史了,在阿里内部,Java 也是使用最广泛的一门语言。在阿里实习的这段时间,规范一词是我感受最深的。没有规矩不成方圆,今天来说一下 Java 中的各种 O(bject)。
为什么会出现这些 O? 我们知道,这些 O 不管叫什么名字,其本质都还是对象(Object),既然本质都一样,为什么非要给他们套上各种马甲? 个人认为原因有三: 第一,随着编程工业化的发展,需要有一套合理的体系出现。中国人喜欢造神,外国人喜欢造概念,于是 MVC、MVP、MVVM 等编程模型就出现了,为了搭配这些编程模型的使用,需要对 Object 的功能进行划分,于是我们便看到了这些层出不穷的 Object。当然这里并没有批评这些概念的意思。 其二,我认为在团队协作编码中,一个好的命名方式是可以节约很多时间成本的。就比如getItemById一眼看去就知道是通过 id 获取一个 item 对象,ItemVO一眼看去就知道是前端透出的 json 对应的对象。 其三,如此划分,可以让项目结构更加清楚,不至于出现东一块西一块,对象乱扔的局面。尽可能避免了在多人协作时对象混乱的情况。 总的来说,这一切都是为了让软件编程更加合理、更加规范、更加高效。
有哪些 O? 这些 O 有很多衍生出的命名,比如 VO、DO、BO,这里我们把常见的 O 列举出来,然后一一解释。
以下内容参考阿里巴巴 Java 开发手册,如果有需要可以在微信公众号「01 二进制」后台回复「Java 开发手册」获得。
DO( Data Object):与数据库表结构一一对应,通过 DAO 层向上传输数据源对象。 PO(Persistant Object):持久对象,一个 PO 的数据结构对应着库中表的结构,表中的一条记录就是一个 PO 对象 DTO( Data Transfer Object):数据传输对象,Service 或 Manager 向外传输的对象。 BO( Business Object):业务对象。 由 Service 层输出的封装业务逻辑的对象。 AO( Application Object):应用对象。 在 Web 层与 Service 层之间抽象的复用对象模型,极为贴近展示层,复用度不高。 VO( View Object):显示层对象,通常是 Web 向模板渲染引擎层传输的对象。 POJO( Plain Ordinary Java Object):POJO 专指只有 setter/getter/toString 的简单类,包括 DO/DTO/BO/VO 等。 DAO(Data Access Objects):数据访问对象,和上面那些 O 不同的是,其功能是用于进行数据操作的。通常不会用于描述数据实体。 一下子给出 8 个常见的 O,光看解释大家可能会有些迷糊,接下来我们从下面这张图入手,带大家直观的感受下,这些 O 的用处。...