Guacamole是一个由Apache开发的支持Web端连接VNC服务器并在网页上远程控制计算机的平台,它支持配置文件认证、基于数据库的认证等多种认证方式。还支持RDP、VNC等多种远程连接协议,对于私有云平台和个人管理服务器有着非常方便的作用。

Guacamole环境分为Server和Client两部分。Server包含Guacamole所需要的所有基础组件,以及guac(真正发起远程连接的代理程序,在系统中以daemon的形式运行,为guacd),而Client包括Web服务的war包(对用户提供Web端登录页面和远程控制页面)。

用户在Web端登录之后,tomcat会请求guacd,由guacd发起对要连接的服务器的远程连接请求,并转发到tomcat端,实时的在Web端页面上进行展示。具体工作序列图如下图。

TIM截图20180413132355.png

搭建Guacamole的过程如下:

1、克隆GitHub上的代码。

$ git clone git://github.com/apache/guacamole-server.git
Cloning into 'guacamole-server'...
remote: Counting objects: 6769, done.
remote: Compressing objects: 100% (2244/2244), done.
remote: Total 6769 (delta 3058), reused 6718 (delta 3008)
Receiving objects: 100% (6769/6769), 2.32 MiB | 777 KiB/s, done.
Resolving deltas: 100% (3058/3058), done.
$

2、默认下载下来的代码中是不包含configure文件的,因此无法直接make,需要先生成configure文件。

$ cd guacamole-server/
$ autoreconf -fi
$

若无法正常执行autoreconf,请先安装GNU Autotools工具。具体安装过程每个Linux发行版有区别,可自行搜索。

3、根据需要先安装各种需要用到的远程协议。如果需要用到VNC连接,则需先安装libvncserver-devel包,如果需要用到RDP连接,则需要先安装freerdp-devel包。

4、远程协议工具包安装完毕后,执行configure设置命令,根据具体报错信息,安装缺少的软件包。

$ ./configure --with-init-dir=/etc/init.d
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
...

------------------------------------------------
guacamole-server version 0.9.14
------------------------------------------------

   Library status:

     freerdp ............. yes
     pango ............... yes
...

Type "make" to compile guacamole-server.

$

5、设置完成之后,执行make,进行源码编译。

6、Server端编译成功之后,需要编译Client端。因为Client端为纯Java实现,所以需要先搭建Maven构建环境。因搭建Maven环境的解决方案很多,这里不再赘述。

7、Maven环境搭建完成之后,先克隆Client端源码。

$ git clone git://github.com/apache/guacamole-client.git
Cloning into 'guacamole-client'...
remote: Counting objects: 12788, done.
remote: Compressing objects: 100% (4183/4183), done.
remote: Total 12788 (delta 3942), reused 12667 (delta 3822)
Receiving objects: 100% (12788/12788), 3.23 MiB | 799 KiB/s, done.
Resolving deltas: 100% (3942/3942), done.
$

8、直接在代码目录执行“mvn package”,即可完成构建。

