centos安装powershell

2019年7月17日 没有评论

微软powershell功能很强大,也支持了很多linux命令,对于只停留在cmd的同学可以试试,除了命令行,还可以用来开发图形程序。

powershell并?#20063;?#32465;定在windows,微软开源了代码,在linux也可以安装。利用这个特性,linux就可以通过powershell远程执行windows中的程序。

powershell的安装也非常容易,微软在github上提供了编译好的不同系统的安装包,可以更具自己?#19981;?#30340;系统来选择。

https://github.com/PowerShell/PowerShell/releases/download/v6.2.2/powershell-6.2.2-1.rhel.7.x86_64.rpm

centos通过rpm方式安装:

wget https://github.com/PowerShell/PowerShell/releases/download/v6.2.2/powershell-6.2.2-1.rhel.7.x86_64.rpm
rpm -ivh  powershell-6.2.2-1.rhel.7.x86_64.rpm 

安装完成之后的测试需要特别注意,网上很多方法都说跟windows类似使用powershell进入,实际上目前已经变成了pwsh

分类: linux 标签:

nginx proxy_pass 配置详解

2019年7月10日 没有评论
语法:proxy_pass URL;
默认值:
上下文:locationif in locationlimit_except

设置被代理的服务器的协议和地址,还可以设置可选的URI。

协议是“http?#34987;?#32773;“https”。

地址既可以使用域名或者IP地址加端口(可选)的形式来定义:

proxy_pass http://localhost:8000/uri/;

或使用UNIX域套接字路径来定义。该路径接在“unix”?#22336;?#20018;后面,两端由冒号所包围,比如:

proxy_pass http://unix:/tmp/backend.socket:/uri/;

如果解析一个域名得到多个地址,所有的地址都会?#26376;?#36716;的方式被使用。?#27604;唬?#20063;可以使用upstream来定义地址。

请求URI按下面规则传送给后端被代理服务器:

1.如果proxy_pass使用了URI(下面例子中127.0.0.1地址后面部分,包括只有斜杠的情况),请求路径与loction路径的匹配部分将被替换为proxy_pass中定义的URI:

 
location /name/ {
proxy_pass http://127.0.0.1/remote/;
}

2.如果proxy_pass没有使用URI,发给被代理服务器的请求路径和客户端发情的请求路径相同,不会被修改。

location /some/path/ {
proxy_pass http://127.0.0.1;
}

特殊情况:

1.location使用正则表达式定义路径。这种情况下,指令不应该带有URI。

2.使用rewrite指令改变了URI,但仍使用相同配置处理请求(break):

location /name/ {
rewrite /name/([^/]+) /users?name=$1 break;
proxy_pass http://127.0.0.1;
}

这种情况下,指令设置的URI会被忽略,改变后的URI将被发送给后端服务器。

3.后端服务器的地址,端口和URI中都可以使用变量:

proxy_pass http://$host$uri; 
分类: nginx 标签:

nginx upstream 配置和作用

2019年7月10日 没有评论

配置例子

upstream backend {
    server backend1.example.com       weight=5;
    server backend2.example.com:8080;
    server unix:/tmp/backend3;

    server backup1.example.com:8080   backup;
    server backup2.example.com:8080   backup;
}

server {
    location / {
        proxy_pass http://backend;
    }
}

指令

语法:upstream name { ... }
默认值:
上下文:http

定义一组服务器。 这些服务器可以监听不同的端口。 而且,监听在TCP和UNIX域套接字的服务器可以混用。

例子:

upstream backend {
    server backend1.example.com weight=5;
    server 127.0.0.1:8080       max_fails=3 fail_timeout=30s;
    server unix:/tmp/backend3;
}

默认情况下,nginx按加权轮转的方式将请求分发到各服务器。 在上面的例子中,每7个请求会通过以下方式分发: 5个请求分到backend1.example.com, 一个请求分到第二个服务器,一个请求分到第三个服务器。 与服务器通信的时候,如果出?#25191;?#35823;,请求会被传给下一个服务器,直到所有可用的服务器都被尝试过。 如果所有服务器都返回失败,客户端将会得到最后通信的那个服务器的(失败)响应结果。

语法:server address [parameters];
默认值:
上下文:upstream

定义服务器的地址address和其他参数parameters。 地址可以是域名或者IP地址,端口是可选的,或者是指定“unix:”前缀的UNIX域套接字的路径。如果没有指定端口,就使用80端口。 如果一个域名解析到多个IP,本质上是定义了多个server。

你可以定义下面的参数:weight=number设定服务器的权重,默认是1。max_fails=number设定Nginx与服务器通信的尝试失败的次数。在fail_timeout参数定义的时间段内,如果失败的次数达到此值,Nginx就认为服务器不可用。在下一个fail_timeout时间段,服务器不会再被尝试。 失败的尝试次数默认是1。设为0就会停止统计尝试次数,认为服务器是一直可用的。 你可以通过指令proxy_next_upstream、 fastcgi_next_upstream和memcached_next_upstream来配置什么是失败的尝试。 默认配置时,http_404状态不被认为是失败的尝试。fail_timeout=time设定

  • 统计失败尝试次数的时间段。在这段时间中,服务器失败次数达到指定的尝试次数,服务器就被认为不可用。
  • 服务器被认为不可用的时间段。

默认情况下,该超时时间是10秒。backup标记为备用服务器。当主服务器不可用以后,请求会被传给这些服务器。down标记服务器永久不可用,可以跟ip_hash指令一起使用。

Example:

upstream backend {
    server backend1.example.com     weight=5;
    server 127.0.0.1:8080           max_fails=3 fail_timeout=30s;
    server unix:/tmp/backend3;

    server backup1.example.com:8080 backup;
}
语法:ip_hash;
默认值:
上下文:upstream

