使用Swoole与Shlink.io在Ubuntu 20.04系统上搭建高性能短网址程序

短网址程序想必大家不会陌生。有的时候我们需要发送一条非常长的链接,如果能将其缩短,将会非常方便。市面上有各类现成的短网址服务;如果我们拥有一个短域名,我们也可以自己搭建短域名服务器。

现成的免费短网址程序非常多,比如大名鼎鼎的Yourls, 等等。这些程序大多数基于传统PHP, 性能较差,特别是访问量多了以后数据库查询非常耗时。另外,这些短网址程序也不能提供详细的访问记录与数据分析。

如果您只是想要用短网址程序,那么我推荐您使用我提供的免费短网址服务器。您只需要解析您的域名到我的服务器地址上,即可使用您的短域名添加短链接,非常方便,无需任何设置。具体使用方法可以看这里:https://qing.su/shorturl

如果您仍然想用自己的服务器来搭建,那么今天我来介绍一个好用的高性能短网址程序,Shlink.io.  它基于Swoole-PHP, 采用Mezzio, Doctrine, Symfony等最新的技术,拥有其他短网址程序无法比拟的性能,支持高并发与快速数据库查询。另外,它提供丰富的数据分析和API, 能够按照标签、地域等做单项统计,获得专业的数据分析。它的API功能非常强大,您可以自由定制想要实现的功能。它的搭建过程比较复杂,我们这里先简单介绍一下一键Docker搭建(不推荐),然后再详细介绍手工搭建。程序源码及使用教程在这里https://github.com/shlinkio/shlink.  很遗憾,官方的搭建教程比较简略,建议您参考这篇文章来搭建,否则可能会遇到各种预料之外的情况。

本文作者为香菇肥牛,原文链接为https://qing.su/article/160.html, 转载请注明原文链接。谢谢!

1, 使用Docker搭建

Docker搭建Shlink.io非常简单,您只需要执行下面的命令就可以了。

1
2
3
4
5
6
7
docker run \
        --name my_shlink \
        -p 8080:8080 \
        -e SHORT_DOMAIN_HOST=qing.su \
        -e SHORT_DOMAIN_SCHEMA=https \
        -e GEOLITE_LICENSE_KEY=kjh2.qing.su.d3kj345 \
        shlinkio/shlink:stable

命令中的Geolite_License_Key我在后面会详细提到。由于整个程序可以定制和修改的部分较多,因此我这里建议手动安装Shlink.io系统。

 

2, 手动搭建——系统环境要求

本教程的系统环境为Ubuntu 20.04 LTS 64 bit.  您可以使用其他的操作系统,但是因为Shlink.io需要PHP 7.4, 因此在使用其他操作系统安装的时候可能需要额外添加源。

短网址程序的所有数据均存在数据库中。下面的教程将使用MariaDB数据库,但是您也可以使用MySQL/PostgreSQL/Sqlite/MSSQL等数据库。

短网址程序使用Swoole作为服务器。可以选择前端用Nginx/Apache/HAProxy做反代,也可以直接用Swoole处理HTTP请求,我将在后面分别介绍如何操作。

另外,由于短网址程序需要大量的数据库读写,为了性能考虑,建议您使用NVMe硬盘。本文的搭建环境需要2 GB内存。

Shlink.io统计分析时会需要用到Maxmind IP数据库,您需要在这里注册一个账号,然后申请一个免费的GeoLite2 IP数据库License Key.  请记下这个Licence Key, 后面的安装过程会用到。

请将您的短域名设置A记录,解析到您的服务器的IP地址上。解析生效后,我们就可以开始搭建了。本文中,将用测试域名test.mywi.fi作为示例,搭建短网址程序。

 

3, 安装数据库

这里介绍安装MariaDB数据库。其他数据库的安装类似。在SSH中执行:

1
apt-get install mariadb-server

然后设置root密码:

1
mysql_secure_installation

设置完毕后,登录MariaDB新建数据库,用户名以及密码。

