内容简介:If you want to build a modern web app, you typically need to use a few different tools: one set for the front-end, and another for the back-end. In addition, you would need to learn and use a different API (and often even a different programming language)
Browser Functions: A new serverless platform using Web Browser execution engines
Dec 9, 2019 ·6min read
If you want to build a modern web app, you typically need to use a few different tools: one set for the front-end, and another for the back-end. In addition, you would need to learn and use a different API (and often even a different programming language) for the back-end. However, the Web API is a rich and stable API, and the web browser is a stable, powerful and secure execution environment. So why then can we not use this execution environment for our back-end too? This is the question we asked ourselves at IBM Research , so we decided to try running a browser on the server. This turned out to work much better than we had anticipated!
Browser-to-Browser communication
Our first challenge was: how do we get many desktop browsers to talk to a browser on the server? The solution
we came up with is simple: run a regular web server, and have it forward the requests to the server browser
(which we will call the Execution Engine
), which then processes the requests in tabs (i.e. loads the web page and runs a main()
JavaScript function), and returns the results back. We created a controller tab
that runs on the execution engine, which talks to the web server using a WebSocket, and then opens and closes (or re-uses) tabs on-demand. This simple setup was all that was needed to get the system functional.
Performance
Initially, we were concerned about how this might perform. After all, browsers are built to run on desktops, and hence to not utilize too many resources, so as to keep the rest of the system responsive. On a server however, we’d like maximum hardware utilization so that we can optimize the throughput and response times. So we built a proof-of-concept, and ran some performance tests. We ran the execution engine in headless mode, which makes it perform more like a back-end server. When we saw response times of around 20 milliseconds for a full round-trip function execution, our concerns were eased! Some more performance testing on a laptop showed that, in general, performance is about 10 times better * than a container-based serverless platform running the same function, on the same machine.
* This is a baseline comparative test, running a trivial JavaScript function on two platforms. Other tests with different workload or test profiles may reveal different performance results.
Surprising benefits
What we’d basically ended up with is a performant serverless platform, which we are calling Browser Functions, that can execute web front-end code on the back-end. As we explored this idea further, we realized some surprising benefits to this platform:
We can now do full stack development using just Web APIs. Need to read/write network resources
? Use the fetch
API. Need to cache some data
? Use localStorage
. Need to blur an image
? Use a CSS filter on an img
tag. Need to manage sessions
? Use cookies. Need multi-threading? Use Web Workers
. Need native compiled speed
(or a language other than JavaScript)? Use WebAssembly.
We already have all the tools needed to develop and debug the back-end code on our local development machines: the desktop web browser! We can develop locally, then upload the code to the server, and it just works.
The server is lightweight and easy to install and maintain. Running tens of thousands of simple requests on the server uses less than 2Gb of RAM.
We benefit from the proven, tested, and constantly updated security that the browser vendors have developed to protect one website from another. We use domain isolation to leverage this security by running each application in a separate domain.
We have hardware acceleration in the form of WebGL (if a 3D graphics card is available). We can leverage this by using JavaScript libraries that use WebGL, such as gpu.js or Tensorflow.js.
We have free, distributed “package management” in the form of <script>
or <link>
tags that can pull content directly from CDNs. Thanks to the CDNs, the initial load of external resources are fast, and the execution engines will then cache these resources for subsequent invocations. Versioning is supported, as is integrity checking, via subresource integrity
.
Any modern browser could run as an execution engine. We use Firefox or Chrome/Chromium as they support headless mode, and we can leverage Puppeteer support on the server for automation.
We can add more execution engines to a single web server instance simply by opening a web browser to the server URL. The web server automatically load balances across all connected execution engines. Instant scaling!
These execution engines could be running anywhere, including inside our private network, thus enabling a hybrid-cloud approach. We could even run them on desktops/laptops/Raspberry Pi’s.
Show me the code
What do browser functions look like? Initially, they were complete web pages with a JavaScript main()
function that gets called, and its return value returned as the result of the function call. We wanted to make this easier though, so we currently support HTML fragments and pure JavaScript functions that are then automatically embedded into a full web page with the associated HTML5 boilerplate.
Here is a basic and complete “hello world” JavaScript example:
function main() {
return "Hello, world!";
}
To run this function, upload the function file to an existing Browser Functions server (or use the local development tools), and then execute the function by calling it as a REST endpoint:
home$ curl https://server/execute/hello/function.js
Hello, world!
home$
Browser Functions also provides function arguments, environment variables, ability to set return headers, and more, via a simple API .
Use cases
You may be wondering why you wouldn’t just run the functions on client browsers instead of on an execution engine. Running the code on a hosted server is useful when you need to:
- protect sensitive credentials from the client, e.g. database login or API keys
- run the function on a trigger, e.g. on a schedule, or via Webhooks
- expose private cloud data to public, i.e. the function runs inside a private network
- work around CORS restrictions, i.e. proxy clients through the server
- have the function be consumed by non-browsers, e.g. mobile apps, embedded devices
- pre-render content for old browsers/embedded devices/smart watches, e.g. render an SVG, return the image
- perform resource intensive computations on the server, e.g. Tensorflow.js inference or GPU.js calculations
- add a caching layer to a rate-limited external API, e.g. twitter
These are just some of the scenarios we thought of, but we’re really looking forward to seeing how other developers make use of or build on this platform.
Here’s a simple example of how we used Browser Functions in one of our projects. We created a static web site for a product, which included a contact form. We wanted to store the contact form submissions into our CouchDB database. We didn’t want to do this directly from the client browser, because we would need to enable CORS for all origins on our database (reduces security), and we would need to send the authentication tokens (with write access to the database) to the client. So instead, we had our form submit its data to a browser function:
<form action="/execute/form_to_couchdb.html" method="POST">
<input type="text" name="full_name" value="">
<input type="text" name="email_address" value="">
<textarea name="message"></textarea>
<input type="submit" name="submit">
</form>
In our browser function, we grabbed the submitted form data, and posted this into a new document in CouchDB using its REST API, as follows:
The end result was simple and very quick to implement. In addition, we implemented a daily digest e-mail of contact details submitted, which is a browser function that we called from a cron
job (i.e. on a timer). This function loaded the documents saved since the last digest run from CouchDB, created a DOM rendering of the content suitable for an e-mail, grabbed the innerHTML
of that rendering, and sent that off as an email using an e-mail service.
Try it out, and contribute
We believe we’ve barely scratched the surface of what’s possible when using the Web API on the back-end. For example, we have yet to explore how we might leverage API’s such as WebAssembly, WebRTC, WebUSB, WebSocket, or many other capabilities of the web browser; how browser extensions/add-ons or even Puppeteer could be used as a mechanism to manage running worker tabs (CPU limits, RAM limits, billing, etc); or performance optimization using browser settings, command-line switches, or custom browser builds. This is why we’ve open sourced Browser Functions, so that you can get involved in exploring and extending this platform with us.
The source code and documentation is available at: https://github.com/IBM/browser-functions
NOTE: The URLs used in the demo videos above are not publicly accessible.
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
人工智能产品经理——AI时代PM修炼手册
张竞宇 / 电子工业出版社 / 2018-6 / 59
随着人工智能热潮的兴起,企业对人工智能领域产品经理的人才需求也开始井喷,人工智能产品经理成为顺应时代潮流的重要人力资源。实际上,人工智能确实给现有的产品和服务带来了全方位的升级,这也给产品经理从业人员提出了更高的要求,是关注人工智能产品的产品经理们面临的一次关键转型考验。 《人工智能产品经理——AI时代PM修炼手册》从知识体系、能力模型、沟通技巧等方面帮助大家系统地梳理了人工智能产品经理所必......一起来看看 《人工智能产品经理——AI时代PM修炼手册》 这本书的介绍吧!
CSS 压缩/解压工具
在线压缩/解压 CSS 代码
MD5 加密
MD5 加密工具