CentOS 7源码安装Redis 6.0及自启动

Redis 是完全开源的,遵守 BSD 协议,是一个高性能的 key-value 数据库。当下非常流行,使用非常广泛,这篇文章记录下CentOS 7源码安装Redis服务的方法。

安装Redis

先执行下面的命令,安装一大堆依赖:

#安装依赖
yum -y install cpp binutils glibc glibc-kernheaders glibc-common glibc-devel gcc make
#升级gcc
yum -y install centos-release-scl
yum -y install devtoolset-9-gcc devtoolset-9-gcc-c++ devtoolset-9-binutils
scl enable devtoolset-9 bash

写这篇文章的时候,Redis最新稳定版为6.0,随着时间推移,版本会发生变化,请前往Redis官方:https://redis.io/download下载最新版本。

#下载Redis
wget https://download.redis.io/releases/redis-6.0.9.tar.gz
#解压Redis
tar xzf redis-6.0.9.tar.gz
#进入Redis目录
cd redis-6.0.9
#编译
make

编译成功后,Redis服务二进制文件位于src/redis-server,直接输入这个路径即可运行Redis服务,不过运行后是在前台运行,一旦结束或窗口关闭,Redis服务也随之停止。

运行Redis

为了方便后期管理与维护,可以将Redis src放到特定目录下,比如mv src/ /usr/local/redis

同时可以将redis-6.0.9目录下的redis.conf也复制一份:

cp redis.conf /etc

默认情况下,Redis是前台运行,如果需要后台运行,需要修改redis.conf配置文件,将

daemonize no

修改为:

daemonize yes

然后输入命令:/usr/local/redis/redis-server /etc/redis.conf重新启动Redis服务,这个时候就是保持后台运行了,通过ps命令可看到进程:

[root@hecs-centos-7 ~]# ps -ef|grep 'redis'
root     10217     1  0 22:00 ?        00:00:00 /usr/local/redis/redis-server 127.0.0.1:6379

设置环境变量

每次都输入Redis绝对路径来运行,难免还是有些不方便,我们可以将Redis路径加入到Linux环境变量,在/etc/profile这个文件底部追加:

export PATH=$PATH:/usr/local/redis

再输入命令source /etc/profile使其生效,这样我们就可以直接执行redis命令,而不用输入完整路径了。比如:

[root@hecs-centos-7 ~]# redis-server -v
Redis server v=6.0.9 sha=00000000:0 malloc=jemalloc-5.1.0 bits=64 build=ef93b08070de4db5

Redis客户端

通过上面编译后,Redis自带了一个命令行客户端redis-cli,输入下面的命令可检测Redis是否正常运行。

[root@hecs-centos-7 ~]# /usr/local/redis/redis-cli 
127.0.0.1:6379> ping
PONG

注册为Systemd服务

如果需要将Redis设置为开启启动,我们可以将redis注册为Systemd服务,方便日后管理。首先创建一个服务文件:vi /etc/systemd/system/redis.service,内容如下:

[Unit]
Description=Redis Server
After=network.target

[Service]
Type=forking
ExecStart=/usr/local/redis/redis-server /etc/redis.conf

[Install]
WantedBy=multi-user.target

然后输入systemctl daemon-reload重新加载服务,接下来就可以使用systemctl命令来管理了:

#启动redis
systemctl start redis
#停止redis
systemctl stop redis
#开机启动
systemctl enable redis

redis批量删除key 远程批量删除key

一、遇到的问题

  在开发的过程中,经常会遇到要批量删除某种规则的key,如缓存的课程数据“course-课程uid”,其中课程uid是变量,我们需要删除”course-*”这一类的数据,但是这里就坑了,redis有提供批量查询一类key的命令keys,但是没有提供批量删除某种类型key的命令。

二、解决方案

  先看看我们怎么解决。

1、先进入redis的客户端

cd redis所在目录/src
./redis-cli

2、初始化数据,模拟数据

复制代码
127.0.0.1:6379> set course-1 1
OK
127.0.0.1:6379> set course-2 2
OK
127.0.0.1:6379> set course-3 3
OK
复制代码

3、通过keys命令可以看到,现在有上面的三个key

127.0.0.1:6379> keys  course-*
1) "course-3"
2) "course-2"
3) "course-1"

4、退出redis的客户端

127.0.0.1:6379> exit

5.1、本地批量删除key

./redis-cli keys "course-*" | xargs ./redis-cli del

此处刚刚 course-*  相关的3个key已经被删除了

原理解析:

  先通过redis客户端执行了keys命令,模糊搜索出所有的key,通过xargs命令,将前面查询出来的key作为后面redis的del命令的输入