1
2
3
4
mysql -u root -p
        CREATE DATABASE shlinkdb;
        GRANT ALL ON shlinkdb.* TO 'shlinkuser' IDENTIFIED BY 'fj09SUH8e40sUf38hyG';
        quit;

 

4, 安装PHP与Swoole

前面提到过,Shlink.io只支持PHP 7.4.  我们用包管理器安装PHP, 并安装需要的组件。

1
apt-get install php7.4 php7.4-fpm php7.4-mysql php7.4-json php7.4-gd php7.4-common php7.4-curl php7.4-intl php7.4-xml

Swoole可以通过pecl来安装。PHP默认不带pecl, 因此我们先安装Pecl.

1
2
wget http://pear.php.net/go-pear.phar
php go-pear.phar

然后,使用pecl编译安装Swoole.  需要注意的是,默认安装的PHP 7.4不带phpize, 我们需要额外安装php7.4-dev来获取phpize.  另外,如果您的系统上没有安装编译器,您还需要gcc/g++来编译安装包。安装phpize与gcc/g++:

1
apt-get install php7.4-dev build-essential

编译安装Swoole:

1
pecl install swoole

安装完毕后,我们将swoole模块写入php.ini让其生效。

1
echo "extension=swoole.so" >> /etc/php/7.4/cli/php.ini

 

5, 安装网站程序

配置好数据库与PHP-Swoole之后,我们就可以开始安装短网址站程序了。

1
2
3
4
5
6
7
8
9
10
mkdir -p /srv/www/shlink
cd /srv/www/shlink
wget https://github.com/shlinkio/shlink/releases/download/v2.2.1/shlink_2.2.1_dist.zip
unzip *
rm *.zip
mv * public_html
cd *
chmod -R +w data
cd bin
./install

这样就开始了自动安装程序。安装过程中会需要设置多个选项。比较重要的有下面这些。

  1. 数据库配置,您需要填入之前新建的数据库名,用户及密码
  2. 是否启用SSL.  若您只使用自己的短域名,建议您开启SSL.  若您打算开放服务器,允许别人的任意域名解析到您的服务器添加短网址,那么建议您关闭SSL, 选择HTTP.
  3. Provide a GeoLite2 license key 这里填入我们之前申请的GeoLite2授权码
  4. REDIRECTS部分,需要填入根域名以及无效短域名的跳转地址。若不填,则默认跳到一个404页面
  5. Redis缓存,您可以在本地搭建Redis缓存服务,进一步提升性能

具体的安装过程可以在下面的轻视频中查看。


程序安装完毕之后,目前还不能访问。我们需要建一个Swoole的守护进程。编辑文件/etc/init.d/shlink_swoole, 添加下面的内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#!/bin/bash
### BEGIN INIT INFO
# Provides:          shlink_swoole
# Required-Start:    $local_fs $network $named $time $syslog
# Required-Stop:     $local_fs $network $named $time $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Description:       Shlink non-blocking server with swoole
### END INIT INFO

SCRIPT=/srv/www/shlink/public_html/vendor/bin/mezzio-swoole\ start
RUNAS=root

PIDFILE=/var/run/shlink_swoole.pid
LOGDIR=/var/log/shlink
LOGFILE=${LOGDIR}/shlink_swoole.log

start() {
  if [[ -f "$PIDFILE" ]] && kill -0 $(cat "$PIDFILE"); then
    echo 'Shlink with swoole already running' >&2
    return 1
  fi
  echo 'Starting shlink with swoole' >&2
  mkdir -p "$LOGDIR"
  touch "$LOGFILE"
  local CMD="$SCRIPT &> "$LOGFILE" & echo \$!"
  su -c "$CMD" $RUNAS > "$PIDFILE"
  echo 'Shlink started' >&2
}

stop() {
  if [[ ! -f "$PIDFILE" ]] || ! kill -0 $(cat "$PIDFILE"); then
    echo 'Shlink with swoole not running' >&2
    return 1
  fi
  echo 'Stopping shlink with swoole' >&2
  kill -15 $(cat "$PIDFILE") && rm -f "$PIDFILE"
  echo 'Shlink stopped' >&2
}

