前言 本文是笔者在团队内部做分享整理的资料的一部分,本次分享主要是站在一个服务端开发的视角对(前端)低代码平台的一些调研,已经剔除了一些敏感数据和信息,可放心食用。
太阳底下无新事 Dreamweaver -> Low-Code 将时钟拨回到 20 年前,那个时候的开发者对于 html/css/js 还处在望而生畏的阶段,Dreamweaver 的出现仿佛让他们看见了曙光。通过简单的拖拽就可以实时预览编排的页面,点击按钮就可以自动生成对应的前端代码,配置好机器信息就可以一键部署访问…… 这些特性让无数开发者趋之若鹜,然后现在他的境况
现如今,Dreamweaver 几乎已经退出了历史舞台,但 Low-Code 似乎又有卷土重来的迹象……
Low-Code 是什么? A low-code development platform (LCDP) is software that provides a development environment used to create application software through graphical user interfaces and configuration instead of traditional hand-coded computer programming.
一句话概括就是 👉 用 GUI+配置取代传统手工编码 技术上,实现低代码平台的关键要素是模型驱动设计、代码自动生成和可视化编程,通过这些手段来隐藏下层的代码细节。
更激进的—— No-Code(零代码) Low-Code 更激进的演进方向是 No-Code,主要的差异点如下:
平台用户:任何业务人员都能使用无代码平台,而低代码平台面向开发者(尽管专业要求不那么高)
核心设计:无代码平台倾向于让用户通过拖拽或简单的表达式来操纵完成应用设计,而低代码平台更倾向于通过人工编码来指定应用程序的核心结构
用户界面:无代码平台为了简化应用设计,一般只支持内置的 UI 库,而低代码平台可能会提供更灵活的 UI 选项,但代价是需要额外编码,使用上的复杂性有所增加...
前言 对于一个 Java 开发者来说,Lombok 应该是使用最多的插件之一了,他提供了一系列注解来帮助我们减轻对重复代码的编写,例如实体类中大量的 setter,getter 方法,各种 IO 流等资源的关闭、try…catch…finally 模版等,虽然可以通过 IDE 的快捷帮我们生成这些方法,但这些冗长的代码仍会影响代码的简洁性与可阅读性。 如今,随着使用者数量越来越多,Lombok 甚至成为 IDEA 的内置插件了(2020.3 版本+),可见其影响力。
但不知道使用 Lombok 的你,是否思考过这种自动生成代码究竟是什么原理呢?🤔 这些代码又是怎么产生的呢?而这就是本文要展开介绍的内容了。
Lombok 的安装与使用网络上相关的介绍已经很多了,这里就不多说了,自行查阅相关资料即可。
注解解析的两种方式 关于注解,我在之前的文章里有过详细的介绍,在解释 Lombok 的原理之前,推荐你先阅读 👉《给编译器看的注释——「注解」》 这里主要回顾一下 Lombok 注解的解析方式。
运行时解析 这是最常见的注解解析的方式,运行时能够解析的注解,必须将@Retention设置为RUNTIME,这样就可以通过反射拿到该注解。 例如使用最多的@RequestMapping注解就是一个运行时注解。
@Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented @Mapping public @interface RequestMapping { String name() default ""; @AliasFor("path") String[] value() default {}; @AliasFor("value") String[] path() default {}; RequestMethod[] method() default {}; String[] params() default {}; String[] headers() default {}; String[] consumes() default {}; String[] produces() default {}; } 运行时注解的解析原理也很简单,在 java....
抛砖引玉 在文章开始前,先看看一个常见的情况 👇
在集团内进行开发时,通常会遇到不同组之间的合作,如果是同一个组的前后端,因为交互请求都是在同一个 「域」 内发生的,所以一般不会存在跨域问题。但如果未做处理,直接从 a.alibaba.com 请求 b.alibaba.com 的接口,就会出现跨域的问题,这是因为浏览器对于不同域请求的限制问题,其实跨域的问题很好解,只要设置了正确的请求头即可,具体的可以参考我的这篇文章 👉《一次跨域问题的分析》
但这是访问不需要登录的接口,那如果是从 a.alibaba.com 访问 b.alibaba.com 下的一个需要登录的接口呢?又该如何解决呢?
下文以 A 站点指代 a.alibaba.com,B 站点指代 b.alibaba.com
单系统登录 对于一个 web 应用来说,通信协议通常是 HTTP 协议,该协议是无状态的,也就是说,在请求与请求之间是不会产生关联的。这也就意味着,任何用户都能通过浏览器访问服务器资源,且不会打扰到其他用户。如下图所示 👇
如果想要保护某些资源,比如一些珍贵的学习资料,那就必须限制浏览器的请求,对于服务端来说就是要知道发出这个请求的人是谁,也即让请求变得有「状态」,只不过既然 HTTP 协议无状态,那就让浏览器和服务器之间共同维持一个状态吧,而这就是最常见的——会话机制。
Cookie 和 Session 在会话机制中,最重要的就是 Cookie 和 Session 了,Session 好理解,服务端保存的用来维护某一个用户的状态,浏览器只需用某种方式记录下这个会话的 ID 然后之后每次请求携带即可,想必有小伙伴会发出疑问了,既然是给浏览器携带参数,那么直接在请求参数里携带不是最简单的吗?
的确,将会话 id 作为每一个请求的参数,服务器接收请求自然能解析参数获得会话 id,并借此判断是否来自同一会话,这个思路当然是可以的,只是这种做法的缺点也十分明显,就是请求的 URL 会变得非常长,隐秘性也很差。
而 Cookie 是浏览器用来存储少量数据的一种机制,数据以”key/value“形式存储,并且浏览器发送 http 请求时自动附带 Cookie 信息。此时,有 Cookie 参与的登录请求的流程就变成了下面这样 👇
Cookie 和 Session 的使用原理基本如此,至于这么设置 Cookie,怎么通过 Cookie 校验 Session 就不是本文要说的内容了。有兴趣的可以查阅相资料。...
前一篇文章我们介绍了 Java 中的两个常见的序列化方式,JDK 序列化和 Hessian2 序列化,本文我们接着来讲述一个后起之秀——Kryo 序列化,它号称 Java 中最快的序列化框架。那么话不多说,就让我们来看看这个后起之秀到底有什么能耐吧。
Kryo 序列化 Kryo 是一个快速序列化/反序列化工具,依赖于字节码生成机制(底层使用了 ASM 库),因此在序列化速度上有一定的优势,但正因如此,其使用也只能限制在基于 JVM 的语言上。
网上有很多资料说 Kryo 只能在 Java 上使用,这点是不对的,事实上除 Java 外,Scala 和 Kotlin 这些基于 JVM 的语言同样可以使用 Kryo 实现序列化。
和 Hessian 类似,Kryo 序列化出的结果,是其自定义的、独有的一种格式。由于其序列化出的结果是二进制的,也即 byte[],因此像 Redis 这样可以存储二进制数据的存储引擎是可以直接将 Kryo 序列化出来的数据存进去。当然你也可以选择转换成 String 的形式存储在其他存储引擎中(性能有损耗)。
由于其优秀的性能,目前 Kryo 已经成为多个知名 Java 框架的底层序列化协议,包括但不限于 👇
Apache Fluo (Kryo is default serialization for Fluo Recipes) Apache Hive (query plan serialization) Apache Spark (shuffled/cached data serialization) Storm (distributed realtime computation system, in turn used by many others) Apache Dubbo (high performance, open source RPC framework) …… 官网地址在:https://github....
我之前在《聊一聊 RPC》中曾提过什么是序列化和反序列化,当时有说过之后要单独抽出一期来详细聊聊序列化,没想到这一拖竟然拖了一年多,现在来把这个坑补上。由于篇幅较长,本文先主要介绍两种常见的序列化方式——JDK 序列化和 Hessian 序列化。
序列化是什么(What) 百度百科对于 「序列化」 的解释是:
序列化 (Serialization)是将对象的状态信息转换为可以存储或传输的形式的过程。
这么说太抽象了,举一个例子:你如果想让一个女孩子知道你喜欢她,你可以给她写情书,这样 「喜欢」 这种状态信息就变成了 「文字」 这种可以存储或传输的信息。
至于怎么把“情书”送给女生就有很多种方式了,我在《聊一聊 RPC》中已经有写过了,感兴趣的读者们可以点击阅读。
所以,简单理解序列化就是将“对象”存储的信息保存到某个“文件”中,之后再通过某种方式读取“文件”转换成对象。在 Java 中,序列化其实就是把一个 Java 对象变成二进制内容,本质上就是一个 byte[]数组。
既然有序列化,那么就会有反序列化,在上文的例子中,如果女孩通过情书中的文字明白了男孩的喜欢,这就是一种反序列化。在 Java 中,将一个 byte[]数组重新变成 Java 对象就是一种反序列化。
为什么要序列化(Why) 这个时候肯定就有人会问了,直接把对象作为参数传递不就可以了吗?为什么还要多此一举把对象变成“文本”,然后再将“文本”变成对象?
我们知道,Java 创建的对象都是存在于 Java 虚拟机中,也即 JVM 中,那么 JVM 又在哪里呢?
JVM 是 Java 程序运行的环境,但是他同时是一个操作系统的一个应用程序,即一个进程。他的运行依赖于内存,因此 Java 中对象都是存储在内存中,准确地说是 JVM 的堆或栈内存中,可以各个线程之间进行对象传输,但是无法在进程之间进行传输。如果涉及到跨内存的数据传输(比如两台机器的传输),直接把对象作为参数传递就不可取了,这时就需要通过“网络”将数据传输。
举个例子,如果没办法自己亲自把情书送到对方手上,是不是得找一个人送过去?这就是 RPC 相关的知识了。
怎么序列化(How) 上述内容在之前那篇文章里都有涉及,接下来才是本文的重点,在实际使用时我们究竟该怎么序列化,有哪些方式可以序列化?为什么我们在代码中很少遇到手写序列化的情况。这些都是本文要解答的内容。
本文我们以 Java 为例。
JDK 序列化 作为一个成熟的编程语言,Java 本身就已经提供了序列化的方法了,因此我们也选择把他作为第一个介绍的序列化方式。
JDK 自带的序列化方式,使用起来非常方便,只需要序列化的类实现了Serializable接口即可,Serializable 接口没有定义任何方法和属性,所以只是起到了标识的作用,表示这个类是可以被序列化的。如果想把一个 Java 对象变为 byte[]数组,需要使用ObjectOutputStream。它负责把一个 Java 对象写入一个字节流:...
计算机的世界是由 0 和 1 构成的,为了方便人类与计算机沟通,先贤们发明了编程语言,通过编译器将这些语言翻译成机器可以看懂的机器语言。为了方便人类更好的阅读代码,避免不必要的 996,几乎所有的编程语言都提供「注释」的特性,在某种程度上,这些「注释」的存在就是“废话”,因为编译器在执行到这里的时候是直接忽略的,「注释」虽然是人类写的,却也只是为了给“愚蠢”的人类看的。然而,无论哪个时代都有前行者,他们所做的不过是让我们的代码看起来更简洁,更有时代的进步感,因此必须要让人类与机器的沟通更进一步了,而这就是写给编译器的注释——「注解」。
何为「注解」 所谓注解,英文名 Annotation,是在 Java SE 5.0 版本中开始引入的概念,同class和interface一样,也属于一种类型。很多开发人员认为注解的地位不高,但其实不是这样的。像@Transactional、@Service、@RestController、@RequestMapping、@CrossOrigin 等等这些注解的使用频率越来越高。
说了这么多,到底何为「注解」?
注解是放在 Java 源码的类、方法、字段、参数前的一种特殊“注释”。
话不多说,直接上代码:
// 用户请求接口 @RestController public class UserController { @GetMapping(value = "/user") public User getUser() { return new User("闰土",22,"男"); } } 上述是一个十分简单的 SpringBoot 的控制器代码,第 1 行是「注释」,是告诉阅读这行代码的人这是一个用户请求接口;第 2 行和第 4 行是「注解」,是用来编译器,这一个 Restful 接口,请求方法为 Get,匹配的是"/user"路径。
注释会被编译器直接忽略,注解则可以被编译器打包进入 class 文件,因此,注解是一种用作标注的“元数据”。从 JVM 的角度看,注解本身对代码逻辑没有任何影响,如何使用注解完全由工具决定。
「注解」的本质 在探究「注解」的本质之前,我们要先理解一个东西,Annotation 同class和interface一样,也属于一种类型,因此如果想要申明一个注解的话,我们同样需要写一个 java 文件来创建注解。注解的创建方法很简单,见下面的代码 👇
import java.lang.annotation.*; @Target(ElementType.METHOD) @Retention(RetentionPolicy.SOURCE) public @interface TestOverride { } 如上面代码所示,创建了一个名为「TestOverride」的注解,关键词是**「@interface」**,这时有小伙伴肯定就要说了,为什么我创建一个注解前还有注解?不急,这里我们暂且按下不表,之后来解释。...
前言 对于云端编程,我想大多数人的第一想法应该是微软推出的 VSCode Remote,这个功能基于开源的 VSCode,通过 SSH 远程连接到服务器,开发者可以通过端口转发、SCP 等一系列实用功能快速实现远程开发。我曾体验过这种编程方式,极大减轻了电脑性能的压力,但我认为这并不是云端编程的最终形态,因为我仍然需要在自己的电脑上安装 VSCode 才可以使用这个功能。
最近 2021 款的 iPad Pro 上市了,这次搭载的是和 Mac 同款的 M1 芯片,性能强大到甚至有让人利用 iPad 编程的想法,只是迫于各大厂商没有推出适配 iPad 的 IDE,便也只能沦为“买钱生产力,买后爱奇艺”的工具了。那么有没有什么办法可以在不安装 IDE 的情况下使用 iPad 编程吗?自然是有的,JetBrains 公司提出了一种新的解决方案:把 IDE 搬进浏览器里。这便是本文的主角——JetBrains Projector。
发展 提起 JetBrains,你会想到什么?各路强大的 IDE,比如 Android Studio、IDEA、WebStorm……这些对于开发者来说耳熟能详的产品都出自这家公司,这些 IDE 的功能强大,但同时也只能运行在用户自己的电脑上,其“内存黑洞”的称号更是让开发者们又爱又恨。
事实上,目前所有的 JetBrains IDE 都使用 Java Swing 绘制 UI,其他基于 IntelliJ 的 IDE 也是如此,比如 Android Studio。鉴于 Swing 是 Java GUI 的一个库,而 Java 本身就是一门很吃内存的编程语言,虽然可以充分利用 Java 跨平台的特性,这也是这些 IDE 在 macOS、Windows 和 Linux 上 UI 几乎一致的原因。但现在,Swing 跨桌面平台的特性却也成为阻碍其发展的一个原因了,在一些瘦客户端的情况下,“内存黑洞”屡屡被人诟病,Swing 也无法发挥其优势,于是 Projector 便应运而生了。...
3 月 30 日,小米在其新品发布会上公布了他们要造车的消息,那场发布会我看完了,其实这个消息在意料之中,如今的手机市场已经趋向饱和,手机厂商竞争加剧,疯狂内卷,手机业务再进行大的扩张也非易事。
就在这两天,极狐阿尔法 S 也面世了,这辆车上搭载的是华为最新的无人驾驶系统,由此可见,围绕着汽车形成的车联网在未来也会逐渐普及。而我也就是一个写代码的,对于企业的战略布局我不关心,这一篇文章也只是想来聊聊新领域背后的一项老技术——MQTT。
何为 MQTT MQTT 即 Message Queuing Telemetry Transport,中文名为消息队列遥测传输协议,是一种基于发布/订阅模式的"轻量级"通讯协议。其本质上也是构建于 TCP/IP 协议上的一种通信协议,其地位在 OSI 七层网络协议中和 HTTP 协议并列,同属应用层的网络通信协议。
HTTP 协议全称**「超文本传输协议」**,这里的超文本包括 HTML 文件、图片等。因此在设计之初,HTTP 就已经包含了复杂的报文,但我们知道并不是所有的环境都有较好的网络环境,MQTT 的出现正是为了解决这种问题。
MQTT 协议的最大优点在于,可以以极少的代码和有限的带宽,为连接远程设备提供实时可靠的消息服务。也正是因为 MQTT 协议是一种低开销、低带宽占用的即时通讯协议,使其在物联网、小型设备、移动应用等方面有较广泛的应用。
探究 MQTT 的原理 发布/订阅 MQTT 协议是基于客户端-服务器的消息发布/订阅传输协议,在整个通信过程中,有三个重要的角色,分别是发布者(Publish)、代理(Broker)(服务器)、订阅者(Subscribe)。其中,消息的发布者和订阅者都是客户端,消息代理是服务端,消息发布者可以同时是订阅者。
代理(Broker) MQTT 中的 Broker 类似于一个中转站,位于消息发布者和订阅者之间。在 Broker 中,可以接受客户发布的应用信息,处理来自客户端的订阅和退订请求以及向订阅的客户转发应用程序消息。Broker 通常由一个应用程序或一台设备充当。
消息组成 在 MQTT 中,传输的消息分为:主题(topic)和负载(payload)两部分:
Topic,可以理解为消息的类型,订阅者订阅(Subscribe)后,就会收到该主题的消息内容。 Payload,可以理解为消息的内容,是指订阅者具体要使用的内容。 最后 本篇文章篇幅较短,主要是为了向大家介绍一下 MQTT 这一协议的基本信息,下一节将会介绍如何搭建一个可用的 MQTT 环境并用实际代码演示如何使用 MQTT 协议。
身份认证 这里所说的身份认证,指的是狭义上的在计算机及其网络系统中确认操作者身份的过程,从而确定用户是否具有访问或操作某种资源的权限。
之所以要在互联网中进行身份认证,是为了防止攻击者假冒你的身份在系统中进行不利于你的操作。试想一下,万一哪天早晨起来你发现你的支付宝账号被盗了,你余额宝里的钱全没了,那岂不是亏大了。
只不过,和现实世界不同的是,网络世界中一切信息都是用一组特定的数据来表示的,计算机只能识别用户的数字身份,所以对用户的授权本质上就是针对用户数字身份的授权。
因此,如何保证操作者的物理身份和数字身份相对应,就成了一个至关重要的议题了,身份认证也因此在互联网世界中起着举足轻重的作用了。本文将会介绍目前很多网站常用的一种方式——双因素认证(也叫两步验证,英语:Two-factor authentication,缩写为 2FA)。
双因素认证 2FA 虽然网络世界和真实世界对于身份的表示不尽相同,但是对于身份认证的手段与经验是可以相互借鉴的。在真实世界,对用户的身份认证基本依据可以分为这三种:
上述三种认证依据被称为三种「因素」(factor)。因素越多,证明力就越强,身份就越可靠。
因此,在网络世界中,为了达到更高的身份认证安全性,某些场景会将上面 3 种挑选 2 种混合使用,即双因素认证。
在支付宝还没有在中华大地普及的时候,去银行通常需要准备一个叫「U 盾」的东西,在使用网上银行时,用户需要先插上 U 盾,然后再输入密码才能登录网上银行。在这一操作中,U 盾(you have)+密码(you know)这两种因素组合在一起就构成了一个双因素认证。
只是后来,随着移动互联网的普及,手机渐渐成为最离不开人身边的物品了,于是传统的「U 盾+密码」的组合方案就被「手机+密码」的组合替代了。
现如今,短信验证码在国内已经成为使用最广泛的两步验证方法之一了,虽然操作方便,不需要安装额外的 APP,但是验证码的下发依赖网络和运营商信号,有被窃听的风险。试想一下,如果这种验证码的获取不需要依赖运营商和网络,哪怕手机处于飞行模式也可以获取验证码,那么安全性是不是就得到提升了?
而这也就是下面将要说的 TOTP,即**“基于时间的一次性密码(Time-based One-time Password)”**。这是目前公认的可靠解决方案,已被纳入国际标准。
TOTP 流程 TOTP 的流程如下:
服务器随机生成一个的密钥,并且把这个密钥保存在数据库中。 服务端将该密钥下发,通常是在页面上显示一个二维码,内容中包含密钥。 客户端扫描二维码,把密钥保存在客户端。 客户端每 30 秒使用密钥和时间戳通过 TOTP 算法生成一个 6 位数字的一次性密码 其实利用 TOTP 验证的流程很简单,这里也只是介绍,如果想深入了解 TOTP 算法的具体实现过程,可以参考 👉TOTP: Time-Based One-Time Password Algorithm
通过这种方式生成一次性验证码,除去第一次获取服务器下发的密钥外,对网络并无其他要求了,这样即使是在离线情况下也可以使用,而且由于由于这种动态生成的密码通常只会存在 30s,安全性也得到了较大的提升。
只是在实际过程中,肯定要额外考虑一些情况,比如如果有人想要暴力破解验证码时,我们可以对验证的错误次数进行限制;抑或是手机端时间和服务器时间不同步,我们需要通过算法的方式兼容服务器时间的前后 30s,从而有效的避免细微时间上差异而导致的验证失败。
使用现状 目前 TOTP 验证 App 主要分为两类:“独占类”和“开放类”。所谓独占类指的是只支持自家账户登录的两步验证,比如 QQ 安全中心、Steam 验证令牌等。开放类则是一个纯粹的两步验证 App,通过一个 App 去作为多个网站的验证器,例如 Google authenticator 就是一个开源的基于 TOTP 原理实现的一个生成一次性密码的工具。...
我上大学时的第一台电脑是微星的一款游戏本,当时买它的原因很简单,性能足够强大,无论是编程等日常任务还是游戏它都可以胜任。现在回想起来,依稀记得它炫酷的灯光、强悍的性能以及用它驰骋虚拟世界的快感。后来年纪渐长,打游戏的热情也逐渐减少,虽然那台电脑仍在家中,但已经落后的性能让我鲜有机会“宠幸”它。再后来,读研之后换了 Mac 后更是没怎么碰过游戏了。
大家都说正经人谁用 Mac 打游戏,一开始我也是这么认为的,毕竟买来就是用来写代码的,可是最近发现的一个有趣玩意让我对这个问题有了新的想法,那就是——云游戏。
云计算?云? 以下内容摘自百度百科
云游戏是以云计算为基础的游戏方式,在云游戏的运行模式下,所有游戏都在服务器端运行,并将渲染完毕后的游戏画面压缩后通过网络传送给用户。在客户端,用户的游戏设备不需要任何高端处理器和显卡,只需要基本的视频解压能力就可以了。
我将上述内容中一些比较重要的点做了标注,百科在对于云游戏的描述时,第一句就直接阐明了云游戏的基础是云计算,那么「云计算」以及「云」指的是什么?
云计算(cloud computing),是一种基于互联网的计算方式,通过这种方式,共享的软硬件资源和信息可以按需提供给计算机和其他设备。提供资源的网络被称为“云”。
看完上面一句话有些小伙伴还会不太清楚,我们先来回顾下之前的知识。我在《互联网是如何工作的》这一篇文章中提到:一台又一台的服务器通过“网线”连接在了一起,形成了类似下面这样的结构 👇
众多服务器组成的这种结构被称为“互联网”,而其中每台服务器都被称作“节点”。
事实上这些节点都和你的本机无关但又何你的本机有关。
为什么这么说呢?
无关的原因是,这些节点所包含的计算能力(CPU、GPU)和存储文件都不是你的。有关的原因是,你可以通过某些方式运用这些能力和文件。
而上述所说的一个个节点便是云计算的核心,即「云」。
大量的水滴漂浮在空中,聚合成云。和我们所说的云很相似,只是这里的云是由大量的数据存储、计算资源和应用程序组成,这便是云计算服务。
「云」其实是一个抽象的概念,并不像服务器有一个具体的实物可以展示,我们可以把「云」理解为一个资源共享池。举个例子就是,我有很多东西,家里放不下了,放到一个特定的地方存着,随时提取。大家都可以访问的就是「公有云」,只有特定的人可以访问的就是「私有云」。
这个“东西”一般是指数据、软件、服务等,而“特定的地方”就是云。所以对于云计算我们也可以简单的理解为:将本地需要进行的计算任务迁移到云端进行。
如今云计算及其产物已经深入我们的生活,我们熟悉的百度网盘、iCloud 还有最近的阿里网盘就是「云存储」,以及本文要介绍的主角「云游戏」也是云计算的产物。
云游戏 云游戏的原理 在现在这个游戏变得越来越流行的时代,人们却被低配设备所限制,比如我,虽然出了很多新游戏,却苦于手头没有一台合适的机器用于玩耍。以往玩游戏我需要配一台游戏主机或者高性能游戏本,少说也要五六千,因为游戏对于计算机性能的要求是非常高的,这些都必须依赖玩家自己的电脑。
但是在云游戏模型中,所有的游戏逻辑和渲染都在服务器端运行,然后再从服务器把压缩的画面传给用户,这样玩家就不需要一台高性能的计算机了,对于设备的要求便也就是基本的视频渲染能力和可靠稳定的网络环境了。
云游戏摆脱了对硬件的依赖。对服务器来说,仅仅需要提高服务器性能而不需要研发新主机;对用户来说,可以得到更高的画质而不用购买高性能的计算机。也就是说,用户可以花一小笔钱租一个更好的计算机来玩各种游戏,就像用机顶盒看电视一样,这意味着玩家可以在计算机硬件,特别是 GPU 上省下一大笔钱。
云游戏需要什么? 低延时 在解释云游戏的原理时,我们提到了云游戏的游戏逻辑和渲染都是在服务器端进行,然后将画面传送给用户,所以说一台可以高速上网的设备极其重要。如果网速不够快,不够稳定就无法及时接收到高质量的画面。
说到这我们需要介绍一下网络延时,所谓网络延时指一个数据包从用户的计算机发送到网站服务器,然后再立即从网站服务器返回用户计算机的来回时间。通俗的讲,就是数据从电脑这边传到那边往返所用的时间。
以我们现在还在普遍使用的 4G 网络而言,它的延时基本在 30ms ~ 70ms 波动,部分信号不好的地方延时还会更大。这还只是数据传输时的网络延时,如果算上画面编解码的时间,延时达到 100ms 是很容易的事情。
我们知道视频的原理就是每秒播放多张静态画面,画面越多,对于人的观感来说就是视频越流畅。这是因为对于人眼来说,我们的视觉神经是有一个反应速度的,并且对于不同频率的光有不同的暂留时间。其时值约是 1/16 秒,也就是 62.5ms。也就是说,如果网络传输所消耗的延时大于 62.5ms,我们就会觉得画面很不流畅(62.5 是一个理论值,实际情况下这个数值会小于 62.5ms,对延时的要求更苛刻)。
高带宽 现在我们来做一个简单的数学题。
刚才我们说到视频的原理是每秒播放多张静态图像。我们知道图像都是由一个个像素点构成的,对于一张非黑即白的二值图像,不压缩的情况下一个像素只需要 1 个 bit。如果是 256 种状态的灰度图像,不压缩的情况下一个像素需要 8bit(1 字节,256 种状态)。如果用 256 种状态标识屏幕上某种颜色的灰度,而屏幕采用三基色红绿蓝(RGB),不压缩的情况下一个像素需要占用 24bit(3 字节),这个就是常说的 24 位真彩色。...