最终执行的结果可以理解成

 1、模糊查询

keys "course-*" 

  查询出上面的course-1 course-2 course-3 这三个key

2、执行删除key

  del的三个key来自前面的keys查询

del course-1 course-2  course-3    

5.2、远程批量删除key

  经常我们开发的时候,redis都是公用的,可能redis不在本地我们可以通过redis客户端远程进行删除

./redis-cli -h redis所在服务器ip -p 端口 keys "course-*" |xargs ./redis-cli -h redis所在服务器ip -p 端口 del

三、补充知识

1、远程某台机子的redis

  以下实例演示了如何连接到主机为 127.0.0.1,端口为 6379 ,密码为 mypass 的 redis 服务上。

redis-cli -h 127.0.0.1 -p 6379 -a "mypass"

2、xargs命令

xargs命令是给其他命令传递参数的一个过滤器,也是组合多个命令的一个工具。 详情课件 http://man.linuxde.net/xargs

转自:https://www.cnblogs.com/0201zcr/p/9647787.html

curl: (35) SSL connect error

linux 命令行curl 访问https出现如下error:

rpm –import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org

curl: (35) SSL connect error
error: https://www.elrepo.org/RPM-GPG-KEY-elrepo.org: import read failed(2).

* Closing connection #0

* SSL connect error

curl: (35) SSL connect error

解决方法:

yum update -y nss curl libcurl ca-certificates

yum update -y nss curl libcurl ca-certificates

Loaded plugins: fastestmirror
Setting up Update Process
Loading mirror speeds from cached hostfile
Resolving Dependencies
There are unfinished transactions remaining. You might consider running yum-complete-transaction first to finish them.
^C–> Running transaction check
—> Package ca-certificates.noarch 0:2017.2.14-65.0.1.el6_9 will be updated
[root@10-13-72-98 vhost]# yum update -y nss curl libcurl ca-certificates

Loaded plugins: fastestmirror
Setting up Update Process
Loading mirror speeds from cached hostfile
Resolving Dependencies
There are unfinished transactions remaining. You might consider running yum-complete-transaction first to finish them.
–> Running transaction check
—> Package ca-certificates.noarch 0:2017.2.14-65.0.1.el6_9 will be updated
—> Package ca-certificates.noarch 0:2020.2.41-65.1.el6_10 will be an update
—> Package curl.x86_64 0:7.19.7-53.el6_9 will be updated
—> Package curl.x86_64 0:7.19.7-54.el6_10 will be an update
—> Package libcurl.x86_64 0:7.19.7-53.el6_9 will be updated
–> Processing Dependency: libcurl = 7.19.7-53.el6_9 for package: libcurl-devel-7.19.7-53.el6_9.x86_64
—> Package libcurl.x86_64 0:7.19.7-54.el6_10 will be an update
–> Running transaction check
—> Package libcurl-devel.x86_64 0:7.19.7-53.el6_9 will be updated
—> Package libcurl-devel.x86_64 0:7.19.7-54.el6_10 will be an update
–> Finished Dependency Resolution

Dependencies Resolved

======================================================================================================================================================

Package Arch Version Repository Size

Updating:
ca-certificates noarch 2020.2.41-65.1.el6_10 updates 908 k
curl x86_64 7.19.7-54.el6_10 updates 198 k
libcurl x86_64 7.19.7-54.el6_10 updates 170 k
Updating for dependencies:
libcurl-devel x86_64 7.19.7-54.el6_10 updates 247 k

Transaction Summary

Upgrade 4 Package(s)

Total download size: 1.5 M
Downloading Packages:
(1/4): ca-certificates-2020.2.41-65.1.el6_10.noarch.rpm | 908 kB 00:00
(2/4): curl-7.19.7-54.el6_10.x86_64.rpm | 198 kB 00:00
(3/4): libcurl-7.19.7-54.el6_10.x86_64.rpm | 170 kB 00:00

(4/4): libcurl-devel-7.19.7-54.el6_10.x86_64.rpm | 247 kB 00:00