指定服务器组的负载均衡方法,请求基于客户端的IP地址在服务器间进行分发。 IPv4地址的前三个字节或者IPv6的整个地址,会被用来作为一个散列key。 这种方法可以确保从同一个客户端过来的请求,会被传给同一台服务器。除了当服务器被认为不可用的时候,这些客户端的请求会被传给其他服务器,而且很有可能也是同一台服务器。

从1.3.2和1.2.2版本开始支持IPv6地址。

如果其中一个服务器想暂时移除,应该?#30001;?code>down参数。这样可?#21592;?#30041;当前客户端IP地址散列分布。

例子:

upstream backend {
    ip_hash;

    server backend1.example.com;
    server backend2.example.com;
    server backend3.example.com down;
    server backend4.example.com;
}

从1.3.1和1.2.2版本开始,ip_hash的负载均衡方法才支持设置服务器权重值。

语法:keepalive connections;
默认值:
上下文:upstream

这个指令出现在版本 1.1.4.

激活对上游服务器的连接进行缓存。

connections参数设置每个worker进程与后端服务器保持连接的最大数量。这些保持的连接会被放入缓存。 如果连接数大于这个值时,最久未使用的连接会被关闭。

需要注意的是,keepalive指令不会限制Nginx进程与上游服务器的连接总数。 新的连接总会按需被创建。 connections参数应该稍微设低一点,?#21592;?#19978;游服务器也能处理额外新进来的连接。

配置memcached上游服务器连接keepalive的例子:

upstream memcached_backend {
    server 127.0.0.1:11211;
    server 10.0.0.2:11211;

    keepalive 32;
}

server {
    ...

    location /memcached/ {
        set $memcached_key $uri;
        memcached_pass memcached_backend;
    }

}

对于HTTP代理,proxy_http_version指令应该设置为“1.1?#20445;?#21516;时“Connection”头的值也应被清空。

upstream http_backend {
    server 127.0.0.1:8080;

    keepalive 16;
}

server {
    ...

    location /http/ {
        proxy_pass http://http_backend;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        ...
    }
}

另外一种选择是,HTTP/1.0协议的持久连接也可以通过发送“Connection: Keep-Alive”头来实现。?#36824;?#19981;建议这样用。

对于FastCGI的服务器,需要设置 fastcgi_keep_conn 指令来让连接keepalive工作:

upstream fastcgi_backend {
    server 127.0.0.1:9000;

    keepalive 8;
}

server {
    ...

    location /fastcgi/ {
        fastcgi_pass fastcgi_backend;
        fastcgi_keep_conn on;
        ...
    }
}

当使用的负载均衡方法不是默认的轮转法时,必须在keepalive 指令之前配置。

针对SCGI和uwsgi协议,还没有实?#21046;鋕eepalive连接的打算。

语法:least_conn;
默认值:
上下文:upstream

这个指令出现在版本 1.3.1 和 1.2.2.

指定服务器组的负载均衡方法,根据其权重值,将请求发送到活跃连接数最少的那台服务器。 如果这样的服务器有多台,那就采取有权重的轮转法进行尝试。

嵌入的变量

ngx_http_upstream_module模块支持以下嵌入变量:

$upstream_addr保存服务器的IP地址和端口或者是UNIX域套接字的路径。 在请求处理过程中,如果有多台服务器被尝试了,它们的地址会被拼接起来,以逗号隔开,比如: “192.168.1.1:80, 192.168.1.2:80, unix:/tmp/sock”。 如果在服务器之间通过“X-Accel-Redirect”头或者error_page有内部跳转,那么这些服务器组之间会以冒号隔开,比如:“192.168.1.1:80, 192.168.1.2:80, unix:/tmp/sock : 192.168.10.1:80, 192.168.10.2:80”。$upstream_response_time以毫秒的精度保留服务器的响应时间,(输出)单位是秒。 出现多个响应时,也是以逗号和冒号隔开。$upstream_status保存服务器的响应代码。 出现多个响应时,也是以逗号和冒号隔开。$upstream_http_...保存服务器的响应头的值。比如“Server”响应头的值可以通过$upstream_http_server变量来获取。 需要注意的是只有最后一个响应的头会被保留下?#30784;?

分类: nginx 标签:

nginx rtmp流?#25945;?#30452;播服务器配置

2019年7月9日 没有评论

nginx是一个轻?#32771;?#30340;web服务器,通过RTMP模块可以提供流?#25945;?#26381;务。RTMP没有预编译好的包,需要从源码编译。

安装nginx和RTMP模块

本文在ubuntu环境实现。安装前的编译工具准备:

$ sudo apt-get install build-essential libpcre3 libpcre3-dev libssl-dev

下载nginx源码包:

$ wget http://nginx.org/download/nginx-1.15.1.tar.gz

从git上下载RTMP模块源码:

$ wget https://github.com/sergey-dryabzhinsky/nginx-rtmp-module/archive/dev.zip

解压两个压缩包,进入nginx文件夹:

$ tar -zxvf nginx-1.15.1.tar.gz
$ unzip dev.zip
$ cd nginx-1.15.1

编译带有rtmp模块的nginx:

$ ./configure --with-http_ssl_module --add-module=../nginx-rtmp-module-dev
$ make
$ sudo make install

到此,nginx安装完成。默认安装到 /usr/local/nginx, 启动命令

$ sudo /usr/local/nginx/sbin/nginx

测试nginx是否正常工作,使用浏览器打开http://ip/,可以看到 "Welcome to nginx!" 页面。

nginx配置RTMP模块

打开配置文件,位置在/usr/local/nginx/conf/nginx.conf ,添加如下配置:

rtmp {
        server {
                listen 1935;
                chunk_size 4096;

                application live {
                        live on;
                        record off;
                }
        }
}

这个一个最基础的直播流配置,把RTMP流发送给请求者。

重启nginx:

$ sudo /usr/local/nginx/sbin/nginx -s stop
$ sudo /usr/local/nginx/sbin/nginx

测试

1.配置OBS推流

新建一个场景,配置如下:

Streaming Service: Custom
Server: rtmp://<your server ip>/live
Play Path/Stream Key: test

2.播放流

使用VLC v2.1.0以后版本,打开网络流文件,输入rtmp://<your server ip>/live/test 就可以看到视频了!

rtmp完整配置,

分类: nginx 标签:

Redis协议详细规范

2019年6月29日 没有评论

Redis客户端和服务器端通信使用名为 RESP (REdis Serialization Protocol) 的协议。虽然这个协议是专门为Redis设计的,它也可以用在其它 client-server 通信模式的软件上。

RESP 是下面条件的折中:

  • 实?#21046;?#26469;简单。
  • 解析速度快。
  • 有可读性。

RESP 能序列化不同的数据类?#20572;?#20363;如整型(integers)、?#22336;?#20018;(strings)、数组(arrays)。额外还有特殊的错误类型。请求从客户端以?#22336;?#20018;数组的形式发送到redis服务器,这些?#22336;?#20018;表示要执行的命令的参数。Redis用特定于命令的数据类型回?#30784;?/p>

RESP 是二进制安全的,并?#20063;?#38656;要处理从一个进程发到另外一个进程的批量数据,因为它使用前缀长度来传输批量数据。 注意:这里概述的协议仅用于客户机-服务器通信。Redis集群使用不同的二进制协议在节点之间?#25442;?#28040;息。

网络层

连到Redis服务器的客户端建立了一个到6379端口的TCP连接。

虽然RESP在技术上不特定于TCP,但是在Redis的上下文中,该协议仅用于TCP连接(或类似的面向流的连接,如unix套接字)。

请求-响应模型

Redis接受由不同参数组成的命令。一旦收到命令,就会对其进行处理,并将应答发送回客户端。

这是最简单的模?#20572;?#20294;是有两个例外:

  • Redis 支持管道pipelining。所以,客户端可以一次发送多个命令,然后再等待应答。
  • 当一个Redis客户端订阅一个频道,那么协议会改变语义并变成pushprotocol, 也就是说,客户客户端不再需要发送命令,因为服务器端会一收到新消息,就会?#36828;?#21457;送给客户端。

除了上面两个例外情况,Redis协议是一个简单的请求-响应协议。

RESP 协议解释

RESP 协议在Redis1.2被引入,直到Redis2.0才成为和Redis服务器通信的标准。这个协议需要在你的Redis客户端实现。

RESP 是一个支持多种数据类型的序列化协议:简单?#22336;?#20018;(Simple Strings),错误( Errors),整?#20572;?Integers), 大容量?#22336;?#20018;(Bulk Strings)和数组(Arrays)。

RESP在Redis中作为一个请求-响应协议以如下方式使用:

  • 客户端以大容量?#22336;?#20018;RESP数组的方式发送命令给服务器端。
  • 服务器端根据命令的具体实?#22336;?#22238;某一种RESP数据类型。

在 RESP 中,数据的类型?#35272;?#20110;首字节:

  • 简单?#22336;?#20018;(Simple Strings): 响应的首字节是 “+”
  • 错误(Errors): 响应的首字节是 “-“
  • 整?#20572;↖ntegers): 响应的首字节是 “:”
  • 大容量?#22336;?#20018;(Bulk Strings): 响应的首字节是“$”
  • 数组(Arrays): 响应的首字节是 “*

另外,RESP可以使用大容量?#22336;?#20018;或者数组类型的特殊变量表示空值,下面会具体解释。RESP协议的不同部分总是以 “\r\n” (CRLF) 结束。

RESP 简单?#22336;?#20018;

简单?#22336;?#20018;编码方法: 加号后面跟着一个不包含回车或换行?#22336;?#30340;?#22336;?#20018; (不允许出?#21482;?#34892;),以CRLF(“\r\n”)结尾。

简单?#22336;?#20018;通常被用来传输非二进制安全?#22336;?#20018;并且消耗极小。例如,许多redis命令在成功?#34987;馗础癘K?#20445;?#21363;简单?#22336;?#20018;用以下5个字节编码:

"+OK\r\n"

为了发送二进制安全的?#22336;?#20018;,需要使用RESP的大容量?#22336;?#20018;(Bulk Strings)替代。

当Redis返回简单?#22336;?#20018;(Simple String)时,客户端lib应该返回去掉首?#22336;?#21152;号和结尾CRLF?#22336;?#30340;?#22336;?#20018;给调用者。

RESP Errors

RESP 有特殊类型来处理错误。errors类?#32479;?#20102;首?#22336;?#26159;减号 ‘-‘不是加号以外,其它跟简单?#22336;?#20018;一样。RESP中简单?#22336;?#21644;错误的真正区别是:错误被客户?#35828;?#20316;异常处理,组成错误类型的?#22336;?#20018;是错误消息自身。

基本格式如下:

"-Error message\r\n"

错误应答只在发生异常时发?#20572;?#20363;如,要执行命令的参数数据类型不匹配或者命令不存在等。当收到错误返回时,客户端lib应该抛出一个异常。

错误返回例子:

-ERR unknown command 'foobar'
-WRONGTYPE Operation against a key holding the wrong kind of value

从”-“后面第一个单词起,直到第一个空格或者换行,表示返回的错误类型。这是Redis的一种约定,并不是RESP协议的要求。