$ mvn package
[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Build Order:
[INFO] 
[INFO] guacamole-common
[INFO] guacamole-ext
[INFO] guacamole-common-js
...
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 34.701 s
[INFO] Finished at: 2015-06-08T17:03:15-07:00
[INFO] Final Memory: 34M/340M
[INFO] ------------------------------------------------------------------------
$

9、Client构建完成之后,可以在“guacamole-client/guacamole”目录找到war包,将其复制到tomcat的webapps目录下启动tomcat即可。

10、在正式启动Guacamole之前,需要对其做一些设置。Guacamole的默认配置目录在“/etc/guacamole”下,一般情况下,所有的配置文件都存放在这个目录。首先,需要对guacd的配置文件进行设置。切换到“/etc/guacamole”文件夹,新建“guacd.conf”文件,并写入如下内容:

#
# guacd configuration file
#

[daemon]

pid_file = /var/run/guacd.pid
log_level = info


[server]

bind_port = 4822

其中“bind_port”代表guacd监听的供tomcat端连接的代理端口。默认为4822。

11、新建“guacamole.properties”文件,并写入如下内容:

guacd-hostname: 127.0.0.1
guacd-port:     4822

这里指定了要连接的guacd的地址和端口。若guacd部署在另外一台服务器上,则这里的地址和端口需要做相应调整。

12、新建“user-mapping.xml”,并写入如下内容:

<user-mapping>    
    <!-- Per-user authentication and config information -->
    <authorize username="admin" password="admin">
        <protocol>vnc</protocol>
        <param name="hostname">192.168.56.101</param>
        <param name="port">5900</param>
        <param name="password">test</param>
    </authorize>
</user-mapping>

其中,每一个authorize标签代表一个可用的用户,该标签中的protocol标签代表连接协议,可选“vnc”、“rdp”等。param标签为该协议下所需要的配置。具体可参阅Guacamole配置官方文档

13、配置完毕之后,先启动guacd,执行下列命令:

service guacd start

并启动tomcat,之后访问“http://127.0.0.1:8080/guacamole”,即可跳转到登录界面。
TIM截图20180413135422.png

14、输入正确的用户名和密码,之后就可以在网页上远程控制设置的服务器了。
TIM截图20180413135651.png

前面我们讲述了如何基于“go-bindata-assetfs”开源工具包将html/js/css静态文件打包到Go程序中,形成一个一体化Web服务程序(点此查看)。解决方案最核心的一句代码如下:

//静态请求,由AssetFS统一处理。
http.Handle("/", http.FileServer(assetFS()))

我们知道,如果需要对路由做更加灵活的处理,需要使用http.HandleFunc方法。那么上述代码意味着所有访问"/"路径下,未经其他路由处理过的路径都将被“assetfs”处理。这种方式在一些需要动态解析的场景下会存在比较麻烦的问题。

举例说明,在某种场景下我们虽然需要直接显示html文件,但是又必须在html回送给客户端前对其进行解析,加入动态查询的数据(如基于“template”包来进行模版渲染的伪静态文件)。这个时候,我们需要将“assetfs”提供给我们的数据结构进行灵活使用,先获取到html等静态文件的内容,把它当作模板进行解析,然后再输出到客户端。

下面将给出相应的解决方案,可以趁此机会,更好更细节的理解“assetfs”的工作原理。核心代码如下:

fs := assetFS()
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
  path := r.URL.Path
  if path == "/" || strings.Contains(path, ".html") {
    //根目录默认显示首页。
    if path == "/" {
      path = "/index.html"
    }
    data, _ := fs.Asset("pages" + path)
    html := string(data)
    //这里可以对html页面数据进行处理。
    //...
    w.Header().Add("Content-Type", "text/html; charset=UTF-8")
    w.Write([]byte(html))
  } else {
    //其他处理。
    //...
  }
})

示例中,fs.Asset方法,作用是根据文件路径获取到该文件内容的字节数组。有一点需要注意的是,传入的文件路径必须带有文件编译前的前缀,如某“aaa.html”文件编译时,所在的解决方案路径为“xxx/yyy/”,VSCode终端中运行的是“go-bindata-assetfs xxx/yyy/...”,那么最终在使用fs.Asset方法获取文件内容字节数组时,应使用如下调用格式:

fs.Asset("xxx/yyy/aaa.html")

否则将无法获取到真实的数据。

Go的高性能,使它天生适合开发io方面的服务,Web服务当然不再话下。同时,Go编译后生成的单文件不是字节码,而是对应平台的机器码,因此它效率更高、资源占用更低。

为了更好的进程程序管理,移动程序时更加方便,本文将尝试将Web服务的资源文件打包到Go生成的二进制文件中。

本文将使用一个开源项目“go-bindata-assetfs”来实现目标。该项目的基本原理非常简单,这里描述如下:

1、读取指定的目录,递归的将文件相对路径和字节流的对应关系用变量定义和byte字面值来保存在“bindata.go”文件中。
TIM截图20180227104817.png

2、“bindata.go”文件参与项目编译与构建,从而将文件数据打包进最终生成的二进制文件中。

3、在Web服务需要的地方,构造“http.FileServer”所需要的“FileSystem”参数。此项目自己定义了“AssetFS”结构体,实现了“FileSystem”接口所需要的“Open”方法,在收到request访问指定文件时,由“AssetFS”定义的“Open”方法,经由相关逻辑,直接返回该文件的字节流。
TIM截图20180301101709.png