case "$1" in
  start)
    start
    ;;
  stop)
    stop
    ;;
  restart)
    stop
    start
    ;;
  *)
    echo "Usage: $0 {start|stop|restart}"
esac

保存退出后,开启Daemon

1
2
3
4
chmod +x /etc/init.d/shlink_swoole
update-rc.d shlink_swoole defaults
update-rc.d shlink_swoole enable
/etc/init.d/shlink_swoole start

此时,我们访问域名:8080, 比如我这里是test.mywi.fi:8080, 发生了跳转,说明程序已经安装完毕,可以生效了。

 

6, 处理前端HTTP请求

Swoole默认开启在8080端口。因此,为了让用户正常通过80或者443端口访问我们的短网址服务器,我们有两个选择。1, 设置一个前端Web服务器,用于反代后端的Swoole-PHP服务器;2, 直接让Swoole监听80端口,用Swoole处理前端HTTP请求。这两个方法各有利弊。使用Swoole直接作为服务器,更为轻量高效,且性能更好,能够充分利用Swoole的特性。使用传统服务器反代,则配置较为方便,尤其是SSL等。这里,我将分别介绍两种情况,您可以自行决定。

(1) 直接使用Swoole

直接使用Swoole比较简单,我们直接修改Swoole监听的端口即可。编辑文件/srv/www/shlink/public_html/vendor/mezzio/mezzio-swoole/src/HttpServerFactory.php, 找到下面这行(我这里是第34行):

1
public const DEFAULT_PORT = 8080;

改成

1
public const DEFAULT_PORT = 80;

然后重启Swoole服务:

1
/etc/init.d/shlink_swoole restart

这样,就设置好了Swoole监听80端口。此时,访问您的短域名,比如我这里的test.mywi.fi, 就可以实现跳转了。

(2) 使用传统服务器反代

我们这里介绍Nginx反代,您也可以使用Apache/HAProxy/LiteSpeed等程序来设置反代。首先,安装Nginx.  这里我们只需要实现一个简单的反代功能,不需要手动编译,直接使用默认安装即可。

1
apt-get install nginx

然后,配置虚拟主机文件,添加反代。编辑文件/etc/nginx/sites-enabled/default, 在location里面设置成下面的形式:

1
proxy_pass http://127.0.0.1:8080;

需要注意的是,如果我们仅设置成反代8080端口,那么后端Swoole不能确认前端访问的主域名是什么。因此,无论解析什么域名,最后都会按照主域名设置的短链接来跳转。同时,后端Swoole也无法确认前端访客的来源IP, 无法按照地理位置进行数据分析。如果需要实现这些功能,我们还需要通过Nginx将对应的头信息传递给后端Swoole.  同样在location里面添加:

1
2
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;

保存完毕之后,测试Nginx配置文件格式是否正确:

1
nginx -t

然后,重新载入Nginx配置文件。

1
service nginx reload

这样,我们就配置好了前端Nginx反代。如果您需要额外配置SSL, 则可以使用Let’s Encrypt一键配置,或者手动添加证书。

 

7, 使用客户端添加短网址

Shlink短网址程序搭建好之后,我们就可以添加短网址了。我们有三种方式添加短网址:1,使用命令行;2,使用官网或者自建客户端;3,使用API.  命令行方式较为麻烦,这里不做过多介绍了。这一节我们先介绍使用客户端添加短网址。

使用客户端添加,本质上也是使用API, 只不过程序已经帮你写好了。您可以使用我编译好的客户端https://qing.su/url (数据全部在您的服务器上,不经过我的服务器),或者按照下面的教程,手动编译客户端。

客户端是用JS写的,我们先下载源码:

1
2
3
wget https://github.com/shlinkio/shlink-web-client/archive/v2.5.1.zip
unzip v2.5.1.zip
cd shlink-web-client-2.5.1

然后,我们需要配置一下编译选项。编辑文件package.json, 找到下面这行:

1
"homepage": ""