ERR 是一个通用错误, 而 WRONGTYPE 是表示更具体的错误,意味着客户端在错误的数据类型上执行操作。这被叫做错误前缀(Error Prefix), 使客户端不用?#35272;?#20855;体错误消息就知道返回的错误类?#20572;?#38169;误消息可能会随着时间而变化。

客户端实现可能会对不同异常返回不同类型的错误,或者可能提供一种通用的方式来捕获错误,通过以?#22336;?#20018;的形式直接返回错误名给调用者。

尽管如此,这种特性不能认为很重要,因为它很少被使用。一小部分客户端的实现可能会返回通用错误条件,例如false。

RESP 整型

整型类型是由以冒号开头,CRLF结尾,中间是?#22336;?#20018;形式表示的数字。 例如 “:0\r\n”, 或 “:1000\r\n” 都是整型回?#30784;?/p>

很多Redis命令返回RESP整数,像 INCRLLEN 和 LASTSAVE.

返回的整数并没有特别的意义, INCR 返回的是一个递增的数字, LASTSAVE 返回的是Unix时间戳等。返回的整数有效值需要在有符号64位整数范围内。

整型返回也?#36824;?#27867;的用来返回 true 或 false。比如 EXISTS 或 SISMEMBER 命令返回1表示true,返回0表示false。

其它命令像 SADDSREM 和 SETNX 如果操作被执行则返回1,否则返回0。

返回整型回复的命令: SETNXDELEXISTSINCRINCRBYDECRDECRBYDBSIZELASTSAVERENAMENXMOVELLENSADDSREMSISMEMBERSCARD.

RESP 大容量?#22336;?#20018;

大容量?#22336;?#20018;被用来表示最大512MB长的二进制安全?#22336;?#20018;。

大容量?#22336;?#20018;编码方式:

  • 美元符 “$” 后面跟着组成?#22336;?#20018;的字节数(前缀长度),并以 CRLF 结尾。
  • 实际的?#22336;?#20018;数据。
  • 结尾是 CRLF。

所以,?#22336;?#20018; “foobar” 编码如下:

"$6\r\nfoobar\r\n"

空?#22336;?#20018;编码格式:

"$0\r\n\r\n"

RESP 大容量?#22336;?#20018;(Bulk Strings) 也可以使用一个特殊的用来表示空值的格式表示不存在的值。在这种格式里长度值为-1,数据部分不存在,所以空(Null)用如下方式表示:

"$-1\r\n"

叫做空的大容量?#22336;?#20018;Null Bulk String。

客户端API库不应该返回空串,当服务器端响应一个空的大容量?#22336;?#20018;时,API库可以返回一个空对象给调用者。例如,Ruby库应该返回 ‘nil’ ,而C库应该返回NULL。 

RESP 数组

客户端使用 RESP 数组发送命令到 Redis 服务端。同样地,某些使用 RESP 数组返回元素集合给客户端的 Redis 命令是应答类型。 LRANGE 命令返回元素?#26012;?#23601;是一个例子。

RESP 数组使用如下格式发?#20572;?/p>

  • 以星号* 为首?#22336;?#25509;着是表示数组中元素个数的十进制数,最后以 CRLF 结尾。
  • 外加数组中每个 RESP 类型的元素。

空数组表示:

"*0\r\n"

有两个 RESP 大容量?#22336;?#20018;”foo” 和”bar”元素的 RESP 数组 :

"*2\r\n$3\r\nfoo\r\n$3\r\nbar\r\n"

在前缀 *<count>CRLF 的后面,组成数组的其它数据类型一个接在另一个后面。 例如包含三个整数的数组编码方式:

"*3\r\n:1\r\n:2\r\n:3\r\n"

数组可以包含混合类?#20572;?#19981;一定必须是同一种类型。例如,4个整型和1个大容量?#22336;?#20018;编码方式:

*5\r\n
:1\r\n
:2\r\n
:3\r\n
:4\r\n
$6\r\n
foobar\r\n

(为了方便阅读,应答分成多行来展示)

第一个行表示 *5\r\n 说明后面有5个应答。这些应答组成一个大的应答一起发送。