Total 18 MB/s | 1.5 MB 00:00
Running rpm_check_debug
Running Transaction Test
Transaction Test Succeeded
Running Transaction
Updating : libcurl-7.19.7-54.el6_10.x86_64 1/8
Updating : curl-7.19.7-54.el6_10.x86_64 2/8
Updating : libcurl-devel-7.19.7-54.el6_10.x86_64 3/8
Updating : ca-certificates-2020.2.41-65.1.el6_10.noarch 4/8
Cleanup : libcurl-devel-7.19.7-53.el6_9.x86_64 5/8
Cleanup : curl-7.19.7-53.el6_9.x86_64 6/8
Cleanup : ca-certificates-2017.2.14-65.0.1.el6_9.noarch 7/8
Cleanup : libcurl-7.19.7-53.el6_9.x86_64 8/8
Verifying : curl-7.19.7-54.el6_10.x86_64 1/8
Verifying : libcurl-devel-7.19.7-54.el6_10.x86_64 2/8
Verifying : libcurl-7.19.7-54.el6_10.x86_64 3/8
Verifying : ca-certificates-2020.2.41-65.1.el6_10.noarch 4/8
Verifying : curl-7.19.7-53.el6_9.x86_64 5/8
Verifying : libcurl-devel-7.19.7-53.el6_9.x86_64 6/8
Verifying : libcurl-7.19.7-53.el6_9.x86_64 7/8
Verifying : ca-certificates-2017.2.14-65.0.1.el6_9.noarch 8/8

Updated:
ca-certificates.noarch 0:2020.2.41-65.1.el6_10 curl.x86_64 0:7.19.7-54.el6_10 libcurl.x86_64 0:7.19.7-54.el6_10

Dependency Updated:
libcurl-devel.x86_64 0:7.19.7-54.el6_10

Complete!

广电DNS地址

广电网DNS地址陕西210.87.141.250  陕西省西安市//汉中市广电网180.1677%
广电网DNS地址天津211.148.160.209  天津市/广电网10.0093%
广电网DNS地址四川60.255.80.19  四川省/广电网10.0093%
广电网DNS地址福建203.190.96.2  福建省福州市/广电网10.0093%
广电网DNS地址江苏211.167.132.29  江苏省苏州市/广电网10.0093%
广电网DNS地址四川60.255.80.18  四川省/广电网10.0093%
广电网DNS地址山东210.77.192.88  山东省济南市/广电网10.0093%

Centos6利用rpm升级OpenSSH到openssh-8.1p1版本

CentOS6的rpm升级包进行OpenSSH到openssh-8.1p1版本分享。

下载:

wget https://cikeblog.com/s/openssh8.1-6.tar.gz
tar -zxvf openssh8.1-6.tar.gz

安装方法一:

rpm -Uvh *.rpm

安装方法二(此方法会自动处理依懒关系):

