使用Electron构建跨平台的桌面应用

作者:李晓健。苏宁视频云前端部门经理。拥有7年前端业务研发和架构经验,目前负责苏宁云视频前端研发和架构工作。

Electron简介

Electron 是一个使用 JavaScript,HTML 和 CSS 等 Web 技术创建原生桌面程序的框架。官网是https://electronjs.org/

Electron就是使用Web技术来开发,然后打包成桌面客户端的一个框架。它渲染Web内容使用的是Chromium,Chromium基本上和大家常用的chrome浏览器差不多,并且Electron在打包时是将Chromium嵌入到了应用里,所以它并不依赖用户机器上安装的浏览器,大家都知道做Web开发,最大的一个问题就是兼容性的问题,经常相同的代码在不同操作系统中不同的浏览器里,甚至不同版本的浏览器里都可能会出现不同的效果。Electron相当于是把一个固定版本的浏览器嵌入到应用中,所以他就不存在兼容性问题,只要我们开发时写的代码可以正常运行,就不存在打包后在用户的机器上因为兼容性问题无法使用的情况。

Electron支持Node.js的原生模块,也就是说可以在Electron应用中直接使用Node.js的模块。Web应用为了安全等一系列的问题考虑,限制了很多的功能,比如本地文件的读写、操作系统中硬件设备的调用等等,但是Node.js并没有这些限制。也就是说在Electron应用中,我们不光可以使用Web技术的特点,还能够突破Web技术的限制,使用Node.js的模块功能,使应用功能更加丰富。

Electron开发出来的应用是跨平台的,当应用开发完成后,我们可以将同一套代码打包成Linux、macOS、Windows平台上的可执行程序或安装包。

Electron中比较重要的概念

学习任何一门框架,里面或多或少都会有一些新的概念,只有把这些新的概念都弄懂了,才能更好的掌握和运用这门框架,Electron中新的概念并不是很多,接下来我就就来说说最重要的3个概念。

1. 主进程:Electron应用中运行package.json的main脚本的进程被称为主进程,在主进程中运行的脚本通过创建web页面来展示用户界面。一个 Electron 应用总是有且只有一个主进程。

2. 渲染进程:Electron应用中是通过在主进程里创建web页面来展示用户界面的,在主进程中可以通过BrowserWindow 实例创建页面,这里的一个web页面就是运行在一个渲染进程里的,一个Electron应用可以包含多个web页面,所以一个Electron 应用中是可以有多个渲染进程的,当一个 BrowserWindow 实例被销毁后,相应的渲染进程也会被终止。

3. IPC:既然有主进程和渲染进程,而主进程管控的是一个应用全局的设置和方法,而渲染进程只在一个web页面中存在,那他们肯定不会始终完全孤立的存在,有时也是需要有通信的,比如我在页面做了一个操作,整个应用需要去做一个响应,就是就需要用到主进程和渲染进程的通信。就里就有一个概念IPC(Inter-Proess Communication),进程中通信。IPC就提供了相应的方法来供主进程和渲染进程间进行通信。

所以他们大概的关系就是一个应用中有一个主进程,然后主进程可以创建多个渲染进程,主进程和渲染进程间通过IPC来通信。如下图:

Electron的安装