空数组的概念也是存在的,另一个表示空值的方式(通常使用大容量空?#22336;?#20018;,历史遗留导致有这两种格式)。

例如,当 BLPOP 命令超时,它会返回一个空数组,数组的计数器是-1 :

"*-1\r\n"

当 Redis 返回一个空数组的时候,Redis客户端库API应该返回一个空对象而不是返回一个空数组。 这对区分空?#26012;?#21644;其它不同情况(像 BLPOP 命令超时情况)是必要的。

数组的数组也是可行的。例如,一个含有两个数组元素的数组编码方式:

*2\r\n
*3\r\n
:1\r\n
:2\r\n
:3\r\n
*2\r\n
+Foo\r\n
-Bar\r\n

(为了方便阅读,分成多行来展示).

上面的 RESP 数据类型包含两个数组,一个数组包含三个整数1, 2, 3 ,另一个是简单?#22336;?#20018;和一个错误类型。

数组中的空元素

数组中可以有为空的元素。主要使用在Redis应答中,为了表示这个元素丢失并?#20063;?#26159;一个空的?#22336;?#20018;。当SORT命令使用GET 模式选项,并且特定的key丢失的?#34987;?#20986;现这种应答。 含有有空元素的应答数组例子:

*3\r\n
$3\r\n
foo\r\n
$-1\r\n
$3\r\n
bar\r\n

第二个元素是空,客户端库应该返回像下面这样的数据:

["foo",nil,"bar"]

这不是前面提到的异常情况,这只是说明协议的一个例子。

发送命令到Redis服务器

?#38142;耍?#25105;?#19988;?#32463;很熟悉RESP序列化格式,写一个Redis客户端库的实?#21482;?#21464;得很容易。我?#24378;?#20197;进一步说明客户端和服务端如何?#25442;?#24037;作:

  • 客户端发送包含只有大容量?#22336;?#20018;的数组给Redis服务器。
  • Redis 服务器给客户端发送?#25105;?#26377;效的 RESP 数据类型作为应答。

下面是一个典型的?#25442;?#36807;程例子:

客户端发送命令 LLEN mylist 来获取存储在 mylist 键中?#26012;?#30340;长读,然后服务器端返回整数应答(C: 代表客户端, S: 代表服务器端).

C: *2\r\n
C: $4\r\n
C: LLEN\r\n
C: $6\r\n
C: mylist\r\n

S: :48293\r\n

为了方便理解我们?#27809;?#34892;把协议分成不同部分,实际上客户端发送的是一个整体没有换行:*2\r\n$4\r\nLLEN\r\n$6\r\nmylist\r\n as a whole.

管道和多个命令

客户端可以使用同一个连接发送多个命令。通过管道客户端可以一次写操作发送多个命令,发送下一个命令?#23433;?#38656;要等待前一个命令的应答。所有应答可以在最后?#27426;?#21462;。

关于管道详细参考 page about Pipelining.

内联命令

有时你手边只能操作telnet 并且需要给Redis 服务器端发送命令。虽然Redis协议是容易实现的,但并不适合用在?#25442;?#20250;话。redis-cli 也不是随时都能可用。因此,redis还以一种特殊的方式接受为人类设计的命令,称为内联命令格式。 以下是使用内联命令进行服务器/客户端聊天的示例(服务器聊天以s开头,客户端聊天以c开头)。

C: PING
S: +PONG

以下是返回整数的内联命令的另一个示例:

C: EXISTS somekey
S: :0

基本上,您只需在telnet会话中编写空格分隔的参数。由于统一请求协议中没有以*开头的命令,因此Redis能够检测到这种情况并解析您的命令。

Redis 协议的高性能解析器

虽然redis协议是非常容易被人阅读和实现的,但是它可以以类似于二进制协议的性能来实现。

RESP 使用带前缀的长度来传输批量数据,因此不需要像使用json那样扫描有效负载以查找特殊?#22336;?#20063;不需要引用需要发送到服务器的有效负载。

批量和多批量长度可以使用代码进行处理,代码对每个?#22336;?#25191;行单个操作,同时扫描CR?#22336;?#22914;以下C代码:

RESP 使用带前缀的长度来传输大容量数据,因此不需要像使用json那样扫描有效负载以查找特殊?#22336;?#20063;不需要引用需要发送到服务器的有效负载。

大容量和多个大容量长度可以使用代码进行处理,代码对每个?#22336;?#25191;行单个操作,同时扫描CR?#22336;?#22914;以下C代码:

#include <stdio.h>

int main(void) {
    unsigned char *p = "$123\r\n";
    int len = 0;

    p++;
    while(*p != '\r') {
        len = (len*10)+(*p - '0');
        p++;
    }

    /* Now p points at '\r', and the len is in bulk_len. */
    printf("%d\n", len);
    return 0;
}

在识别出第一个CR之后,可以跳过它和下面的LF,而不需要任何处理。然后,可以使用不以任何方式检查有效负载的单个读取操作读取大容量数据。最后,剩余的CR和LF?#22336;?#23558;?#27426;?#24323;,而不进行任何处理。

Redis协议有着与二进制协议可比的性能,更重要的是易于在大多数高级语言中实现,从而减少了客户端软件中的错误数量。

分类: redis 标签:

spring boot eclipse 下pom文件第一行报unknown错

2019年6月28日 没有评论

从spring.io生成的maven工程,导入eclipse之后pom文件第一行出现unknown错误。

虽然报错,但是工程可以正常用 mvn 命令构建和运行。

查了一下有很多人说不同办法,升级eclipse插件、升级maven版本、删除本地maven库等等。都不太好使,最后发现只有降低spring boot版本号才好使。

如果想用新版本可以使用命令行来构建工程,忽略pom错误。

解决办法:

把spring boot 版本修改成低版本2.1.1.RELEASE就没有unknown错误提示,很神奇。

分类: java 标签:

理解Nginx的server匹配规则

2019年6月27日 没有评论

Nginx的块配置

Nginx在逻辑上将提供不同内容的配置划分为块,这些块以层次结构的形式存在(http->server->location)。客户端发出请求时,Nginx收到之后,会有一个确定应该使用哪些配置块来处理请求的过程。本文主要介绍 server 块背后的处理过程。

server块是Nginx配置的子集,它定义用于处理已定义类型请求的虚拟服务器(虚拟机)。管理员通常会配置多个server块,并根据请求的域名,端口和IP地址决定哪个块应该处理哪个连接。

Nginx如何决定哪个server块来处理请求

由于Nginx允许管理员定义多个server块作为单独的虚拟Web服务器实例,因此需要一个算法来确定将使用哪些server块来匹配请求。

Nginx在此过程中关注的主要server块指令是listen指令和server_name指令。

解析“listen”指令以找到可能的匹配

首先,Nginx查看请求的IP地址和端口,并与每个服务器的 listen 指令相匹配,构建可能解析请求的服务器块?#26012;懟?/p>

listen指令通常定义 server 块将响应的IP地址和端口。默认情况下,任何不包含listen指令的 server 块默认 listen 在0.0.0.0:80(或者0.0.0.0:8080如果Nginx由普通的非root?#27809;?#36816;行),这样的配置块响应80端口上任何接口的请求,但是这个默认值在server选择过程中没有太大的权重。

listen指令可以设置为:

  • IP地址/端口组合。
  • 只有IP地址,它将监听默认端口80。
  • 只有端口,它将监听该端口上的每个接口。
  • Unix套接字的路径。

最后的选项通常在不同的服务器之间传递请求时起到作用。

在尝试确定向哪个服务器块发送请求时,Nginx将首先尝试listen使用以下规则根据指令的特异性来决定:

  • Nginx用默认的缺省值来替换所有不完整的lesten指令(完整:IP+port的组合)的缺省值,因此每一个server块的listen指令都可以看作是IP地址和端口的组合。 这种转换的例子有:
    • 没有listen指令的块使用该值0.0.0.0:80
    • 设置为111.111.111.111没有端口的IP地址的块变为111.111.111.111:80
    • 设置为8888没有IP地址的端口的块变为0.0.0.0:8888
  • 接下来Nginx会尝试去收集一个server块的?#26012;恚?#36825;个?#26012;?#26159;基于具体的IP和端口最佳匹配。也就是?#31561;?#26524;匹配的server块有具体的IP地址,它就不会匹配用0.0.0.0作为默认的IP地址的server块。无论什么情况,在Nginx选择server块的过程中,端口必须?#26082;?#21305;配。
  • 如果只有一个最具体的匹配,那么该server块将用于提供请求。如果有多个server 块具有相同层次的具体匹配,那么Nginx需继续评估server_name指令 。

需要特别注意的是,只有 listen 指令在同一层次上有多个匹配的 server 块时,Nginx才会继续评估server_name指令。举个例子,如果域名example.com被解析到IP为192.168.1.10,端口为80的主机上,当客户端请求example.com时,在本例中,第一个server模块总是会提供服务,尽管server_name指令在第二个server模块中。

1
2
3
4
server{
listen 192.168.1.10;
....
}
1
2
3
4
5
server{
listen 80;
server_name example.com;
....
}

多个server模块在具体的匹配中处于同一级别的情况下,Nginx下一步才会检查server_name指令。

解析server_name指令选择一个匹配

接下来,为了进一步评估具有相同特定listen指令的请求,Nginx会检查请求的“host”标头,此值包含客户端实际尝试访问的域或IP地址。

Nginx在候选的每一个server模块中,查看其server_name指令,尝试去找到最佳的匹配。Nginx通过下面的公式来进行评估:

  • Nginx首?#26085;?#21040;server_name与请求的Host头信息精准匹配的server模块,如果找到了这个server模块,它将会被用于服务客户端的请求。若有多个特定的匹配项被找到,第一个会被用于提供服务。
  • 如果没有找到精准的匹配项,Nginx接下来将尝试去找server_name与前置通配符(在配置中名称的开头用*表示)匹配的server模块。只要找到一个,这个server模块将被用于为客户端提供服务。如果找到了多个匹配,最长匹配结果的server模块将会被用于提供服务。
  • 如果使用前置通配符没有找到匹配时,Nginx接下来将尝试去找server_name与后置通配符(在配置中名称的结尾用*表示)匹配的server模块。只要找到一个,这个server模块将被用于为客户端提供服务。如果找到了多个匹配,最长匹配结果的server模块将会被用于提供服务。
  • 如果使用后置通配符没有找到匹配时,Nginx接下来将会评估用正则表达式(在名称前用~表示)定义server_name的server模块。带有与Host头匹配的正则表达式的第一个server_name将被用于提供服务。
  • 如果没有找?#25509;?#27491;则表达式定义server_name的相匹配的server模块时,Nginx接下来会使用默认IP和端口的server模块。

每一个IP地址/端口组合都有一个默认的server模块,当用上面的方法不能确定一个操作的过程时将使用默认的server模块。对于IP地址/端口的组合来说,这将是配置中的第一个模块或者是包含default_server选项作为listen指令的一部分的server模块(这将复写first-found算法)。每一个IP地址/端口组合只能有一个default_server声明。

实例

如果已定义的server_name与Host头的值精准匹配时,这个server模块将被选择来处理请求。

在这个例子中,如果请求的Host头的值被设置为 host1.example.com,第二个server模块将被选中:

1
2
3
4
5
server{
listen 80;
server_name *.example.com;
...
}
1
2
3
4
5
server{
listen 80;
server_name host1.example.com;
...
}

如果精准的匹配没有被找到时,Nginx将会检查是否有一个具有适合前置通配符的server_name。以通配符开始的最长的server_name的server模块将会被选择来完?#19978;?#24212;。

在这个例子中,如果请求的Host头是 www.example.org,第二个server模块将被选中:

1
2
3
4
5
server{
listen 80;
server_name www.example.*;
...
}
1
2
3
4
5
server{
listen 80;
server_name *.example.org;
...
}
1
2
3
4
server{
listen 80;
server_name *.org;
}

server_name以通配符开始的模块没有找到,Nginx将查看在表达式后面有通配符的匹配项是否存在。此时,以通配符结尾的最长的匹配项将被用于服务客户端的请求。

在这个例子中,如果请求的Host头被设置为 www.example.com,第三个模块将被选中:

1
2
3
4
5
server{
listen 80;
server_name host1.example.com;
...
}
1
2
3
4
server{
listen 80;
server_name example.com;
}
1
2
3
4
server{
listen 80;
server_name www.example.*;
}

如果通配符匹配项没有找到,Nginx将会去匹配用了正则表达式的server_name。第一个匹配上的server模块将会被选中来响应请求。

在这个例子中,如果请求的Host头设置为 www.example.com,那么第二个server模块将被选中来完?#19978;?#24212;。

1
2
3
4
5
server{
listen 80;
server_name example.com;
...
}
1
2
3
4
5
server{
listen 80;
server_name ~^(www|host1).*\.example\.com$;
...
}
1
2
3
4
5
server{
listen 80;
server_name ~^(subdomain|set|www|host1).*\.example\.com$;
...
}

如果上述步骤都不能满足请求,则该请求将被传递到默认的server模块以获取匹配的IP地址和端口。

分类: nginx 标签:

如何使用nginx配置负载均衡

2019年6月14日 没有评论

负载均衡是扩展应用程序并提高其性能和冗余的绝佳方法。Nginx是一种流行的Web服务器软件,可以配置为简单但功能强大的负载均衡器,以提高服务器?#35797;?#30340;可用性和效?#30465;?#22312;负载平衡配置中,nginx充当在多个单独服务器上工作的分布式Web应用程序的单个入口点。

在Web场上进行负载平衡

本文介绍如何使用nginx为云服务器配置负载均衡。作为先决条件,您需要至少安装?#25945;?#20027;机并安装Web服务器软件,?#21592;?#20102;解负载均衡器的优势。

安装nginx

目前,最新版本的CentOS,Debian和Ubuntu都提供nginx软件包,可以使用命令快速安装nginx。

#Debian和Ubuntu 
sudo apt-get update
#然后安装Nginx开源版
sudo apt-get install nginx
#CentOS 
#安装额外的软件包存储库
sudo yum install epel-release
#更新存储库并安装Nginx
sudo yum update
sudo yum install nginx

安装完成后,进入nginx主配置文件夹。

cd /etc/nginx/

根据您的操作系统不同,Web服务器配置文件将位于两个位置之一。

Ubuntu和Debian遵循在 /etc/nginx/sites-available/, 中存储虚拟主机文件的规则,这些规则 通过符号链接启用到 /etc/nginx/sites-enabled/。您可以使用以下命令启用任何新的虚拟主机文件。

sudo ln -s /etc/nginx/sites-available/vhost /etc/nginx/sites-enabled/vhost

CentOS?#27809;?#21487;以在/etc/nginx/conf.d/下找到其主机配置文件,加载了任何.conf类型的虚拟主机文件。

检查您是否可以找到至少默认配置,然后重新启动nginx。

sudo systemctl restart nginx

通过在Web浏览器中打开负载均衡器服务器的IP地址来测试服务器是否回复HTTP请求。当您看到nginx的默认欢迎页面时,安装成功。

Nginx默认欢迎页面。

如果您在加载页面时遇到问题,请检查防火墙是否阻止了您的连接。例如,在CentOS 7上,默认防火墙规则不允许HTTP流量,请使用以下命令启用它。

sudsudo firewall-cmd --add-service=http --permanent 
sudo firewall-cmd --reload

然后尝试重新加载浏览器。

将nginx配置为负载均衡器

安?#23433;?#27979;试nginx后,您可以开始配置它以实现负载平衡。从本质上讲,您需要做的就是设置nginx,其中包含要监听的连接类型以及重定向位置的说明。要实?#25191;?#30446;的,请使用您?#19981;?#30340;任何文本编辑器创建新的配置文件,例如使用vi

sudo vi /etc/nginx/conf.d/load-balancer.conf

load-balancer.conf中,您需要定义以下两个段:上游服务器,请参阅下面的示例。

#定义要包含在负载均衡方案中的服务器。  
#最好使用服务器的私有IP以获得更好的性能和安全性。
http {
upstream backend {
server 10.1.0.101;
server 10.1.0.102;
server 10.1.0.103;
}

#该服务器接受到端口80的所有流量并将其传递给上游。
#请注意,上游名称和proxy_pass需要匹配。
server {
listen 80;
location / {
proxy_pass http://backend;
}
}
}

然后保存文件并退出编辑器。

接下来,您需要禁用先前在安装后测试的默认服务器配置。同样取决于您的操作系统,这部分略有不同。

在Debian和Ubuntu系统上,您需要从启用站点的文件夹中删除默认符号链接。

sudo rm /etc/nginx/sites-enabled/default

CentOS的主机不使用相同的链接,而是简单地将重命名default.confconf.d /目录下的东西,不是结束的.conf,例如:

sudo mv /etc/nginx/conf.d/default.conf /etc/nginx/conf.d/default.conf.disabled

然后使用以下命令重新启动nginx。

sudo systemctl restart nginx

检查nginx是否成功启动。如果重新启动失败,请查看刚刚创建的  /etc/nginx/conf.d/load-balancer.conf,以确保没有错误类型或缺少分号。

在Web浏览器中输入负载均衡器的公共IP地址时,您现在应该被传递到其中一个后端服务器。

负载均衡方法

如果没有定义其他方法,默认情况下使用nginx进行负载均衡会使用循环算法,如上面的第一个示例所示。使用循环方案,将根据您在load-balancer.conf  文件中设置的顺序轮流选择每个服务器。这平衡了短期操作的请求数量。

基于最少连接的负载平衡是另一种简单的方法。顾名思义,此方法将请求定向到当?#26412;?#26377;最少活动连接的服务器。对于请求有时可能需要更长时间才能完成的应用程序,它比循环法更有效。

要启用最少连接平衡方法,请将参数least_conn添加到上游  部分,如下例所示。

upstream backend {
least_conn;
server 10.1.0.101;
server 10.1.0.102;
server 10.1.0.103;
}

虽然循环和最少连接平衡方案是公平的并且有其用途,但是它们不能提供会话持久性。如果您的Web应用程序要求?#27809;?#38543;后被定向到与之前连接相同的后端服务器,则应使用IP哈希方法。IP哈希使用访问者IP地址作为密钥来确定应选择哪个主机来为请求提供服务。这允许访问者每次被定向到同一服务器,被授予服务器可用且访问者的IP地址未被更改。

要使用此方法,请将ip_hash 添加到上游  段,如下面的示例所示。

upstream backend {
ip_hash;
server 10.1.0.101;
server 10.1.0.102;
server 10.1.0.103;
}

在不同主机之间的可用?#35797;?#19981;相等的服务器设置中,可能希望某些服务器优先于其他服务器。定义服务器权重允许您使用nginx进一步微调负载平衡。负载均衡器中权重最高的服务器最常选择。

upstream backend {
server 10.1.0.101 weight=4;
server 10.1.0.102 weight=2;
server 10.1.0.103;
}

例如,在上面显示的配置中,第一个服务器的选择频率是第二个服务器的两倍,与第三个服务器相比,它再次获得两倍的请求。

启用HTTPS的负载均衡

为您的网站启用HTTPS是保护访问者及其数据的好方法。如果您?#24418;?#22312;网络主机上实施?#29992;埽?#25105;们强烈建议您查看我们的?#25913;希?a rel="noreferrer noopener" target="_blank">了解如何在nginx上安装Let's Encrypt

在负载均衡器中使用?#29992;?#27604;您想象的要容易。您需要做的就是在负载均衡器配置文件中添加另一个服务器部分,该文件使用SSL侦听端口443上的HTTPS流量,并为上游段设置proxy_pass,就像上一个示例中的HTTP一样。

再次打开配置文件进行编辑。

sudo vi /etc/nginx/conf.d/load-balancer.conf

然后将以下服务器段添加到文件末尾。

server {
listen 443 ssl;
  server_name domain_name;
  ssl_certificate /etc/letsencrypt/live/domain_name/cert.pem;
ssl_certificate_key /etc/letsencrypt/live/domain_name/privkey.pem;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
  location / {
     proxy_pass http://backend;
  }
}

然后保存文件,退出编辑器并再次重新启动nginx。

sudo systemctl restart nginx

健?#23548;?#26597;

为了知道哪些服务器可用,nginx的反向代理实现包括?#27426;?#26381;务器健?#23548;?#26597;。如果服务器无法响应请求或回复错误,nginx将注意服务器已失败,并将尝?#21592;?#20813;?#27426;?#26102;间转发到该服务器的连接。

通过将参数max_fails设置为服务器行,可以在负载均衡器配置文件中定义特定时间段内连续不成功的连接尝试次数。默认情况下,如果未指定max_fails,则将此值设置为1.(可选)将max_fails设置为0将禁用对该服务器的运行状况检查。

如果将max_fails设置为大于1的值,则后续失败必须在特定时间范围内发生,?#21592;?#26080;法计数。此时间范围由参数fail_timeout指定,该参数还定义服务器应被视为失败的时间。默认情况下,fail_timeout设置为10秒。

在服务器标记失败并且fail_timeout设置的时间已过后,nginx将开始使用客户端请求正常探测服务器。如果探测返回成功,则服务器再次标记为实时并且正常包含在负载平衡中。

upstream backend {
server 10.1.0.101 weight=5;
server 10.1.0.102 max_fails=3 fail_timeout=30s;
server 10.1.0.103;
}

使用运行状况检查可以根据需要通过启动或关闭主机来使服务器后端适应当前需求。在高流量期间启动其他服务器可以在新?#35797;醋远?#20379;负载均衡器使用时轻松提高应用程序性能。

结论

如果您希望提高Web应用程序的性能和可用性,那么设置负载均衡器绝对值得考虑。使用nginx进行负载均衡功能强大且设置相对简单,并且与简单的?#29992;?#35299;决方案(例如Let's Encrypt客户端)一起使用,它为您的Web场提供了一个很好的前端。

虽然使用多个主机可?#21592;?#25252;您的Web服务具有冗余,但负载均衡器本身仍然可以留下单点?#25910;稀?#24744;可以通过在多个负载平衡器之间设置浮动IP来进一?#25945;?#39640;高可用性。

分类: nginx 标签:

推荐一个微信公众号

2019年6月8日 没有评论

程序员翻身

作者简介:程序员翻身,一个彪悍的程序员。曾在某大厂做过码农,后转型做产品。选择有时比努力重要,永远保持学习的热情,与你共成长。欢迎大家与我?#21019;睿?#35299;答你的职?#21040;?#21319;困惑,记录你我的?#36866;隆?/em>

分类: 杂谈 标签:

Markdown快速人门

2019年6月5日 没有评论

标题:使用#后面加题目标识标题:

#标题
##主要标题
###小标题
####第4级副标题

重点:

粗体:__string__或者**string**,斜体:_string_或者*string*,删除线:~~string~~

缩进引用:使用大于号(>)然后使用空格,然后键入文本。

无序?#26012;恚?/strong> 使用横线(-)然后使用空格,然后键入文本。

编号?#26012;恚?/strong> 使用数字(1. )然后使用空格,然后键入文本。

表格:

| Heading | Heading |
| ----| ----|
| text| text |
| text| text |

图片:![Alt text](url/filename.gif "Title text")

水平线:使用三个星号:***

外部链接:[link text](http://url)

分类: 小技巧 标签:
极速快乐十分助手
英超积分榜澳客网 玩分分彩必输 安徽快3数据 25选7开奖公告 广东十一选五一定牛 内蒙古快3基本二码遗漏 加韩国人微信 广西11选5开奖最快结果 188比分直播|直播吧 河内5分彩官网 江西快三网上平台 幸运飞艇害了多少人 不倒翁倍投法带图 欧洲博彩网秒速时时彩 河北快三套选说明