yum install ./*.rpm

安装后会如下提示:

[root@test ~]# rpm -Uvh *.rpm
Preparing...                          ################################# [100%]
Updating / installing...
   1:openssh-8.1p1-1.el7              ################################# [ 14%]
   2:openssh-clients-8.1p1-1.el7      ################################# [ 29%]
   3:openssh-server-8.1p1-1.el7       ################################# [ 43%]
   4:openssh-debuginfo-8.1p1-1.el7    ################################# [ 57%]
[root@test ~]# ssh -V
OpenSSH_8.1p1, OpenSSL 1.0.1e-fips 11 Feb 2013
[root@768 ~]#

至此,升级完成,因为OPENSSH升级后,/etc/ssh/sshd_config会还原至默认状态,我们需要进行相应配置:

cd /etc/ssh/
chmod 400 ssh_host_ecdsa_key ssh_host_ed25519_key ssh_host_rsa_key
echo "PermitRootLogin yes" >> /etc/ssh/sshd_config
echo "PasswordAuthentication yes"  >> /etc/ssh/sshd_config
systemctl restart sshd

并且,/etc/pam.d/sshd也文件会被覆盖,我们进行还原:
先清空:

>/etc/pam.d/sshd;

再还原:

echo '#%PAM-1.0
auth       required     pam_sepermit.so
auth       include      password-auth
account    required     pam_nologin.so
account    include      password-auth
password   include      password-auth
# pam_selinux.so close should be the first session rule
session    required     pam_selinux.so close
session    required     pam_loginuid.so
# pam_selinux.so open should only be followed by sessions to be executed in the user context
session    required     pam_selinux.so open env_params
session    optional     pam_keyinit.so force revoke
session    include      password-auth'>/etc/pam.d/sshd

至此,升级完成,先别关闭终端,直接新开一个终端,连接到服务器测试。

注意:如果新开终端连接的时,root密码报错,并且已经根据上面后续操作,那可能就是SElinux的问题,我们进行临时禁用:

setenforce 0

即可正常登录,然后修改/etc/selinux/config 文件:

sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config

进行永久禁用SElinux即可。

php 7.2 安装 mcrypt 扩展

升级 php 7.2 后,使用微信提供的加解密代码时,提示 call to undefined function mcrypt_module_open() ;大脑疯狂运转1秒钟后,得出结论:php 7.2的扩展有变动;查阅相关资料知晓,mcrypt 扩展从 php 7.1.0 开始废弃;自 php 7.2.0 起,会移到 pecl。还好,安装过程不复杂。

环境:centos 7

yum 安装依赖包:

yum install libmcrypt libmcrypt-devel mcrypt mhash

在 php 官网下载 mcrypt 包,php 扩展官网

  # wget  http://pecl.php.net/get/mcrypt-1.0.3.tgz

  # tar xf mcrypt-1.0.3.tgz

  # cd mcrypt-1.0.3

编译安装 mcrypt

  # /usr/local/php/bin/phpize

  # ./configure –with-php-config=/usr/local/php/bin/php-config  && make && make install

在php.ini加上扩展即可

extension=mcrypt.so

重启 php-fpm

/etc/init.d/php-fpm restart

Nginx location 匹配顺序整理

Nginx环境

a. 查看当前系统cat /etc/redhat-release

[root@nginx /]# cat /etc/redhat-release

CentOS release 6.7 (Final)

[root@nginx /]#

b. 查看系统内核uname –r

[root@nginx /]# uname -r

2.6.32-573.el6.x86_64

[root@nginx /]#

c. 安装的Nginx版本,/appliation/nginx/sbin/nginx -V

[root@nginx sbin]# ./nginx -V

nginx version: nginx/1.6.2

built by gcc 4.4.7 20120313 (Red Hat 4.4.7-16) (GCC)

TLS SNI support enabled

configure arguments: –user=nginx –group=nginx –prefix=/application/nginx1.6.2 –with-http_stub_status_module –with-http_ssl_module

[root@nginx sbin]#

location模块

Nginx location

location 指令的作用是根据用户请求的URI来执行不同的应用,URI就是根据用户请求到的网址URL进行匹配,匹配成功了进行相关的操作。

location语法

下面是官网的语法结构:

Syntax:    location [ = | ~ | ~* | ^~ ] uri { … }

location @name { … }

Default:   —

Context:   server, location

官网解释翻译和理解

下面会结合官网原文进行解释,以下英文部分均从官网摘抄:

http://nginx.org/en/docs/http/ngx_http_core_module.html#location

(翻译的不好勿喷)

Sets configuration depending on a request URI.

根据请求的URI进行配置

URI 变量是待匹配的请求字符串,

A location can either be defined by a prefix string, or by a regular expression.

Regular expressions are specified with the preceding “~*” modifier (for case-insensitive matching), or the “~” modifier (for case-sensitive matching)

一个location可以用prefix string(前缀字符串)定义,也可以通过regular expression(正则表达式来定义)

通俗的说也就是:我们可以通过使用不同的前缀,表达不同的含义,对于不同的前缀可以分为两大类:普通location和正则location

符号:”~”表示uri包含正则,并且区分大小写

符号:“~*”表示uri包含正则,但不区分大小写

注意:如果你的uri用正则,则你的正则前面必须添加~或者~*,之前我在这里存在误区,以为可以不加~或者~*

To find location matching a given request, nginx first checks locations defined using the prefix strings (prefix locations). Among them, the location with the longest matching prefix is selected and remembered. Then regular expressions are checked, in the order of their appearance in the configuration file. The search of regular expressions terminates on the first match, and the corresponding configuration is used. If no match with a regular expression is found then the configuration of the prefix location remembered earlier is used.

Nginx服务器会首先会检查多个location中是否有普通的uri匹配,如果有多个匹配,会先记住匹配度最高的那个。然后再检查正则匹配,这里切记正则匹配是有顺序的,从上到下依次匹配,一旦匹配成功,则结束检查,并就会使用这个location块处理此请求。如果正则匹配全部失败,就会使用刚才记录普通uri匹配度最高的那个location块处理此请求。

If the longest matching prefix location has the “^~” modifier then regular expressions are not checked.

当普通匹配的最长前缀匹配有符号“^~”的时候,就不会在匹配正则

直接使用当前匹配的这个location块处理此请求

Also, using the “=” modifier it is possible to define an exact match of URI and location. If an exact match is found, the search terminates. For example, if a “/” request happens frequently, defining “location = /” will speed up the processing of these requests, as search terminates right after the first comparison. Such a location cannot obviously contain nested locations.

使用符号“=”修饰符可以定义一个精确匹配的URI和位置,如果找到了一个精确的匹配,则搜索终止,例如,如果一个”/”请求频繁发生,定义“location =/”将加快这些请求的处理,一旦精确匹配只有就结束,这样的location显然不能包含嵌套location

这里我们说一下location / {} 和location =/ {}的区别:

“location / {}”是普通的最大前缀匹配,任何的uri肯定是以“/”开头,所以location / {} 可以说是默认匹配,当其他都不匹配了,则匹配默认匹配

根据上述官网内容进行总结

a. ”=”用于普通uri前,要求精确匹配,如果匹配成功,则停止搜索并用当前location处理此请求

b. ”~” 表示uri包含正则,并且区分大小写

c. “~*”表示uri包含正则,但不区分大小写

d. ”^~”表示在普通uri前要求Nginx服务器找到普通uri匹配度最高的那个location后,立即处理此请求,并不再进行正则匹配

e. ”^~”和“=”都可以阻止继续匹配正则location两者的区别:“^~”依然遵守最大前缀原则,然后“=”是需要严格匹配

关于location网上的一些误解

location 的匹配顺序是“先匹配正则,再匹配普通”

这是一个错误的结论,从上面官网的文章中我们可以知道:

先匹配普通uri,然后记住匹配度最高的那个(官网原话:To find location matching a given request, nginx first checks locations defined using the prefix strings (prefix locations). Among them, the location with the longest matching prefix is selected and remembered.)然后匹配正则,如果正则匹配则结束查找,如果正则不匹配,则匹配之前普通匹配中匹配度最高的那个将执行该请求(官网原话:Then regular expressions are checked, in the order of their appearance in the configuration file. The search of regular expressions terminates on the first match, and the corresponding configuration is used. If no match with a regular expression is found then the configuration of the prefix location remembered earlier is used.)

所以:location 的匹配顺序是“先匹配正则,再匹配普通” 这句话肯定是错误的,况且这里并没有包含”^~”和“=”

location 的执行逻辑跟 location 的编辑顺序无关。

这也是一种错误的理解,我们根据上述内容可以知道:

如果是普通uri 匹配,这个时候是没有顺序的,但是正则匹配则是有顺序的,是从上到下依次匹配,一旦有匹配成功,则停止后面的匹配。

那么顺序到底是怎么匹配呢?

我画了一个location匹配的逻辑图便于理解匹配的顺序规则

通过实验来验证出结果

对www.conf配置如下:

[root@nginx extra]# cat www.conf

    server {

        listen       80;

        server_name  www.zhaofan.com;

        access_log      logs/access_www.log;

        root    html/www;

        location / {

            return 401;

        }

        location = / {

            return 402;

        }

        location  /documents/ {

            return 403;

        }

        location  ^~ /images/ {

            return 404;

        }

        location ~* \.(gif|jpg|jpeg)$ {

            return 500;

        }

    }

[root@nginx extra]#

注意:

        location ~* \.(gif|jpg|jpeg)$ {

            return 500;

这个部分$前面不能有空格,否则会提示如下错误:

[root@nginx extra]# ../../sbin/nginx -s reload

nginx: [emerg] invalid location modifier “~*\.(gif|jpg|jpeg)” in /application/nginx1.6.2/conf/extra/www.conf:19

如果$后面没有空格,则会提示如下错误:

[root@nginx extra]# ../../sbin/nginx -s reload

nginx: [emerg] directive “location” has no opening “{” in /application/nginx1.6.2/conf/extra/www.conf:23

这些都是细节问题,一定要注意

实验一:登录nginx网站,我这里的直接打开:http://192.168.8.105/

可以看出这里是精确匹配

        location = / {

            return 402;

        }

实验二:打开http://192.168.8.105/aaa/

这里可以看出因为都不匹配,所以最后匹配了location / {}

        location / {

            return 401;

        }

实验三:打开http://192.168.8.105/1.gif

这里可以看出是匹配了正则

        location ~* \.(gif|jpg|jpeg)$ {

            return 500;

        }

实验四:打开http://192.168.8.105/aaa/1.gif

这里依然是匹配正则

        location ~* \.(gif|jpg|jpeg)$ {

            return 500;

        }

实验五:打开http://192.168.8.105/images/1.gif

        location / {

            return 401;

        }

        location = / {

            return 402;

        }

        location  /document/ {

            return 403;

        }

        location  ^~ /images/ {

            return 404;

        }

        location ~* \.(gif|jpg|jpeg)$ {

            return 500;

        }

这里通过配置把实验三和实验四的对比就可以看出来因为普通匹配里有“^~”,并且匹配到了images,所以这个就是不进行正则匹配

        location  ^~ /images/ {

            return 404;

        }

实验六:“^~”遵守最大前缀原则

配置如下:

        location / {

            return 401;

        }

        location = / {

            return 402;

        }

        location  = /document/ {

            return 403;

        }

        location  ^~ /images/ {

            return 404;

        }

        location   /images/1/ {

            return 501;

        }

        location ~* \.(gif|jpg|jpeg)$ {

            return 500;

        }

还是关注标红的地方,这个时候我们登陆:http://192.168.1.19/images/

结果如下:

从这里可以看出匹配了:

        location  ^~ /images/ {

            return 404;

        }

但是如果我们登陆:http://192.168.1.19/images/1/

结果如下;

这里匹配了:

        location   /images/1/ {

            return 501;

        }

从这里我们可以看出“^~”遵守最大匹配原则。

实验七:当最长匹配和精确匹配相同时

配置如下:

        location / {

            return 401;

        }

        location = / {

            return 402;

        }

        location  = /document/ {

            return 403;

        }

        location  ^~ /images/ {

            return 404;

        }

        location   /images/1/ {

            return 501;

        }

        location  =  /images/1/ {

            return 502;

        }

        location ~* \.(gif|jpg|jpeg)$ {

            return 500;

        }

登陆:http://192.168.1.19/images/1/

结果如下:

但是如果这个时候登陆:http://192.168.1.19/images/1/aaa/

结果如下:

从这里我们可以看出当精确匹配和最长匹配相同时,匹配的是精确匹配。

不在过多的做实验,根据上面的逻辑图应该可以解决碰到的问题了所有的努力都值得期许,每一份梦想都应该灌溉!

原文:https://www.cnblogs.com/zhaof/p/5945576.html

双显卡单屏幕电脑OBS获取chrome浏览器源为黑屏

在浏览器设置中关闭硬件加速,可以解决此问题。

但是在浏览网页,游戏需要渲染过多动画的时候会巨卡无比。

因为OBS只能捕获相同渲染方式的窗口

所以我们需要让Chrome浏览器默认使用OpenGL进行GPU加速

  1. 地址栏输入chrome://flags/#use-angle
  2. 选择OpenGL
  3. 重启浏览器 就大功告成了!

部署AppRTC服务

AppRTC是WebRTC视频通话的服务程序,一般可以将其作为参考实现,搭建AppRTC服务受限于很多条件,并不是太容易。在参考了官方操作和大量的博客之后,根据自己操作实践排除了很多网络博客上的错误方法,终于部署成功了一套环境。测试环境为阿里云的CentOS 7服务器,带公网IP和域名。

部署前的必要条件

部署前,首先要明确的是必要的依赖环境,必须满足以下需求:

  • 公网服务器,如果非公网就只能在局域网玩玩了,此处暂不讨论局域网
  • SSL证书,因为WebRTC必须在HTTPS环境下使用,因此通信WebSocket也必须支持

如果没有证书,但是有域名的话,可以去申请免费的证书,具体百度 Let’s Encrypt。本博客使用了Caddy服务器,此服务器可自行自动申请其证书,其证书存放在

/var/lib/caddy/acme/acme-v02.api.letsencrypt.org/sites/

下,按站点域名存放,假设本次部署使用的 example.com 域名,对应 8.8.8.8,其证书存放在

/var/lib/caddy/acme/acme-v02.api.letsencrypt.org/sites/example.com/

下,包含公钥文件 example.com.cert 和私钥文件 example.com.key 文件。

上面的 example.com 和 8.8.8.8 是域名和对应的IP,此处为举例,抹去了我的真实的地址。

安装编译环境

除了必要条件外,编译安装相关源码也需要一些编译环境,已知目前最终部署的程序为

  • apprtc GAE的Python和NodeJS开发的房间服务器
  • collider golang开发的信令服务器
  • coturn c语言开发的stun/turn服务器

系统基础环境安装

因为上面的依赖以及后续使用发现,系统需要安装的依赖环境如下(已经安装了跳过)

yum install python #要求2.7版本
curl -sL https://rpm.nodesource.com/setup_10.x | bash – #安装比较高的10版本
npm -g install grunt-cli #grunt工具
yum install gcc-c++ make #C/C++编译器等
yum install golang #golang编译器
yum install java-1.8.0-openjdk #安装JDK,我选择了1.8版本
yum install libevent-devel #编译coturn需要
yum install git #可以下载Github源码
yum install sqlite-devel #编译coturn需要

GAE环境安装

准确的讲需要安装的是 Google app engine SDK for Python,但是因为众所周知的原因,我们并不能直接访问,但是我从其他地方获知了一个比较老的下载地址,可以离线安装,而且是可以下载的

wget https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/google-cloud-sdk-188.0.1-linux-x86_64.tar.gz

虽然这个是Google Cloud SDK,但是我发现确实是可以用,并且可以更新,估计是现在进行了整合吧

tar xzvf google-cloud-sdk-188.0.1-linux-x86_64.tar.gz
./google-cloud-sdk/bin/gcloud components update

这其中因为 AppRTC 是用GAE的Python开发的,依赖Python 2.7环境。据说现在支持了3.7版本了,因为不能上官网,不确定。

编译构建版本

编译coturn

因为coturn是必须依赖的组件,我们优先处理这个,这个软件并不在仓库中,其依赖的libevent的版本与仓库中的一致,并不需要单独编译,因此只需要下载编译这个软件即可

因为这个软件中带了RPM的构建脚本,因此我这里打算进行RPM包的构建,首先安装RPM构建工具

yum install rpm-build

开始下载源码进行编译构建安装包

wget https://github.com/coturn/coturn/archive/4.5.1.1.tar.gz
mkdir -p ~/rpmbuild/SOURCES
mv 4.5.1.1.tar.gz -p ~/rpmbuild/SOURCES/turnserver-4.5.1.1.tar.gz
rpmbuild -ta ~/rpmbuild/SOURCES/turnserver-4.5.1.1.tar.gz

等构建成功后,会在 ~/rpmbuild/RPMS/x86_64 目录下发现好几个安装包,只需要安装 turnserver 即可

rpm -ivh ~/rpmbuild/RPMS/x86_64/turnserver-4.5.1.1-0.el7.x86_64.rpm

如果怕编译麻烦的,可在本站下载编译好的包进行安装

rpm -ivh https://cdn.xilixili.net/linux/turnserver-4.5.1.1-0.el7.x86_64.rpm

至于配置,我们后面再讲。

编译collider

Collider是Go开发的服务,依赖websocket,依然不能访问其地址。因此只能下载镜像安装,此处以将Go的环境设置的当前用户目录下的go目录为例说明。另外Collider的代码在AppRTC之中,因此此处就直接下载AppRTC的源码了,后续不需要下载了。

export GOPATH=$HOME/go
mkdir -p ~/go/src
git clone https://github.com/apprtc/apprtc
ln -s `pwd`/apprtc/src/collider/collider $GOPATH/src
ln -s `pwd`/apprtc/src/collider/collidermain $GOPATH/src
ln -s `pwd`/apprtc/src/collider/collidertest $GOPATH/src
mkdir -p $GOPATH/src/golang.org/x
cd $GOPATH/src/golang.org/x
git clone https://github.com/golang/net.git
go get collidermain
go install collidermain

至此,程序编译好并且安装到了 $GOPATH/bin 下面。

配置启动服务

注意,下面所有提供网络的服务,要注意防火墙配置,特别是UDP端口,测试平台关闭了防火墙。

配置启动coturn

首先需要生成签名证书

mkdir /cert
openssl req -x509 -newkey rsa:2048 -keyout /cert/turn_server_pkey.pem -out /cert/turn_server_cert.pem -days 99999 -nodes

然后再生成用户,以 apprtc 为例

turnadmin -k -u apprtc -p apprtc

执行之后会生成一个key,记住这个key,马上要用到。编辑 /etc/turnserver/turnserver.conf 文件,这个文件大部分的功能都默认是注释的,因此基本找到出处进行修改,大概如下

listening-ip=8.8.8.8
listening-port=3478
relay-ip=8.8.8.8
tls-listening-port=5349
external-ip=8.8.8.8
Verbose
fingerprint
lt-cred-mech
use-auth-secret
static-auth-secret=apprtc
user=apprtc:0x949534a397bcf2e88470c86ad3749d9c(替换成上面的key)
user=apprtc:apprtc
cert=/cert/turn_server_cert.pem
pkey=/cert/turn_server_pkey.pem

保存之后,启动服务

systemctl enable turnserver
systemctl start turnserver

注意,很多教程说要配置 TRUN REST API,即自己需要实现个REST API服务,让AppRTC进行查询获取,通过分析和测试,发现第一这个服务必须是POST请求的,具体格式参考标准,第二是并不需要这个API也能正常使用,因此请不要折腾REST API了。

启动Collider服务

暂时以测试为主,后续可为此程序编写添加个systemd服务。

此服务需要对外提供WSS服务,因此需要证书,将之前的域名证书拷贝过去即可

cd /var/lib/caddy/acme/acme-v02.api.letsencrypt.org/sites/example.com/
cp example.com.cert cert.pem
cp example.com.key key.pem
chmod 755 /cert/*

然后通过下面的命令启动服务

./collidermain -port=8089 -tls=true -room-server=”http://example.com:8080″

注意,我们设置的这个服务的端口是8089端口,AppRTC默认的HTTP端口是8080,HTTPS端口是8081,但是实际测试中发现AppRTC在使用HTTPS的时,会经常SSL异常,未查明原因。

配置启动AppRTC

配置AppRTC的配置文件 ~/apprtc/src/app_engine/constants.py 文件如下(仅列出修改项)

ICE_SERVER_OVERRIDE = [
{
“urls”: [
“turn:8.8.8.8:3478?transport=udp”,
“turn:8.8.8.8:3478?transport=tcp”
],
“username”: “apprtc”,
“credential”: “0x949534a397bcf2e88470c86ad3749d9c” #替换成上面的key
},
{
“urls”: [
“stun:8.8.8.8:3478”
]
}
]

ICE_SERVER_BASE_URL = ”
ICE_SERVER_URL_TEMPLATE = ”
ICE_SERVER_API_KEY = os.environ.get(‘ICE_SERVER_API_KEY’)

# Dictionary keys in the collider instance info constant.
WSS_INSTANCE_HOST_KEY = ‘example.com:8089’
WSS_INSTANCE_NAME_KEY = ‘vm_name’
WSS_INSTANCE_ZONE_KEY = ‘zone’
WSS_INSTANCES = [{
WSS_INSTANCE_HOST_KEY: ‘example.com:8089’,
WSS_INSTANCE_NAME_KEY: ‘wsserver-std’,
WSS_INSTANCE_ZONE_KEY: ‘us-central1-a’
}]

上面的配置已经可以保证使用了,且在命令行指定SSL证书后,就能提供服务了,但是由于之前提到了SSL异常问题,即使在切换到HTTP之后并使用nginx代理后,出现了URL不匹配的错误,因此还不能直接使用,为了解决上面的问题,我修改了代码,首先配置 ~/apprtc/src/app_engine/constants.py 修改

REDIRECT_URL = ‘https://example.com:9090’

这里假设nginx代理的地址是 example.com:9090 ,然后修改该目录下的 apprtc.py 文件,大概在300行左右,修改其中room_link的赋值为

room_link = constants.REDIRECT_URL + ‘/r/’ + room_id

然后编译代码并运行代码,命令如下

cd ~/apprtc
grunt build
cd ~
google-cloud-sdk/bin/dev_appserver.py –host example.com ~/apprtc/out/app_engine/ –dev_appserver_log_level debug

会看到输出显示

Starting module “default” running at: http://example.com:8080

也就是意味着服务提供的地址是 http://example.com:8080

安装配置nginx代理

如上,使用nginx代理https请求,端口为 9090,直接yum安装

yum install nginx

配置 /etc/nginx/nginx.conf 文件

#server {
# listen 80 default_server;
# listen [::]:80 default_server;
# server_name _;
# root /usr/share/nginx/html;

# # Load configuration files for the default server block.
# include /etc/nginx/default.d/*.conf;

# location / {
# }

# error_page 404 /404.html;
# location = /40x.html {
# }

# error_page 500 502 503 504 /50x.html;
# location = /50x.html {
# }
#}

server {
listen 9090 ssl default_server;
server_name example.com;
ssl_certificate “/cert/cert.pem”;
ssl_certificate_key “/cert/key.pem”;
location /{
proxy_pass http://example.com:8080;
proxy_set_header Host $host;
}
}

配置默认注释了原来默认配置的80端口的配置,添加了一个9090的代理服务,配置之后启动服务

systemctl enable nginx
systemctl start nginx

体验测试

通过 https://example.com:9090 访问AppRTC服务

再找另外一个用户同时打开浏览器,输入相同的号码并JOIN,即可实现视频通话。

另外在目录下的~/apprtc/src/web_app/html/params.html网页中自定义了一些配置参数,可以在URL中自定义WebRTC的参数,比如打开高清摄像头、关闭音频等等,具体参考这个页面即可。

采用默认配置测试后,个人使用感觉效果如下

  • 语音很清晰无噪音,两个用户使用手机外放离的很近的时候,可能是回声消除的原因会出噪音
  • 视频感觉效果一般般,带宽占用也不高,毕竟是P2P模式,但并不是特别清晰
  • 整体感觉和微信视频差不多,可能稍好一点
  • 并没有找到测试turn的环境,这个环境下的效果不清楚

手机微信也可以的哦。