Electron是以Node.js中的模块的方式进行发布的,所以他的安装也非常简单,通过npm来进行安装就可以了。既然Electron是通过Node.js的模块起先发布的,那它的安装就需要依赖Node.js的环境,也就是需要在我们的电脑上安装Node.js,安装Node.js直接去其官网( https://nodejs.org)下载相应的安装包,然后按照默认的设置一路安装就行了,在安装Node.js的同时也会安装上npm,安装完成后检测Node.js和npm是否安装成功,只需要在命令行工具拦执行相应的版本查看命令就行了,如果能看到有版本号输出,则说明安装成功。如下图:

接下来我们就可以直接使用npm来安装我们所需要的模块了。首先进入到我们的项目开发目录,然后初始化好项目(创建好package.json文件),然后在该目录执行

npm install electron –save

然后等待安装完成就行了。

在这个安装过程中,可能由于网络问题会安装失败,我们可以修改npm的镜像源,将npm的镜像源修改成国内的镜像源:在命令行执行 npm config set registry http://registry.npm.taobao.org/ 或者安装cnpm,然后通过cnpm来安装Node.js的模块。

安装完成后,在命令行执行

electron -v

可以看到electron的版本号,就说明Electron安装成功了。

Electron项目的搭建

Electron安装好就,就可以搭建项目了。官网给我们提供了一个空的种子项目,这个项目里面非常的干净,所以可以直接使用,首先我们通过命令行进入我们工作目录,克隆下这个项目(前提是我们的电脑需要安装git),执行

git clonehttps://github.com/electron/electron-quick-start.git

克隆完成后,我们的工作目录中就多了一个 electron-quick-start 目录,这个目录就是

我们的项目目录,这里面有几个文件是我们项目需要用到的文件

1. package.json:项目的一些依赖和配置文件,里面有一些我们项目的基本信息,我们可以根据自己项目的情况来修改这里的值 bash

{
  "name": "electron-quick-start", //项目的名称
  "version": "1.0.0", //项目的版本号
  "description": "A minimal Electron application", //项目的描述
  "main": "main.js", //主入口文件
  "scripts": { //快捷脚本
    "start": "electron ."
  },
  "repository": "https://github.com/electron/electron-quick-start", //代码仓库
  "keywords": [ //项目的关键词
    "Electron",
    "quick",
    "start",
    "tutorial",
    "demo"
  ],
  "author": "GitHub", //项目的作者
  "license": "CC0-1.0", //项目的许可协议
  "devDependencies": { //项目的依赖
    "electron": "^2.0.0"
  }
}

2. main.js:这个文件是项目的启动文件,也是项目的入口文件,该文件就是运行在主进程中的。

// 引入electron中的API

const {app, BrowserWindow} = require(‘electron’)

//定义一个web窗口 这个窗口就运行在一个一个渲染进程中

let mainWindow

//创建web窗口的方法

function createWindow () {

  // 通过BrowserWindow来创建一个窗口

  mainWindow = new BrowserWindow({width: 800, height: 600})

  // 在web窗口中加载html页面

  mainWindow.loadFile(‘index.html’)

  // 监听窗口关闭的事件

  mainWindow.on(‘closed’, function () {

    mainWindow = null

  })

}

// 当应用准备好了  就调用创建web窗口的方法

app.on(‘ready’, createWindow)

// 当所有的窗口都关闭后,就退出应用

app.on(‘window-all-closed’, function () {

    //在非MAC平台下退出应用

    //在MAC平台下所有窗口关闭 应用并不需要退出,它还可以通过dock来重新激活应用

  if (process.platform !== ‘darwin’) {

    app.quit()

  }

})

//当应用被激活事件 

app.on(‘activate’, function () {

  //如果窗口不存在 就创建一个窗口

  if (mainWindow === null) {

    createWindow()

  }

})

3. index.html:这是web窗口里展示需要展示的内容,当然这里也可以是一个远程html的url

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Hello World!</title>
  </head>
  <body>
    <h1>Hello World!</h1>
    <!-- All of the Node.js APIs are available in this renderer process. -->
    We are using Node.js <script>document.write(process.versions.node)</script>,
    Chromium <script>document.write(process.versions.chrome)</script>,
    and Electron <script>document.write(process.versions.electron)</script>.

    <script>
      // You can also require other files to run in this process
      require('./renderer.js')
    </script>
  </body>
</html>

这里就是一个普通的html,但是这里面也有和普通html不同之处,我们可以看到html的script标签里有用到process.xxx.xxx;并且前面没没有定义process,这里确可以直接访问,html里引入script用了require(‘./renderer.js’)。这些写法在我们平常的script里都会报错的,但是这里确可以正常运行的,原因就是我们前面说过的Electron应用中可以直接使用Node.js的Api,这里的process就是Node.js里的变量,require就是Node.js中引入外部文件的关键字。

renderer.js:这个文件是被引入到index.html中的,所以它就是用来写html中逻辑的文件,所以这个文件也是运行在渲染进程中的。

我们上面说到的4个文件的文件名和路径并不是固定的,也可以根据项目需要进行修改,他们的关系是main.js 就是 package.json中main属性对应的值,如果需要修改main.js的名称,这两处需要同时修改。index.html 就是在main.js中 mainWindow.loadFile(‘index.html’) 引入的文件,如果需要修改这两处也需要同时修改。renderer.js就是在index.html中require(‘./renderer.js’) 引入的js文件,当然这里也可以引入多个js谁的,和我们普通的html一样。

文件作用和关系都理清楚了,我们就可以安装依赖了。在命令行执行

npm install

等待安装完成之后,就可以运行项目了,在命令行执行

npm run start

这里的start 就是我们在package.json中scripts属性中配置的值 “start”: “electron .”,我们在命令行运行 npmrun start 就相当于我们运行 npm run electron . ;因为有时有些命令比较长或带了比较多的参数,所以我们在package.json中配置一些别名会大大减少我们在命令行的输入。等命令运行完成我们就可以看到我们的桌面上打开了一个客户端,如下图:

这样我们的一个初始项目就算搭建完成了。

Electron中常用的功能模块

electron不光是可以将我们的页面打包成客户端应用,它也为我们提供了大量的功能模块,方便我们的开发,下面我们就简单介绍一下用的比较多的功能模块。

1. app: 控制应用程序的事件生命周期,用于监听应用的的事件,该模块在主进程中。

2. BrowserWindow:创建和控制浏览器窗口,在创建窗口时可以传入很多的参数,来控制窗口的样式和行为该模块在主进程中。

3. ipcMain:从主进程到渲染进程的异步通信,该模块在主进程中。

4. ipcRenderer:从渲染进程到主进程的异步通信,该模块在渲染进程中。

5. remote:在渲染进程中引入主进程模块,该模块在渲染进程。

6. dialog:显示用于打开和保存文件、警报等的本机系统对话框,该模块在主进程中。

7. crashReporter:将崩溃日志提交给远程服务器

8. globalShortcut:当应用程序没有键盘焦点时监听全局键盘事件,该模块在主进程中。

9. Menu:创建原生应用菜单和上下文菜单,该模块在主进程中。

10. desktopCapturer:可以访问那些用于从桌面上捕获音频和视频的媒体源信息,该模块在渲染进程中。

11. net:使用Chromium的原生网络库发出HTTP/ HTTPS请求,该模块在主进程中。

12. autoUpdater:使应用程序能够自动更新,该模块在主进程中。

以上的这些模块都是比较常用的模块,所有的功能模块并不是在任何地方都可以调用,有些模块在主进程中可以直接引入,有些模块只能在渲染进程中引入,当然也有些模块可以直接主进程和渲染进程中引入使用。这些在主进程中的模块也是可以在渲染进程中引入的,不过不能直接引入,需要通过remote模块来间接引入,所以在主进程中的模块也是可以在渲染进程中使用,例如我们想在渲染进程中使用BrowserWindow:

//我们需要先引入remote模块
const {remote} = require('electron');
//再从remote模块中引入BrowserWindow
const {BrowserWindow} = remote
let win = new BrowserWindow({width: 800, height: 600})
win.loadURL('http://www,pptvyun.com')

更多的功能模块和使用方法可以参考Electron的文档:https://electronjs.org/docs

Electron的Demo

Electron的大概内容已经介绍的差不多了,接下来我们就使用Electron来做一个拍照保存的小demo,能正常运行需要您的电脑上有摄像头。我们的这个demo就基于前面搭建好的空项目来做。前面我们说过,项目的文件名和路径并不是固定的,接下来我们就来调整一下前面那个项目的目录结构,我们将我们需要写代码都放到src目录下,调整个目录如下:

我们将html代码放到view目录下,将样式文件放到style目录下,将图片放入到images目录下,将我们的js代码放到scripts目录下,将main.js改名为index.js(这里改文件只是为了说明这个文件名是可以修改的,并不是固定的),然后直接放到src目录下。

package.json 修改如下

{
  "name": "take-photo",
  "version": "0.0.1",
  "description": "A take photo Electron application",
  "main": "src/index.js",
  "scripts": {
    "start": "electron ."
  },
  "repository": "",
  "keywords": ["Electron","demo"],
  "author": "pptvyun",
  "license": "MIT",
  "devDependencies": {
    "electron": "^2.0.0"
  }
}

index.js 修改如下

// 引入electron中的API

const {app, BrowserWindow} = require(‘electron’)

//定义一个web窗口 这个窗口就运行在一个一个渲染进程中

let mainWindow

//创建web窗口的方法

function createWindow () {

    // 通过BrowserWindow来创建一个窗口

    mainWindow = new BrowserWindow({width: 800, height: 600})

    // 在web窗口中加载html页面

    mainWindow.loadFile(`${__dirname}/view/index.html`)

    // 监听窗口关闭的事件

    mainWindow.on(‘closed’, function () {

        mainWindow = null

    })

}

// 当应用准备好了  就调用创建web窗口的方法

app.on(‘ready’, createWindow)

// 当所有的窗口都关闭后,就退出应用

app.on(‘window-all-closed’, function () {

    //在非MAC平台下退出应用

    //在MAC平台下所有窗口关闭 应用并不需要退出,它还可以通过dock来重新激活应用

    if (process.platform !== ‘darwin’) {

        app.quit()

    }

})

//当应用被激活事件

app.on(‘activate’, function () {

    //如果窗口不存在 就创建一个窗口

    if (mainWindow === null) {

        createWindow()

    }

})

index.html 修改如下

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Hello World!</title>
  </head>
  <body>
    <h1>Hello World!</h1>
    <!-- All of the Node.js APIs are available in this renderer process. -->
    We are using Node.js <script>document.write(process.versions.node)</script>,
    Chromium <script>document.write(process.versions.chrome)</script>,
    and Electron <script>document.write(process.versions.electron)</script>.

    <script>
       //这里修改了renderer.js的引入路径
      require('../scripts/renderer.js')
    </script>
  </body>
</html>

接下来我们就根据我们的业务来写具体的代码,首先我们的代码肯定是需要调试的,Electron使用的是Chromium来做渲染的,所以它也给我们提供了chrome的开发者工具供我们使用。开发完成后的代码如下

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>take photo</title>
    <link rel="stylesheet" href="../style/index.css">
</head>
<body>
<header>拍照保存</header>
<div class="content">
    <video src="" id="video"></video>
    <canvas width="250" height="187" id="canvas"></canvas>
    <div class="button-box">
        <a href="javascript:;" id="openCamera" class="button">打开摄像头</a>
        <a href="javascript:;" id="takePhoto" class="button">拍摄照片</a>
        <a href="javascript:;" id="savePhoto" class="button">保存照片</a>
    </div>
</div>

<script>
    require('../scripts/renderer.js')
</script>
</body>
</html>

src/style/index.css

src/index.js

// 引入electron中的API
const {app, BrowserWindow,globalShortcut} = require('electron')

//定义一个web窗口 这个窗口就运行在一个一个渲染进程中
let mainWindow

//创建web窗口的方法
function createWindow () {
    // 通过BrowserWindow来创建一个窗口
    mainWindow = new BrowserWindow({width: 800, height: 600})

    // 在web窗口中加载html页面
    mainWindow.loadFile(`${__dirname}/view/index.html`)

    // 监听窗口关闭的事件
    mainWindow.on('closed', function () {
        mainWindow = null
    })
    //这里我们注册一个打开 开发者工具有快捷键 win下是Ctrl+F12 macOS下是command+f12
    globalShortcut.register('CommandOrControl+F12', () => {
        mainWindow.webContents.openDevTools()
    })
}

// 当应用准备好了  就调用创建web窗口的方法
app.on('ready', createWindow)

// 当所有的窗口都关闭后,就退出应用
app.on('window-all-closed', function () {
    //在非MAC平台下退出应用
    //在MAC平台下所有窗口关闭 应用并不需要退出,它还可以通过dock来重新激活应用
    if (process.platform !== 'darwin') {
        app.quit()
    }
})

//当应用被激活事件
app.on('activate', function () {
    //如果窗口不存在 就创建一个窗口
    if (mainWindow === null) {
        createWindow()
    }
})

src/sctipts/renderer.js

//引入Electron中的dialog 用来显示消息提示
const {dialog} = require('electron').remote
//引入Node.js的fs模块  用来写文件
const fs = require('fs');
//页面打开摄像头的按钮
const button = document.querySelector('#openCamera');
//页面拍摄照片的按钮
const takephoto = document.querySelector('#takePhoto');
//页面保存照片的按钮
const saveImage = document.querySelector('#savePhoto');
//页面的video标签,用来展示摄像头拍摄的画面
const video = document.querySelector('#video');
//页面的canvas标签,用来展示拍摄的照片
const canvas = document.querySelector('#canvas');
const ctx = canvas.getContext('2d');

//获取摄像头的参数
const mediaConfig = {
    video: true
}
//点击打开摄像头的按钮
button.addEventListener('click',e=>{
    //调用电脑的摄像头
    navigator.mediaDevices.getUserMedia(mediaConfig)
        .then(function(stream) {
            //将摄像头拍摄的内容给到video标签,并从video标签上播放
            video.srcObject = stream;
            video.onloadedmetadata = function(e) {
                video.play();
            };
        })
        .catch(function(err) {
            alert('打开挺像头失败')
        });
})

//点击拍照按钮
takephoto.addEventListener('click',e=>{
    //将video上的画面画到canvas上
    ctx.drawImage(video,0,0,250,187);
})
//点击保存图片按钮
saveImage.addEventListener('click',e=>{
    //选择图片的保存路径
    dialog.showOpenDialog({properties:['openDirectory']},filePaths=>{
        if(filePaths && filePaths[0]){
            //保存图片的目录
            const floder = filePaths[0]+'/';
            //奖canvas上的图片转成base64编码
            let dataURL = canvas.toDataURL('image/png');
            var regex = /^data:.+\/(.+);base64,(.*)$/;
            if(dataURL){
                var matches = dataURL.match(regex);
                var buffer = new Buffer(matches[2], 'base64');
                //将文件流写入选择的目录里
                const file = floder+Date.now()+'.' + matches[1];
                fs.writeFile(file, buffer,err=>{
                    if(err){
                        dialog.showErrorBox("错误提示", '图片保存失败')
                    }else{
                        //图片保存成功的提示
                        dialog.showMessageBox({
                            type:'info',
                            title:'提示信息',
                            message:'图片保存成功,文件保存在'+file,
                        })
                    }
                });
            }
        }
    })
})

代码开发完成后,运行项目,在命令行输入

npm run start

就可以看到项目结果了,页面会出现3个按钮,点击打开摄头,客户端上就会出现摄像头拍摄的内容,然后点击保存照片按钮,客户端就会出现一张静态的图片,然后点击保存按钮,这张图片就会保存在我们选择的目录下。效果如下图:

Electron项目的构建

这个demo开发到这里就算完成了,但是我们的客户端还是需要给别人来使用,总不能让别人把我们的代码拷过去,然后安装依赖,在命令行运行npm run start吧,我们常见的客户端都是有一个安装程序,安装之后就可以直接双击运行的,或者是一个绿色版,有一个可执行程序,我们双击就可以运行的。接下来我们就也把我们的demo打包成一个安装程序,可供用户安装使用。

将Electron打包成安装程序有多种方式,今天我们说的是通过 electron-builder 模块来打包,electron-builder也是一个Node.js的模块,所以我们可以直接通过npm来安装,在命令行运行

npm install electron-builder –save-dev

等待安装完成就可以了,它的文档在https://github.com/electron-userland/electron-builder ,它可以打包出window、macOS、Linux上的可执行程序。然后我们参照文档修改配置文件,这里只需要修改package.json就好。修改后如下

{
  "name": "take-photo",
  "version": "0.0.1",
  "description": "A take photo Electron application",
  "main": "src/index.js",
  "scripts": {
    "start": "electron .",
    "build-all": "electron-builder -mwl",
    "build-win": "electron-builder --win --x64",
    "build-mac": "electron-builder --mac --x64",
    "build-linux": "electron-builder --linux --x64"
  },
  "build": {
    "appId": "com.pptvyun.test",
    "copyright": "pptvyun",
    "productName": "demo",
    "mac": {
      "target": "dmg"
    },
    "dmg": {
      "window": {
        "x": 200,
        "y": 200,
        "width": 800,
        "height": 600
      }
    },
    "win": {
      "icon": "logo.png",
      "target": "nsis"
    },
    "nsis": {
      "oneClick": false,
      "allowToChangeInstallationDirectory": true,
      "artifactName": "Setup-${productName}-${version}-${arch}.${ext}"
    },
    "snap": {}
  },
  "repository": "",
  "keywords": [
    "Electron",
    "demo"
  ],
  "author": "pptvyun",
  "license": "MIT",
  "devDependencies": {
    "electron": "^2.0.0",
    "electron-builder": "^20.19.2"
  }
}

在scripts中添加了在各个平台上的打包脚本,添加了build属性,用来配置在各个平台上的打包参数。我们用打包出window平台的安装程序为例,在命令行运行

npm run build-win

等待打包完成,第一次可能会有点慢,因为它需要下载一些依赖,打包完成后我们的项目里就会多出来一个build的目录,当然这个目录是我们在package.json中配置的,这个目录里就是打包之后的文件,里面有一个win-unpacked的目录,这个目录里有一个demo.exe的文件,这个文件就是可执行程序,这个win-unpacked目录里的文件就相当于是我们平常见的绿色免安装版,直接双击demo.exe就可以运行这个demo。还有一个Setup-demo-0.0.1.exe文件,这个文件就是我们需要的安装程序,双击它就可以运行安装,安装完成后也会在我们的桌面创建快捷方式,不同平台的打包命令可能需要到相应的平台上去执行,比如在window上执行macOS的打包命令可能会失败。

至此,我们的demo就算开发完成了,当然这里还有一些细节上的东西需要注意,比如我们的应用需要在各大平台上发布,供其他用户来下载安装,就需要对代码进行签名,代码签名具体可参考文档https://electronjs.org/docs/tutorial/code-signing ,这里的客户端界面我们用的是默认的,当然我们也可以做一个无边框的应用,然后自定义客户端的界面,还有自动升级等等功能,Electron都是可以支持的,可以查看它的官方文档做出功能丰富的客户端面应用。

Image placeholder
IT头条
未设置
  58人点赞

没有讨论,发表一下自己的看法吧

推荐文章
使用 Go Wails 框架来构建桌面应用(Go+Vue.js)

众所周知,Go主要用于构建API、web后端和CLI工具。但有趣的是,Go可以用在我们没有预料到的地方。 例如,我们可以使用Wails框架用Go和Vue.js构建一个桌面应用程序。 这是一个新框架,

如何构建批流一体数据融合平台的一致性语义保证?

一、批流一体架构 批和流是数据融合的两种应用形态 下图来自Flink官网。传统的数据融合通常基于批模式。在批的模式下,我们会通过一些周期性运行的ETLJOB,将数据从关系型数据库、文件存储向下游的目标

跨平台开发的救星-让我们来了解一下flutter

第一次看文章的朋友可以关注我,会不定期发布Android面试内容、进阶专题等等。简介很多人已经用上了flutter,今天就来介绍一下Flutter架构Flutter框架分三层 Framework,En

Kafka 集群在马蜂窝大数据平台的优化与应用扩展

马蜂窝技术原创文章,更多干货请订阅公众号:mfwtechKafka是当下热门的消息队列中间件,它可以实时地处理海量数据,具备高吞吐、低延时等特性及可靠的消息异步传递机制,可以很好地解决不同系统间数据的

通过 Laravel 创建一个 Vue 单页面应用(一)

使用laravel创建一个Vue单页面应用(SPA)可以构建一个整洁的由API驱动的应用。在此教程中,我们将学习如何构建并运行一个以Vue路由为前端,laravel为后端的SPA应用。首先我们将注意

通过 Laravel 创建一个 Vue 单页面应用(三)

我们将通过演示在vue-router进入一个路由之前,如何异步加载数据来继续使用Laravel构建我们的VueSPA。 之前在通过Laravel创建一个Vue单页应用(二)中完成了UsersInde

Onvif/RTSP海康大华网络安防摄像机网页无插件直播方案EasyNVR如何使用Excel将通道配置简单化?

进入移动互联网时代以来,企业微信公众号已成为除官网以外非常重要的宣传渠道,当3.2亿直播用户与9亿微信用户的势能累加,在微信上开启直播已成为越来越多企业的必然选择。EasyNVR核心在于摄像机的音视频

我们可以不再使用ETL了吗?

近年来,我们在数据科学和高级分析方面取得了一些进步,但许多项目仍然采用20世纪80年代的遗留技术:萃取(extract)、转置(transform)和加载(load),也就是我们所说的ETL。这让数据

百分点万亿级大数据平台的建设实践

从互联网、移动互联网到物联网,数据量之巨大已突破想象边界。与此同时,实时数据分析的需求日益增长,那么,当数据量达到亿级、百亿级甚至万亿级规模,实时数据分析如何来做?尤其在ToB/G来说,大多数企业和政

Kubernetes1.14 版发布,增强了云原生平台的Windows节点支持

Kubernetes1.14GA版本,是开源云原生平台Kubernetes在2019年的一次重大更新。自3月25日开始,这一版本正式推出,供开发者全面使用。  Kubernetes,由云原生计算基金会

日均5亿查询量的京东订单中心,为什么舍MySQL用ES?

京东到家订单中心系统业务中,无论是外部商家的订单生产,或是内部上下游系统的依赖,订单查询的调用量都非常大,造成了订单数据读多写少的情况。我们把订单数据存储在MySQL中,但显然只通过DB来支撑大量的查

IBM Spectrum Protect 8.1.7在AIX7.1上的安装和配置

                                                本文作者: 谷铁柏摘要:    本文章主要讲述IBMSpectrumProtect8.1.7版本在AIX

electron+vue实现div contenteditable功能|截图

最近在学习基于electron+electron-vue开发聊天客户端项目时,需要用到编辑器插入表情功能。一般通过input或textarea也能实现,通过插入[笑脸]、(:12这些标签,展示的时候解

这次华为重构园区网的目标:让光纤到每个桌面

当下,5G成为了聚光灯的宠儿,但5G的发展需要更快的光网络作为基础,5G基站之间的连接、5G基站到主干线等都需要光网络,从用户需求而言,VR/AR、4K/8K高清、云网专线等业务兴起,也亟需光网络升级

干货!IP桌面电话选购的五大要点

随着人们对高效便捷工作方式的追求,移动办公和分布式团队愈发普及。协作空间已不再局限于常规的会议室,它可能是一张办公桌或提供Wi-Fi的咖啡厅,空间风格也逐渐向轻松随意的氛围转变。如何随时、随地利用任何

中台的末路

从15年开始,到19年现在为止。各大公司都在吹捧中台理念。仿佛中台是业务复杂性的救世主。是某些架构师和PM的新出路。各种割韭菜的讲中台的课程层出不穷。 当然,吹牛逼的时候大家都是拣好的说,苦逼的东西就

支付中台的几个面向:支付业务、资金核算、面向风控等切面

手哥架构宝典之支付系统1.0发布后,很多架构师朋友表示受益匪浅,询问支付系统2.0版本什么时候放出来,今天刊发出《架构宝典》支付系统2.0版本,以飨读者。00 概述在1.0的支付系统中,我们遇到了诸多

​中台战略:业务中台的8个设计原则

业务中台是一个充满生命力的个体,它承载业务逻辑、沉淀业务数据、产生业务价值,并随着业务不断发展进化。它的设计遵循如下图所示的8个原则。业务中台设计的8大原则01 服务松耦合原则(1)面向接口实现这是服

基于 Laravel6.x 构建的博客应用,支持 Markdown,支持 RBAC 权限管理

基于Laravel6.x构建的博客应用,支持Markdown,支持图片拖拽上传,基于RBAC权限管理系统首页基于RBAC的权限管理后台,Dashboard页面统计了用户总数、文章发布总数、评论率、评论

如何构建“小数据”驱动的泛场景智能应用体系?

张真百信银行首席技术架构师&AILab负责人目前负责基于自然语言的动态银行研究与落地,关注AI技术与金融,办公,生活场景的深度融入;开源软件UAVStack创始人,面向智能运维提供解决方案,AIOps

【Kubernetes系列】第5篇 Ingress controller – traefik组件介绍

1.概述为了能够让Ingress资源能够工作,在Kubernetes集群中必须至少有一个运行中的ingresscontroller组件。也就是说如果在kubernetes集群中没有一个ingressc

如何使用Vue构建Chrome扩展程序

浏览器扩展程序是可以修改和增强Web浏览器功能的小程序。它们可用于各种任务,例如阻止广告,管理密码,组织标签,改变网页的外观和行为等等。好消息是浏览器扩展并不难写。可以用你已经熟悉的Web技术(HTM

PHP跌出前十,铁打的 Python 连续3年第一:IEEE Spectrum 2019编程语言排行榜出炉

Python势头不减,依旧第一,而且进一步拉开了与其他语言的差距。这一结果,来自IEEESpectrum2019年度编程语言排行榜。这已经是Python连续3年保持第一。在Python之下,第二交椅的

php常用字符串查找函数strstr()与strpos()实例分析

这篇文章主要介绍了php常用字符串查找函数strstr()与strpos(),结合具体实例形式分析了php字符串查找函数strstr()与strpos()的具体功能、用法、区别及相关操作注意事项,需要

1.0. 抽象工厂模式(Abstract Factory)

1.1.1.目的 在不指定具体类的情况下创建一系列相关或依赖对象。通常创建的类都实现相同的接口。抽象工厂的客户并不关心这些对象是如何创建的,它只是知道它们是如何一起运行的。 1.1.2.UML图 1