将其改成您客户端安装的相对路径。比如,我把客户端安装在https://qing.su/url, 那么我这里就需要改成:

1
"homepage": "/url"

如果您的服务器还没有安装node, 使用下面的命令安装。

1
2
curl -sL https://deb.nodesource.com/setup_14.x | bash -
apt-get install -y nodejs

然后,即可开始编译安装:

1
2
npm install
npm run build

编译完成之后,将build文件夹放到您的网站目录下,改成对应的目录名即可访问。我们访问安装好的客户端,如下图

首次使用,需要添加后端地址。点击Add a server, 进入下面的界面。

这里可以看到,客户端需要我们输入一个API.  API可以在后台生成,我们返回SSH, 进入程序目录并生成API授权码:

1
2
cd /srv/www/shlink/public_html/bin
./cli api-key:generate

回到客户端,输入刚才的API授权码以及服务器地址,即可连接上服务器。

需要注意的是,如果您的服务器没有开启HTTPS, 那么在浏览器里面加载的时候会出现HTTPS网站加载HTTP内容的情况,可能会被浏览器自动禁止,需要手动设置允许加载HTTP内容。

点击左侧Create Short URL, 即可开始添加短链接。

 

8, 使用API添加短链接

使用上一节的客户端,我们可以实现短链接的添加,管理和分析。但是,我们不能让所有访客都有这些权限。访客应该只能添加短链接,而只有 管理员才可以管理链接和分析数据。因此,如果您的短网址网站需要开放给访客使用,您就需要使用API来编写接口程序。

Shlink的API文档在这里https://api-spec.shlink.io/. 我们下面给出一个简单的PHP示例,能够获取前端表单用户提交的长链接、域名等,生成短链接。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
function callAPI($method, $url, $data){
   $curl = curl_init();
   switch ($method){
      case "POST":
         curl_setopt($curl, CURLOPT_POST, 1);
         if ($data)
            curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
         break;
      case "PUT":
         curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "PUT");
         if ($data)
            curl_setopt($curl, CURLOPT_POSTFIELDS, $data);                             
         break;
      default:
         if ($data)
            $url = sprintf("%s?%s", $url, http_build_query($data));
   }
   curl_setopt($curl, CURLOPT_URL, $url);
   curl_setopt($curl, CURLOPT_HTTPHEADER, array(
      "accept: application/json",
      'X-Api-Key: xxxxxx-qing.su-your-api-key',
      'Content-Type: application/json',
   ));
   curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
   curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
   $result = curl_exec($curl);
   if(!$result){die("Connection Failure");}
   curl_close($curl);
   return $result;
}
$long_url=trim($_POST['long_url']);
$custom_domain=trim($_POST['custom_domain']);
$custom_slug = null;
$max_visits = null;
if (isset($_POST['custom_slug'])) {
    $custom_slug = trim($_POST['custom_slug']);
}
$surl_request_array = array(
    "longUrl" => $long_url,
    "tags" => $custom_domain,
    "validSince" => null,
    "validUntil" => null,
    "customSlug" => $custom_slug,
    "maxVisits" => $max_visits,
    "findIfExists" => true,
    "domain" => $custom_domain,
    "shortCodeLength" => 5,
);
$make_API_call = callAPI('POST', 'http://public-url-shortner-03.mywi.fi/rest/v2/short-urls', json_encode($surl_request_array));
$response = json_decode($make_API_call, true);
echo "<p>Long URL: ";
echo $response["longUrl"];
echo "</p><p>Short URL: ";
echo $response["shortUrl"];

至此,我们使用Swoole与Shlink.io在Ubuntu 20.04上搭建好了一个完整的高性能的短网址程序,并编写了前端短链接生成接口。如果您有任何疑问,欢迎在这里留言,我将尽力解答。本文作者为香菇肥牛,原文链接为https://qing.su/article/160.html, 转载请注明原文链接。谢谢!

2 thoughts on “使用Swoole与Shlink.io在Ubuntu 20.04系统上搭建高性能短网址程序”

Leave a Comment