本例中使用VSCode进行开发与构建,在进行开发前,首先需要先配置VSCode的Go开发环境,并保证所有的Go相关exe可直接在cmd中运行。相关步骤如下:

1、新建工程目录,并创建“main.go”,输入代码。

2、在VSCode终端中执行命令:

go get github.com/jteeuwen/go-bindata/...
go get github.com/elazarl/go-bindata-assetfs/...

TIM截图20180301102053.png

3、创建“static”目录,将相关html/js/css文件都放在该文件夹下。
TIM截图20180301102120.png

4、在终端中执行命令:

go-bindata-assetfs static/...

执行完毕之后,工程目录下会自动生成“bindata.go”文件,该文件下包含“static”文件夹下的所有文件的字节流定义。
TIM截图20180301102157.png

5、定义Web服务相关逻辑,代码如下:

func startWebServer() {
    log.Println("starting web server...")
    //动态请求1。
    http.HandleFunc("/rpc/", ideaLicenseHandler)
    //动态请求2。
    http.HandleFunc("/getUserList", getUserListHandler)
    //静态请求,由AssetFS统一处理。
    http.Handle("/", http.FileServer(assetFS()))
    err := http.ListenAndServe(fmt.Sprintf(":%d", serverPort), nil)
    if err != nil {
        log.Panic("ListenAndServe: ", err)
    }
}

至此,Web服务开发完毕,相关静态资源文件也已打包到二进制文件中。可以打开浏览器查看效果。
TIM截图20180301102637.png

前篇搭建了最简单的可以调试Java代码的环境,本文将配置VSCode的Maven环境,使导入仓库包更方便。

  1. 首先配置可以正常使用的Maven环境。
  2. 新建一个临时空目录,在其中创建必须的几个文件和文件夹,包括“pom.xml”、“src/main/java”。TIM截图20180227103830.png
  3. 修改VSCode中与Maven相关的配置,将Maven可执行文件(windows平台为“mvn.cmd”)的绝对路径填写在“maven.executable.path”配置项中,并将Maven配置文件“settings.xml”的绝对路径填写在“java.configuration.maven.userSettings”配置项中。TIM截图20180227104002.png
  4. 保存配置并重启VSCode,之后在“pom.xml”文件上右击,并选择“Update project configration”。TIM截图20180227104817.png
  5. 之后,VSCode的Java插件将会在工作区中生成相关的文件(“.classpath”、“target”等)。TIM截图20180227104225.png
  6. 在工作区下方,即可选择Maven工程的常用命令。TIM截图20180227104447.png
  7. 配置完成后,代码中可直接提示出“pom.xml”包含的包中的类。TIM截图20180227104601.png

VSCode是微软开发的简单而又强大的文本编辑器,使用官方提供的插件市场,可以安装支持各种编程语言(C/C++/C#等)的调试插件,从而将其转变为各个语言的IDE环境。

众所周知,在Java程序开发过程中,经常会碰到要测试一些简单的代码或微小的demo的情况。而使用传统的Eclipse/IntelliJ IDEA环境来进行测试,创建工程、导入包、修改工程设置等步骤又非常的繁琐。因此,使用VSCode来进行测试过程,就不失为一个良好的选择了。

使用VSCode搭建简单Java开发环境非常简单,操作步骤如下:

  1. 在插件市场中搜索“Java Extension Pack”并安装。 TIM截图20180226101826.png
  2. 在磁盘中创建一个临时空目录,并创建“Main.java”。之后,使用VSCode打开该目录。 TIM截图20180226102429.png
  3. 在“Main.java”文件中输入或粘贴要测试的代码 TIM截图20180226102606.png
  4. 打开“调试”选项卡(或按下“Ctrl+Alt+D”),并选择“添加配置”。 TIM截图20180226102812.png
  5. 打开“launch.json”,并修改配置项“mainClass”为真实的主类名(本例中为“Main”)。 TIM截图20180226102951.png
  6. 在启动调试前,还需要设置“JAVA_HOME”的路径。打开“文件”--“首选项”--“设置”(或按下“Ctrl+,”),并修改“java.home”配置项为真实的“JAVA_HOME”路径。 TIM截图20180226103050.png
  7. 至此,环境配置完毕,可直接按下“F5”键启动调试,并可正常下断点和监视变量。 TIM截图20180226103710.png