jenkins做持續集成二

2019年7月25日 沒有評論

上一篇文章完成了jenkins的裝和基本配置

新建一個maven的持續集成項目。

注意:maven命令我們在上文最后部分自動安裝,配置保存之后并不會立刻安裝maven,maven命令工具會在第一次構建maven項目是自動下載安裝。

新建項目


配置基本信息

配置源碼獲取方式為git

遇到的一個錯誤

 No valid crumb was included in the request

在jenkins 的Configure Global Security下 , 取消“防止跨站點請求偽造(Prevent Cross Site Request Forgery exploits)”的勾選或者使用代理的情況下勾選代理。(如下圖)

繼續,設置構建觸發條件,定時掃描構建

構建前后都可以執行特定的動作如shell腳本,這里演示就省略了。只填入構建命令clean package

報保存配置之后,點立即構建

jenkins就會在后臺開始自動構架,這里會顯示構建進度,構建完成后紅色表示失敗,藍色表示成功,點擊可以進去查看日志。

點擊console查看日志

如果執行錯誤可以通過日志查看原因,修改錯誤后,重新構建

可以看到前面三步有構建失敗,查看日志可以發現原因:一個是找不到pom.xml,另一是maven下載不了文件。pom文件需要從工程根目錄開始算,加上子文件夾路徑即可。

通過查看構建日志, maven報錯如下:

Failed to transfer Could not transfer artifact org.springframework.boot:spring-boot-starter-parent:pom:1.4.1.RELEASE from/to central (https://repo.maven.apache.org/maven2): Connect to repo.maven.apache.org:443 [repo.maven.apache.org/151.101.52.215] failed: Connection timed out (Connection timed out)
ERROR: Failed to parse POMs
org.apache.maven.project.ProjectBuildingException: Some problems were encountered while processing the POMs:
[FATAL] Non-resolvable parent POM for com.jege.spring.boot:spring-boot-hello-world:1.0.0.RELEASE: Could not transfer artifact org.springframework.boot:spring-boot-starter-parent:pom:1.4.1.RELEASE from/to central (https://repo.maven.apache.org/maven2): Connect to repo.maven.apache.org:443 [repo.maven.apache.org/151.101.52.215] failed: Connection timed out (Connection timed out) and 'parent.relativePath' points at no local POM @ line 24, column 10

構建失敗,是因為jenkins配置了代理,但是自動安裝的maven沒有設置代理,給maven配置代理之后構建成功。

maven代理配置方法:

檢查完畢之后,編輯~/.m2/settings.xml文件,代碼如下:添加代理配置如下:

<settings>
? ?...
<proxies>
? ? ? <proxy>
? ? ? ? ?<id>my-proxy</id>
? ? ? ? ?<active>true</active>
? ? ? ? ?<protocol>http</protocol>
? ? ? ? ?<host>192.168.10.117</host>
? ? ? ? ?<port>3267</port>
? ? ? ? ?<!--
? ? ? ? ?<username>shihuan</username>
? ? ? ? ?<password>123456</password>
? ? ? ? ?<nonProxyHosts>repository.mycom.com|*.google.com</nonProxyHosts>
? ? ? ? ?-->
? ? ? </proxy>
? ? </proxies>
? ?...
</settings>? ?

proxies下可以配proxy元素,如果你聲明了多個proxy元素,則默認情況下第一個被激活的proxy會生效。這里聲明 了一個id為my-proxy的代理,active的值為true表示激活該代理,protocol表示使用的代理協議,這里是http。當然,最重要的 是指定正確的代理服務器的ip和端口。

分類: linux 標簽: ,

使用docker安裝jenkins做持續集成

2019年7月24日 沒有評論

一、jenkins的安裝

參考上文docker環境的安裝配置完成docker的安裝。

無論安裝什么軟件也就是一條命令的事,jenkins也不例外。

docker pull jenkins/jenkins

docker run -d -p 80:8080 -p 50000:50000 -v jenkins:/var/jenkins_home -v /etc/localtime:/etc/localtime --name jenkins jenkins

  • -d 后臺運行鏡像 -p 80:8080 將鏡像的8080端口映射到服務器的80端口
  • -p 50000:50000 將鏡像的50000端口映射到服務器的50000端口
  • -v jenkins:/var/jenkins_home 冒號前面的jenkins表示的是docker卷名,冒號后面的 /var/jenkins_home目錄為容器中jenkins工作目錄。
  • -v /etc/localtime:/etc/localtime 讓容器使用和服務器同樣的時間設置。
  • --name jenkins 給容器起一個別名

一定不能修改卷名jenkins,這個卷名是容器自帶的存放jenkins文件的地方,如果修改為別的路徑就會找不到文件,啟動jenkins就會退出。

types-of-mounts

docker 為我們提供了三種不同的方式將數據掛載到容器中:volume、bind mount、tmpfs

volume 方式是 docker 中數據持久化的最佳方式。

  • docker 默認在主機上會有一個特定的區域(/var/lib/docker/volumes/ Linux),該區域用來存放 volume。
  • 非 docker 進程不應該去修改該區域。
  • volume 可以通過 docker volume 進行管理,如創建、刪除等操作。
  • volume 在生成的時候如果不指定名稱,便會隨機生成。

  • volume 在容器停止或刪除的時候會繼續存在,如需刪除需要顯示聲明。

volume 方式應該是持久化數據的首選方式,我們啟動jenkins容器命令中的第二個-v參數是Bind mount,它會覆蓋容器中的文件,而volume mount則不會,即如果容器中已有文件,則會將文件同步到主機的目錄上 。

二、jenkins的配置

打開瀏覽器輸入http://ip進入Jenkins登錄頁面。頁面會提示你到服務器的指定位置獲取初始化密碼。

由于我們是在容器里運行的jenkins,需要進入容器去查看 /var/jenkins_home/secrets/initialAdminPassword

docker exec jenkins cat /var/jenkins_home/secrets/initialAdminPassword

在文本框中輸入這串密碼,點繼續

如果是內網,jenkins會報網絡連接超時,提示配置代理。

輸入代理信息后繼續

進入插件安裝界面,點擊左邊的推薦插件 Install suggested plugins 后繼續

開始自動安裝

創建用后保存并繼續,進入首頁,可以創建job等任務

默認沒有安裝maven插件

點擊上圖中復選框自動重啟

安裝maven,選擇addmaven,然后輸入名字,選自動安裝,保存

重啟jenkins http://ip/restart/

分類: linux 標簽:

docker快速入門

2019年7月23日 1 條評論

一、什么是docker

dcoker包括一個命令行程序、一個后臺守護進程,以及一組遠程服務器。他簡化了安裝、運行、發布和刪除軟件。

二、鏡像、容器、倉庫

鏡像,是特殊的文件系統,他包含程序、配置、資源等。

容器,鏡像的實例。就像是類和實例一樣,鏡像是靜態的定義,容器是鏡像運行時的實體。容器可以被創建、啟動、停止、刪除、暫停等。

倉庫,用于保存鏡像的服務。

三、centos安裝docker和docker-compose

注意需要使用 root 賬戶或者可以使用 sudo 的賬戶

Docker從1.13版本之后采用時間線的方式作為版本號,分為社區版CE和企業版EE。

社區版是免費提供給個人開發者和小型團體使用的,企業版會提供額外的收費服務,比如經過官方測試認證過的基礎設施、容器、插件等。

社區版按照stable和edge兩種方式發布,每個季度更新stable版本,如18.06,18.09;每個月份更新edge版本,如18.09,18.10。

安裝docker

1、Docker 要求 CentOS 系統的內核版本高于 3.10 ,查看本頁面的前提條件來驗證你的CentOS 版本是否支持 Docker 。

通過 uname -r 命令查看你當前的內核版本

 $ uname -r

2、使用 root 權限登錄 Centos。確保 yum 包更新到最新。

$ sudo yum update

3、卸載舊版本(如果安裝過舊版本的話)

$ sudo yum remove docker  docker-common docker-selinux docker-engine

4、安裝依賴

sudo yum install -y yum-utils \
device-mapper-persistent-data \
lvm2

5、添加docker下載倉庫

sudo yum-config-manager \
--add-repo \
https://download.docker.com/linux/centos/docker-ce.repo

6、docker安裝和驗證

# 安裝docker-ce
sudo yum install docker-ce

# 啟動docker-ce
sudo systemctl start docker

# 驗證
sudo docker --version

安裝 docker-compose

sudo curl -L "https://github.com/docker/compose/releases/download/1.23.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

sudo chmod +x /usr/local/bin/docker-compose

docker-compose --version

五、安裝過程中可能遇到的錯誤

Error response from daemon: Get https://index.docker.io/v1/search?q=nginx&n=25: dial tcp: lookup index.docker.io on [::1]:53: read udp [::1]:57785->[::1]:53: read: connection refused

需要配置dns,查看服務器DNS網絡配置

vi /etc/resolv.conf

添加
nameserver 8.8.8.8

docker pull nginx
Using default tag: latest
Error response from daemon: Get https://registry-1.docker.io/v2/: net/http: req uest canceled while waiting for connection (Client.Timeout exceeded while await ing headers)

這個問題多是網絡連接不好或者沒有網絡,網絡不好可以采用國內鏡像,內網用戶沒有網絡可以配置代理。

六、docker代理設置

內網服務器不能直接聯網,雖然命令行配置了http_proxy環境變量,但是docker命令行工具讀不到,會出現上面的類似錯誤。需要單獨配置docker的代理:

覆蓋docker.service file來實現

1. 創建 docker.service.d 目錄

$ mkdir -p /etc/systemd/system/docker.service.d

2. 創建HTTP 或者HTTPS 代理文件

HTTP:

vim /etc/systemd/system/docker.service.d/http-proxy.conf

HTTPS:

vim /etc/systemd/system/docker.service.d/https-proxy.conf

由于我這里用的是 “HTTPS”,所以只給大家演示HTTPS代理的配置,對于HTTP代理的修改,非常相似,大家可以參考我最后貼出來的連接。

3. 修改 https-proxy.conf 文件

[Service]
Environment="HTTPS_PROXY=xxx.xxx.xxx.xxx:443" "NO_PROXY=localhost,127.0.0.1,xxx.xxxxxx:5000"

解析:

主要是兩點內容:

①  HTTPS_PROXY 將它的值對應到您所希望設置的代理服務地址和端口(例如: HTTPS_PROXY=https://proxy.example.com:443),我這里為了保護隱私,就用xxx代替.

②  NO_PROXY 意味著某些情況下我們不需要使用HTTPS代理來訪問,一般這就配置私有倉庫的路徑(例如:NO_PROXY=localhost,127.0.0.1,mydocker-registry.com:5000

4. 完成修改后保存/刷新

###Flush changes:
#systemctl daemon-reload

###Restart Docker:
#systemctl restart docker

5. 查看修改結果

#systemctl show --property=Environment docker

Environment=HTTPS_PROXY=xxx.xxx.xxx.xxx:443 NO_PROXY=localhost,127.0.0.1,mydocker-registry.com:5000

測試:

七、如何使用Docker加速器

針對Docker客戶端版本大于1.10的用戶

修改daemon配置文件/etc/docker/daemon.json來使用加速器:

sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://w5z91a3d.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker

八、docker常用命令

docker拉取鏡像

docker pull [選項] name[:tag]

docker查看鏡像

docker images

創建并啟動容器

docker run [options] image [command] [arg...]

docker run -d -p 80:80 --name cn1 nginx

-d 放在后臺執行

-p 主機端口:容器端口 將容器的端口映射到主機上,目的是可以直接對外提供訪問

--name 指定容器名

查看容器狀態

docker ps

驗證docker運行正常

進入容器

docker exec -it cn1 bash

對容器的操作,就像普通linux那樣。我們定位到/usr/share/nginx/html/目錄,列出所有文件:

目錄下有50x.htmlindex.html兩個文件,我們新建一個test.html

echo "<html><header><title>測試頁面</title></header>test</html>" >> test.html

測試之前,先從docker退出來,不能可能會找不到命令

停止容器

docker stop [options] container

停止cn1容器
(也可以指定container id停止容器,docker stop 0e9e817ddb5e) ,不能使用鏡像名

查看停止狀態容器

容器停止并沒有銷毀,我們可以使用docker ps -a查看停止狀態的容器

重啟停止狀態的容器

docker start cn1

刪除容器

刪除容器前,必須先停止容器。刪除命令:
docker rm 容器名

再次查看終止狀態容器,docker ps -a

容器cn1已經被徹底銷毀,銷毀的容器不能使用start啟動,需要使用run重啟運行。

刪除鏡像

刪除命令:
docker rmi -f {repository}:{tag}docker rmi -f {image id}?

九、docker 網絡

linux使用namespace來進行資源的隔離 ,docker的隔離性;

1、docker的網路類型分為:

Bridge模式:橋接(默認的模式)

host模式:容器將不會獲得獨立的network namespace,將和主機公用一個;即在docker中使用網絡和主機上一樣的;

None:不與外界任何東西進行通訊

2、采用Bridge的時候需要和主機通訊,就需要使用端口映射

3、端口映射

主機的8080端口映射到容器中的80端口
$ docker run -d --name cn1 -p 8080:80 nginx  

十、docker常用命令速查

docker ps # 查看正在運行的容器
docker ps -a # 查看所有容器
docker ps -l # 查看最近一次運行的容器

docker create 容器名或者容器ID # 創建容器
docker start [-i] 容器名 # 啟動容器
docker run 容器名或者容器ID # 運行容器,相當于docker create + docker start
docker attach 容器名或者容器ID bash # 進入容器的命令行(退出容器后容器會停止)
docker exec -it 容器名或者容器ID bash # 進入容器的命令行
docker stop 容器名 # 停止容器
docker rm 容器名 # 刪除容器

docker top 容器名 # 查看WEB應用程序容器的進程
docker inspect 容器名 # 查看Docker的底層信息

分類: linux 標簽:

linux通過openssh無密碼訪問window

2019年7月18日 沒有評論

對于習慣了使用ssh連接linux執行命令的用戶來說,win10已經提供了新的可能,內置了openssh,windows也可以很容易的提供sshd服務,然后執行powershell。對于win7需要手動安裝,本文主要介紹win7安裝openssh和linux無密碼訪問linux執行程序。

win7安裝openssh

安裝包下載地址:
https://github.com/PowerShell/Win32-OpenSSH/releases

64位系統下載
OpenSSH-Win64.zip

將下載的zip包解壓縮到C:\Program Files\OpenSSH

安裝sshd服務

PS C:\Windows\system32> cd 'C:\Program Files\OpenSSH '
PS C:\Program Files\OpenSSH> powershell.exe -ExecutionPolicy Bypass -File install-sshd.ps1
[SC] SetServiceObjectSecurity 成功
[SC] ChangeServiceConfig2 成功
[SC] ChangeServiceConfig2 成功
sshd and ssh-agent services successfully installed

添加入站防火墻端口22,允許22端口可訪問

PS C:\Program Files\OpenSSH> New-NetFirewallRule -Name sshd -DisplayName 'OpenSSH Server (sshd)' -Enabled True -Directio
n Inbound -Protocol TCP -Action Allow -LocalPort 22

win7沒這個命令,自己去手動在防火墻配置添加:

控制面板\所有控制面板項\Windows 防火墻\高級設置

打開防火請22端口

啟動ssh服務:net start sshd

現在已經可在linx使用密碼訪問服務了。

linux無密碼訪問windows

配置文件位置C:\ProgramData\ssh\sshd_config,所在的目錄是隱藏目錄。打開sshd的配置文件之后,修改如下參數,去掉前面的注釋

PubkeyAuthentication yes

注釋掉結尾兩行

重啟sshd

net stop sshd ;net start sshd

Linux生成密鑰對:

ssh-keygen -t rsa -f id_rsa

把生成的公鑰id_rsa.pub內容添加到windows的
%systemdrive%\Users\<user>\.ssh\authorized_keys (如果文件不存在需要先創建)

linux下面執行 ssh -i .\id_rsa [email protected] 就可以無密碼訪問linux了。 或者把id_rsa訪問~/.ssh目錄下,這樣可以直接
ssh [email protected]

遇到如下錯誤:

2538868 2019-07-18 10:26:11.645 debug1: userauth_pubkey: test pkalg rsa-sha2-512 pkblob RSA SHA256:6LcR7NR13TTY9qR7G6HumknjLfjyrW/GIX3NfQa13Jg [preauth]
2538868 2019-07-18 10:26:11.645 debug1: trying public key file __PROGRAMDATA__/ssh/administrators_authorized_keys
2538868 2019-07-18 10:26:11.648 Authentication refused.
2538868 2019-07-18 10:26:11.648 Failed publickey for user from 10.1.1.4 port 48402 ssh2: RSA SHA256:6LcR7NR13TTY9qR7G6HumknjLfjyrW/GIX3NfQa13Jg

基本都是 authorized_keys 文件權限設置的不正確

只能 System, Administrators和user 三個用戶對
authorized_keys 有所有權限,并且文件的所有者需要是user。

檢查文件權限:
icacls %systemdrive%\Users\<user>\.ssh\authorized_keys

ssh客戶端配置錯誤日志輸出:

ssh客戶端查看日志方式 ,使用參數-vv
ssh -vv

ssh服務器端輸出日志方式:

修改配置文件 sshd_config,然后重啟sshd

  • SyslogFacility LOCAL0
  • LogLevel?to?DEBUG?(or?DEBUG2/DEBUG3 for higher levels of logging

linux環境下權限配置

no 'w' for go anywhere (group or others)
700 for?.ssh
600 for?.ssh/authorized_keys

chmod go-w /home/your-user
chmod 700  /home/your-user/.ssh
chmod 600  /home/your-user/.ssh/authorized_keys*

這其中很多波折沒有一一寫出來,linux的日志比較詳細,windows要么提示權限不對,要么提示失敗,沒有具體的錯誤點提示。微軟在github上有很多解釋說的很不錯,在最后要放棄的時候發現只要把你的authorized_keys文件跟.ssh目錄下的其它文件配置一致是不是就能解決問題,一試還真行。

linux查看服務sshd日志在tail -f /var/log/secure

https://github.com/PowerShell/Win32-OpenSSH/wiki/ssh.exe-examples
https://github.com/PowerShell/Win32-OpenSSH/wiki/Troubleshooting-Steps
https://github.com/PowerShell/Win32-OpenSSH/issues/870
https://github.com/PowerShell/Win32-OpenSSH/wiki/Install-Win32-OpenSSH
分類: linux 標簽:

centos安裝powershell

2019年7月17日 沒有評論

微軟powershell功能很強大,也支持了很多linux命令,對于只停留在cmd的同學可以試試,除了命令行,還可以用來開發圖形程序。

powershell并且不綁定在windows,微軟開源了代碼,在linux也可以安裝。利用這個特性,linux就可以通過powershell遠程執行windows中的程序。

powershell的安裝也非常容易,微軟在github上提供了編譯好的不同系統的安裝包,可以更具自己喜歡的系統來選擇。

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”或者“https”。

地址既可以使用域名或者IP地址加端口(可選)的形式來定義:

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

或使用UNIX域套接字路徑來定義。該路徑接在“unix”字符串后面,兩端由冒號所包圍,比如:

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

如果解析一個域名得到多個地址,所有的地址都會以輪轉的方式被使用。當然,也可以使用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, 一個請求分到第二個服務器,一個請求分到第三個服務器。 與服務器通信的時候,如果出現錯誤,請求會被傳給下一個服務器,直到所有可用的服務器都被嘗試過。 如果所有服務器都返回失敗,客戶端將會得到最后通信的那個服務器的(失敗)響應結果。

語法: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地址。

如果其中一個服務器想暫時移除,應該加上down參數。這樣可以保留當前客戶端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參數應該稍微設低一點,以便上游服務器也能處理額外新進來的連接。

配置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”,同時“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”頭來實現。不過不建議這樣用。

對于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協議,還沒有實現其keepalive連接的打算。

語法: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變量來獲取。 需要注意的是只有最后一個響應的頭會被保留下來。

分類: nginx 標簽:

nginx rtmp流媒體直播服務器配置

2019年7月9日 沒有評論

nginx是一個輕量級的web服務器,通過RTMP模塊可以提供流媒體服務。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 是下面條件的折中:

  • 實現起來簡單。
  • 解析速度快。
  • 有可讀性。

RESP 能序列化不同的數據類型,例如整型(integers)、字符串(strings)、數組(arrays)。額外還有特殊的錯誤類型。請求從客戶端以字符串數組的形式發送到redis服務器,這些字符串表示要執行的命令的參數。Redis用特定于命令的數據類型回復。

RESP 是二進制安全的,并且不需要處理從一個進程發到另外一個進程的批量數據,因為它使用前綴長度來傳輸批量數據。 注意:這里概述的協議僅用于客戶機-服務器通信。Redis集群使用不同的二進制協議在節點之間交換消息。

網絡層

連到Redis服務器的客戶端建立了一個到6379端口的TCP連接。

雖然RESP在技術上不特定于TCP,但是在Redis的上下文中,該協議僅用于TCP連接(或類似的面向流的連接,如unix套接字)。

請求-響應模型

Redis接受由不同參數組成的命令。一旦收到命令,就會對其進行處理,并將應答發送回客戶端。

這是最簡單的模型,但是有兩個例外:

  • Redis 支持管道pipelining。所以,客戶端可以一次發送多個命令,然后再等待應答。
  • 當一個Redis客戶端訂閱一個頻道,那么協議會改變語義并變成pushprotocol, 也就是說,客戶客戶端不再需要發送命令,因為服務器端會一收到新消息,就會自動發送給客戶端。

除了上面兩個例外情況,Redis協議是一個簡單的請求-響應協議。

RESP 協議解釋

RESP 協議在Redis1.2被引入,直到Redis2.0才成為和Redis服務器通信的標準。這個協議需要在你的Redis客戶端實現。

RESP 是一個支持多種數據類型的序列化協議:簡單字符串(Simple Strings),錯誤( Errors),整型( Integers), 大容量字符串(Bulk Strings)和數組(Arrays)。

RESP在Redis中作為一個請求-響應協議以如下方式使用:

  • 客戶端以大容量字符串RESP數組的方式發送命令給服務器端。
  • 服務器端根據命令的具體實現返回某一種RESP數據類型。

在 RESP 中,數據的類型依賴于首字節:

  • 簡單字符串(Simple Strings): 響應的首字節是 “+”
  • 錯誤(Errors): 響應的首字節是 “-“
  • 整型(Integers): 響應的首字節是 “:”
  • 大容量字符串(Bulk Strings): 響應的首字節是“$”
  • 數組(Arrays): 響應的首字節是 “*

另外,RESP可以使用大容量字符串或者數組類型的特殊變量表示空值,下面會具體解釋。RESP協議的不同部分總是以 “\r\n” (CRLF) 結束。

RESP 簡單字符串

簡單字符串編碼方法: 加號后面跟著一個不包含回車或換行字符的字符串 (不允許出現換行),以CRLF(“\r\n”)結尾。

簡單字符串通常被用來傳輸非二進制安全字符串并且消耗極小。例如,許多redis命令在成功時回復“OK”,即簡單字符串用以下5個字節編碼:

"+OK\r\n"

為了發送二進制安全的字符串,需要使用RESP的大容量字符串(Bulk Strings)替代。

當Redis返回簡單字符串(Simple String)時,客戶端lib應該返回去掉首字符加號和結尾CRLF字符的字符串給調用者。

RESP Errors

RESP 有特殊類型來處理錯誤。errors類型除了首字符是減號 ‘-‘不是加號以外,其它跟簡單字符串一樣。RESP中簡單字符和錯誤的真正區別是:錯誤被客戶端當作異常處理,組成錯誤類型的字符串是錯誤消息自身。

基本格式如下:

"-Error message\r\n"

錯誤應答只在發生異常時發送,例如,要執行命令的參數數據類型不匹配或者命令不存在等。當收到錯誤返回時,客戶端lib應該拋出一個異常。

錯誤返回例子:

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

從”-“后面第一個單詞起,直到第一個空格或者換行,表示返回的錯誤類型。這是Redis的一種約定,并不是RESP協議的要求。

ERR 是一個通用錯誤, 而 WRONGTYPE 是表示更具體的錯誤,意味著客戶端在錯誤的數據類型上執行操作。這被叫做錯誤前綴(Error Prefix), 使客戶端不用依賴具體錯誤消息就知道返回的錯誤類型,錯誤消息可能會隨著時間而變化。

客戶端實現可能會對不同異常返回不同類型的錯誤,或者可能提供一種通用的方式來捕獲錯誤,通過以字符串的形式直接返回錯誤名給調用者。

盡管如此,這種特性不能認為很重要,因為它很少被使用。一小部分客戶端的實現可能會返回通用錯誤條件,例如false。

RESP 整型

整型類型是由以冒號開頭,CRLF結尾,中間是字符串形式表示的數字。 例如 “:0\r\n”, 或 “:1000\r\n” 都是整型回復。

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

返回的整數并沒有特別的意義, INCR 返回的是一個遞增的數字, LASTSAVE 返回的是Unix時間戳等。返回的整數有效值需要在有符號64位整數范圍內。

整型返回也被廣泛的用來返回 true 或 false。比如 EXISTS 或 SISMEMBER 命令返回1表示true,返回0表示false。

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

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

RESP 大容量字符串

大容量字符串被用來表示最大512MB長的二進制安全字符串。

大容量字符串編碼方式:

  • 美元符 “$” 后面跟著組成字符串的字節數(前綴長度),并以 CRLF 結尾。
  • 實際的字符串數據。
  • 結尾是 CRLF。

所以,字符串 “foobar” 編碼如下:

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

空字符串編碼格式:

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

RESP 大容量字符串(Bulk Strings) 也可以使用一個特殊的用來表示空值的格式表示不存在的值。在這種格式里長度值為-1,數據部分不存在,所以空(Null)用如下方式表示:

"$-1\r\n"

叫做空的大容量字符串Null Bulk String。

客戶端API庫不應該返回空串,當服務器端響應一個空的大容量字符串時,API庫可以返回一個空對象給調用者。例如,Ruby庫應該返回 ‘nil’ ,而C庫應該返回NULL。 

RESP 數組

客戶端使用 RESP 數組發送命令到 Redis 服務端。同樣地,某些使用 RESP 數組返回元素集合給客戶端的 Redis 命令是應答類型。 LRANGE 命令返回元素列表就是一個例子。

RESP 數組使用如下格式發送:

  • 以星號* 為首字符,接著是表示數組中元素個數的十進制數,最后以 CRLF 結尾。
  • 外加數組中每個 RESP 類型的元素。

空數組表示:

"*0\r\n"

有兩個 RESP 大容量字符串”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"

數組可以包含混合類型,不一定必須是同一種類型。例如,4個整型和1個大容量字符串編碼方式:

*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個應答。這些應答組成一個大的應答一起發送。

空數組的概念也是存在的,另一個表示空值的方式(通常使用大容量空字符串,歷史遺留導致有這兩種格式)。

例如,當 BLPOP 命令超時,它會返回一個空數組,數組的計數器是-1 :

"*-1\r\n"

當 Redis 返回一個空數組的時候,Redis客戶端庫API應該返回一個空對象而不是返回一個空數組。 這對區分空列表和其它不同情況(像 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 ,另一個是簡單字符串和一個錯誤類型。

數組中的空元素

數組中可以有為空的元素。主要使用在Redis應答中,為了表示這個元素丟失并且不是一個空的字符串。當SORT命令使用GET 模式選項,并且特定的key丟失的時會出現這種應答。 含有有空元素的應答數組例子:

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

第二個元素是空,客戶端庫應該返回像下面這樣的數據:

["foo",nil,"bar"]

這不是前面提到的異常情況,這只是說明協議的一個例子。

發送命令到Redis服務器

至此,我們已經很熟悉RESP序列化格式,寫一個Redis客戶端庫的實現會變得很容易。我們可以進一步說明客戶端和服務端如何交互工作:

  • 客戶端發送包含只有大容量字符串的數組給Redis服務器。
  • Redis 服務器給客戶端發送任意有效的 RESP 數據類型作為應答。

下面是一個典型的交互過程例子:

客戶端發送命令 LLEN mylist 來獲取存儲在 mylist 鍵中列表的長讀,然后服務器端返回整數應答(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

為了方便理解我們用換行把協議分成不同部分,實際上客戶端發送的是一個整體沒有換行:*2\r\n$4\r\nLLEN\r\n$6\r\nmylist\r\n as a whole.

管道和多個命令

客戶端可以使用同一個連接發送多個命令。通過管道客戶端可以一次寫操作發送多個命令,發送下一個命令前不需要等待前一個命令的應答。所有應答可以在最后被讀取。

關于管道詳細參考 page about Pipelining.

內聯命令

有時你手邊只能操作telnet 并且需要給Redis 服務器端發送命令。雖然Redis協議是容易實現的,但并不適合用在交互會話。redis-cli 也不是隨時都能可用。因此,redis還以一種特殊的方式接受為人類設計的命令,稱為內聯命令格式。 以下是使用內聯命令進行服務器/客戶端聊天的示例(服務器聊天以s開頭,客戶端聊天以c開頭)。

C: PING
S: +PONG

以下是返回整數的內聯命令的另一個示例:

C: EXISTS somekey
S: :0

基本上,您只需在telnet會話中編寫空格分隔的參數。由于統一請求協議中沒有以*開頭的命令,因此Redis能夠檢測到這種情況并解析您的命令。

Redis 協議的高性能解析器

雖然redis協議是非常容易被人閱讀和實現的,但是它可以以類似于二進制協議的性能來實現。

RESP 使用帶前綴的長度來傳輸批量數據,因此不需要像使用json那樣掃描有效負載以查找特殊字符,也不需要引用需要發送到服務器的有效負載。

批量和多批量長度可以使用代碼進行處理,代碼對每個字符執行單個操作,同時掃描CR字符,如以下C代碼:

RESP 使用帶前綴的長度來傳輸大容量數據,因此不需要像使用json那樣掃描有效負載以查找特殊字符,也不需要引用需要發送到服務器的有效負載。

大容量和多個大容量長度可以使用代碼進行處理,代碼對每個字符執行單個操作,同時掃描CR字符,如以下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字符將被丟棄,而不進行任何處理。

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 標簽:
3d棋牌平台 金蟾捕鱼技巧 专业股票配资公司 开心棋牌好坑 澳门二分彩计划软件 幸运农场选任二计划 河北11选5投注 31选7现场开奖直播 加拿大快乐8开奖结果果 宁夏11选5走势图手机版 天臣股票配资 山东十一选五预测