<p>在之前我有專門寫兩篇文章介紹過<a target="_blank">Exceptionless這款開源日志項目的使用和部署</a>,但是當(dāng)時是基于4.1.0版本(2017年的release),時隔兩年多Exceptionless也推出了5.0.0版本。</p>
<h1>一、關(guān)于Exceptionless 5.0.0</h1>
<p> Exceptionless 是一個開源的實時的好用的日志收集框架,它將日志收集變得簡單易用并且不需要了解太多的相關(guān)技術(shù)細節(jié)及配置。但是之前的版本將其Web和API綁定在了Windows平臺通過IIS運行,對于已經(jīng)步入云原生時代的我們顯得有點格格不入。5.0.0的發(fā)布解決了這一痛點,其最大的變化就是基于ASP.NET Core重寫并支持跨平臺,也就是說當(dāng)初我們設(shè)想的要是能夠基于Docker部署在Linux服務(wù)器下就更好了的愿望已經(jīng)實現(xiàn)了,在此真心<em><strong>感謝Exceptionless項目的各位貢獻者</strong></em>。本文就Exceptionless 5.0.0版本介紹一下快速地部署開發(fā)環(huán)境和生產(chǎn)環(huán)境,相信對有興趣的朋友會有一點幫助。</p>
<p> 至此我也可以將我們之前的Exceptionless從Windows Server遷移到Linux上了!</p>
<h1>二、快速本地部署步驟</h1>
<h2>2.1 安裝Docker 18.09+</h2>
<p> 由于Exceptionless 5.0.0的一個前置要求是Docker版本(CE)在18.09及以上,因此我們需要安裝一個18.09+的Docker CE版本到Linux服務(wù)器上,如果你之前安裝了可以跳過此步驟,但如果版本小于18.09,那么請清理掉老版本升級到新版本,升級版本可以參考以下步驟。</p>
<p> 實驗環(huán)境:<a target="_blank">阿里云ECS主機</a>,CentOS 7.4</p>
<p> (1)清理已有Docker老版本</p>
<p> 停止Docker老版本:</p>
<div class="cnblogs_code">
<pre>systemctl stop docker</pre>
</div>
<p> 卸載軟件包:</p>
<div class="cnblogs_code"><div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="復(fù)制代碼"><img src="http://common.cnblogs.com/images/copycode.gif" alt="復(fù)制代碼"></a></span></div>
<pre><span style="color: #0000ff;">yum</span><span style="color: #000000;"> erase docker
docker</span>-<span style="color: #000000;">client
docker</span>-client-<span style="color: #000000;">latest
docker</span>-<span style="color: #000000;">common
docker</span>-<span style="color: #000000;">latest
docker</span>-latest-<span style="color: #000000;">logrotate
docker</span>-<span style="color: #000000;">logrotate
docker</span>-<span style="color: #000000;">selinux
docker</span>-engine-<span style="color: #000000;">selinux
docker</span>-<span style="color: #000000;">engine
docker</span>-ce</pre>
<div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="復(fù)制代碼"><img src="http://common.cnblogs.com/images/copycode.gif" alt="復(fù)制代碼"></a></span></div></div>
<p> 刪除相關(guān)配置文件:</p>
<div class="cnblogs_code">
<pre><span style="color: #0000ff;">find</span> /etc/systemd -name <span style="color: #800000;">'</span><span style="color: #800000;">docker</span><span style="color: #800000;">'</span> -exec <span style="color: #0000ff;">rm</span> -<span style="color: #000000;">f {} ;
</span><span style="color: #0000ff;">find</span> /etc/systemd -name <span style="color: #800000;">'</span><span style="color: #800000;">docker</span><span style="color: #800000;">'</span> -exec <span style="color: #0000ff;">rm</span> -<span style="color: #000000;">f {} ;
</span><span style="color: #0000ff;">find</span> /lib/systemd -name <span style="color: #800000;">'</span><span style="color: #800000;">docker</span><span style="color: #800000;">'</span> -exec <span style="color: #0000ff;">rm</span> -<span style="color: #000000;">f {} ;
</span><span style="color: #0000ff;">rm</span> -rf /var/lib/<span style="color: #000000;">docker #刪除以前已有的鏡像和容器,非必要,慎刪
</span><span style="color: #0000ff;">rm</span> -rf /var/run/docker </pre>
</div>
<p> (2)安裝Docker 18.09+</p>
<p> 軟件包安裝:</p>
<div class="cnblogs_code">
<pre><span style="color: #0000ff;">yum</span> <span style="color: #0000ff;">install</span> -y <span style="color: #0000ff;">yum</span>-utils device-mapper-persistent-data lvm2</pre>
</div>
<p> 添加yum源:</p>
<div class="cnblogs_code">
<pre><span style="color: #0000ff;">yum</span>-config-<span style="color: #000000;">manager
</span>--add-<span style="color: #000000;">repo
https:</span><span style="color: #008000;">//</span><span style="color: #008000;">download.docker.com/linux/centos/docker-ce.repo</span></pre>
</div>
<p> 查看可安裝的版本:目前最新版本已經(jīng)是19.03</p>
<div class="cnblogs_code">
<pre><span style="color: #0000ff;">yum</span> list docker-ce --showduplicates | <span style="color: #0000ff;">sort</span> -r</pre>
</div>
<p> 安裝指定版本:18.09</p>
<div class="cnblogs_code">
<pre><span style="color: #0000ff;">yum</span> <span style="color: #0000ff;">install</span> docker-ce docker-ce-18.09.9-3.el7 -y</pre>
</div>
<p> 啟動Docker并設(shè)置開機自啟動:</p>
<div class="cnblogs_code">
<pre><span style="color: #000000;">systemctl start docker
systemctl enable docker</span></pre>
</div>
<p> 查看Docker版本:</p>
<div class="cnblogs_code">
<pre>docker version </pre>
</div>
<p> 你可以看到已經(jīng)是18.09版本了:</p>
<p> <img style="width: 70%; border: 1px solid #dddddd; border-radius: 5px;" src="https://img2018.cnblogs.com/blog/381412/201909/381412-20190929225710500-226633119.png" alt=""></p>
<h2>2.2 下載Exceptionless?5.0.0 Release包</h2>
<p> 傳送門:<a target="_blank">Exceptionless release</a></p>
<p>? <img style="width: 60%; border: 1px solid #dddddd; border-radius: 5px;" src="https://img2018.cnblogs.com/blog/381412/201909/381412-20190930143735712-2018898135.png" alt=""></p>
<h2>2.3 安裝Exceptionless 5.0.0</h2>
<p> ?。?)修改docker-compose.yml文件,設(shè)置外部訪問地址/域名(適配你的服務(wù)器IP地址 或 域名+SSL證書,這里我直接修改為我的阿里云服務(wù)器的外網(wǎng)IP地址,參考我的注釋)</p>
<div class="cnblogs_code"><div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="復(fù)制代碼"><img src="http://common.cnblogs.com/images/copycode.gif" alt="復(fù)制代碼"></a></span></div>
<pre>version: <span style="color: #800000;">'</span><span style="color: #800000;">3.4</span><span style="color: #800000;">'</span><span style="color: #000000;">
services:
api:
depends_on:
</span>-<span style="color: #000000;"> elasticsearch
</span>-<span style="color: #000000;"> redis
build:
context: .
target: api
image: exceptionless</span>/<span style="color: #000000;">api:latest
restart: on</span>-<span style="color: #000000;">failure
environment:
EX_AppMode: Production
EX_BaseURL: http:</span><span style="color: #008000;">//</span><span style="color: #008000;">192.168.16.170:5100 #UI地址,修改這里的IP地址為你的服務(wù)器IP地址</span>
EX_ConnectionStrings__Cache: provider=<span style="color: #000000;">redis
EX_ConnectionStrings__Elasticsearch: server</span>=http:<span style="color: #008000;">//</span><span style="color: #008000;">elasticsearch:9200</span>
#EX_ConnectionStrings__Email: smtps:<span style="color: #008000;">//</span><span style="color: #008000;">user:password@smtp.host.com:587</span>
EX_ConnectionStrings__MessageBus: provider=<span style="color: #000000;">redis
#EX_ConnectionStrings__Metrics: provider</span>=statsd;server=<span style="color: #000000;">statsd;
EX_ConnectionStrings__Queue: provider</span>=<span style="color: #000000;">redis
EX_ConnectionStrings__Redis: server</span>=redis,abortConnect=<span style="color: #0000ff;">false</span><span style="color: #000000;">
EX_ConnectionStrings__Storage: provider</span>=folder;path=/app/<span style="color: #000000;">storage
EX_RunJobsInProcess: </span><span style="color: #800000;">'</span><span style="color: #800000;">false</span><span style="color: #800000;">'</span><span style="color: #000000;">
ports:
</span>- <span style="color: #800080;">5000</span>:<span style="color: #800080;">80</span> # This can be commented out <span style="color: #0000ff;">if</span><span style="color: #000000;"> using reverse proxy.
volumes:
</span>- appdata:/app/<span style="color: #000000;">storage
jobs:
depends_on:
</span>-<span style="color: #000000;"> api
build:
context: .
target: job
image: exceptionless</span>/<span style="color: #000000;">job:latest
restart: on</span>-<span style="color: #000000;">failure
environment:
EX_AppMode: Production
EX_BaseURL: http:</span><span style="color: #008000;">//</span><span style="color: #008000;">192.168.16.170:5100 #UI地址,修改這里的IP地址為你的服務(wù)器IP地址</span>
EX_ConnectionStrings__Cache: provider=<span style="color: #000000;">redis
EX_ConnectionStrings__Elasticsearch: server</span>=http:<span style="color: #008000;">//</span><span style="color: #008000;">elasticsearch:9200</span>
#EX_ConnectionStrings__Email: smtps:<span style="color: #008000;">//</span><span style="color: #008000;">user:password@smtp.host.com:587</span>
EX_ConnectionStrings__MessageBus: provider=<span style="color: #000000;">redis
#EX_ConnectionStrings__Metrics: provider</span>=statsd;server=<span style="color: #000000;">statsd;
EX_ConnectionStrings__Queue: provider</span>=<span style="color: #000000;">redis
EX_ConnectionStrings__Redis: server</span>=redis,abortConnect=<span style="color: #0000ff;">false</span><span style="color: #000000;">
EX_ConnectionStrings__Storage: provider</span>=folder;path=/app/<span style="color: #000000;">storage
volumes:
</span>- appdata:/app/<span style="color: #000000;">storage
ui:
image: exceptionless</span>/<span style="color: #000000;">ui:latest
environment:
AppMode: Production
EX_ApiUrl: http:</span><span style="color: #008000;">//</span><span style="color: #008000;">192.168.16.170:5000 #API地址,修改這里的IP地址為你的服務(wù)器IP地址</span>
#EX_Html5Mode: <span style="color: #800000;">'</span><span style="color: #800000;">false</span><span style="color: #800000;">'</span><span style="color: #000000;">
#EX_EnableSsl: </span><span style="color: #800000;">'</span><span style="color: #800000;">false</span><span style="color: #800000;">'</span><span style="color: #000000;">
#EX_EnableAccountCreation: </span><span style="color: #800000;">'</span><span style="color: #800000;">false</span><span style="color: #800000;">'</span><span style="color: #000000;">
ports:
</span>- <span style="color: #800080;">5100</span>:<span style="color: #800080;">80</span> # This can be commented out <span style="color: #0000ff;">if</span><span style="color: #000000;"> using reverse proxy.
reverseproxy:
depends_on:
</span>-<span style="color: #000000;"> api
</span>-<span style="color: #000000;"> ui
image: valian</span>/docker-nginx-auto-<span style="color: #000000;">ssl
restart: on</span>-<span style="color: #000000;">failure
ports:
</span>- <span style="color: #800080;">80</span>:<span style="color: #800080;">80</span><span style="color: #000000;">
</span>- <span style="color: #800080;">443</span>:<span style="color: #800080;">443</span><span style="color: #000000;">
volumes:
</span>- ssldata:/etc/resty-auto-<span style="color: #000000;">ssl
environment:
ALLOWED_DOMAINS: </span><span style="color: #800000;">'</span><span style="color: #800000;">(ex-ui|ex-api).mydomainn.com</span><span style="color: #800000;">'</span><span style="color: #000000;">
SITES: </span><span style="color: #800000;">'</span><span style="color: #800000;">ex-ui.mydomainn.com=ui;ex-api.mydomainn.com=api</span><span style="color: #800000;">'</span><span style="color: #000000;">
elasticsearch:
image: exceptionless</span>/elasticsearch:<span style="color: #800080;">1</span><span style="color: #000000;">
restart: on</span>-<span style="color: #000000;">failure
environment:
cluster.name: </span><span style="color: #800000;">'</span><span style="color: #800000;">exceptionless</span><span style="color: #800000;">'</span><span style="color: #000000;">
bootstrap.memory_lock: </span><span style="color: #800000;">'</span><span style="color: #800000;">true</span><span style="color: #800000;">'</span><span style="color: #000000;">
discovery.type: single</span>-<span style="color: #000000;">node
ES_JAVA_OPTS: </span><span style="color: #800000;">'</span><span style="color: #800000;">-Xms512m -Xmx512m</span><span style="color: #800000;">'</span><span style="color: #000000;">
xpack.security.enabled: </span><span style="color: #800000;">'</span><span style="color: #800000;">false</span><span style="color: #800000;">'</span><span style="color: #000000;">
xpack.graph.enabled: </span><span style="color: #800000;">'</span><span style="color: #800000;">false</span><span style="color: #800000;">'</span><span style="color: #000000;">
xpack.watcher.enabled: </span><span style="color: #800000;">'</span><span style="color: #800000;">false</span><span style="color: #800000;">'</span><span style="color: #000000;">
ports:
</span>- <span style="color: #800080;">9200</span>:<span style="color: #800080;">9200</span>
- <span style="color: #800080;">9300</span>:<span style="color: #800080;">9300</span><span style="color: #000000;">
ulimits:
memlock:
soft: </span>-<span style="color: #800080;">1</span><span style="color: #000000;">
hard: </span>-<span style="color: #800080;">1</span><span style="color: #000000;">
volumes:
</span>- esdata:/usr/share/elasticsearch/<span style="color: #000000;">data
kibana:
depends_on:
</span>-<span style="color: #000000;"> elasticsearch
image: exceptionless</span>/kibana:<span style="color: #800080;">1</span><span style="color: #000000;">
restart: on</span>-<span style="color: #000000;">failure
environment:
xpack.security.enabled: </span><span style="color: #800000;">'</span><span style="color: #800000;">false</span><span style="color: #800000;">'</span><span style="color: #000000;">
ports:
</span>- <span style="color: #800080;">5601</span>:<span style="color: #800080;">5601</span><span style="color: #000000;">
redis:
image: redis:alpine
restart: on</span>-<span style="color: #000000;">failure
ports:
</span>- <span style="color: #800080;">6379</span>:<span style="color: #800080;">6379</span><span style="color: #000000;">
volumes:
esdata:
driver: local
appdata:
driver: local
ssldata:
driver: local</span></pre>
<div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="復(fù)制代碼"><img src="http://common.cnblogs.com/images/copycode.gif" alt="復(fù)制代碼"></a></span></div></div>
<blockquote>
<p><em><strong>Note:</strong></em>在這個docker-compose.yml中定義了Exceptionless的最小化運行環(huán)境,但官方建議生產(chǎn)環(huán)境使用ElasticSearch集群,并適當(dāng)修改ElasticSearch的內(nèi)存限制。如果你的量很小真的不大,那么這個最小化的運行環(huán)境也夠用了,沒必要為了高可用而高可用?! ?lt;/p>
</blockquote>
<p> 此外,貌似官方已經(jīng)將exceptionless/elasticsearch:1這個鏡像移除了,大家可以使用這個鏡像:<strong>edisonsaonian/exceptionless-elasticsearch:1</strong></p>
<p> ?。?)將Release包上傳到阿里云服務(wù)器,然后通過SSH執(zhí)行一下shell命令(首先cd到這個release包的目錄下)啟動Exceptionless 5.0.0。</p>
<div class="cnblogs_code">
<pre>docker-compose up -d</pre>
</div>
<p> 整個過程會比較漫長,因為會經(jīng)過34個Steps,拉取很多鏡像,類似于Redis,ElasticSearch,Kibana及.NET Core SDK等等,請耐心等待。最終效果如下所示:</p>
<p> <img style="width: 60%; border: 1px solid #dddddd; border-radius: 5px;" src="https://img2018.cnblogs.com/blog/381412/201909/381412-20190930144146148-1348602911.png" alt=""></p>
<p> <img style="width: 70%; border: 1px solid #dddddd; border-radius: 5px;" src="https://img2018.cnblogs.com/blog/381412/201909/381412-20190930144232365-1751032748.png" alt=""></p>
<h2>2.4 使用Exceptionless 5.0.0</h2>
<p> ?。?)訪問你的服務(wù)器IP:5100 即可訪問Exceptionless Web管理登錄界面,如果你能看到,那么代表部署成功了。注冊一個賬號,然后登陸吧。</p>
<p> <img style="width: 70%; border: 1px solid #dddddd; border-radius: 5px;" src="https://img2018.cnblogs.com/blog/381412/201909/381412-20190930144336477-464695945.png" alt="" width="738" height="312"></p>
<p> (2)可以看到主頁是全新的中文管理界面,感謝貢獻者的努力</p>
<p> <img style="width: 70%; border: 1px solid #dddddd; border-radius: 5px;" src="https://img2018.cnblogs.com/blog/381412/201909/381412-20190930144419343-853462229.png" alt="" width="688" height="308"></p>
<p> <img style="width: 50%; border: 1px solid #dddddd; border-radius: 5px;" src="https://img2018.cnblogs.com/blog/381412/201909/381412-20190930144440956-1851854497.png" alt=""></p>
<p> (3)創(chuàng)建一些示例項目,如“XDP.Product.API”,并獲取API Key</p>
<p> <img style="width: 50%; border: 1px solid #dddddd; border-radius: 5px;" src="https://img2018.cnblogs.com/blog/381412/201909/381412-20190930144546508-572370284.png" alt=""></p>
<p> ?。?)在你的ASP.NET Core WebAPI項目中配置API Key,并向Exceptionless API(這里是5000端口)發(fā)送Log</p>
<p> (5)在Exceptionless中查看Log</p>
<p> <img style="width: 70%; border: 1px solid #dddddd; border-radius: 5px;" src="https://img2018.cnblogs.com/blog/381412/201909/381412-20190930144628540-1858599463.png" alt="" width="687" height="256"></p>
<p> <img style="width: 70%; border: 1px solid #dddddd; border-radius: 5px;" src="https://img2018.cnblogs.com/blog/381412/201909/381412-20190930144646360-749223515.png" alt="" width="783" height="411"></p>
<h1>三、遺留問題:Email通知配置</h1>
<p> 使用過Exceptionless的童鞋都知道,Exceptionless提供了強大的Email通知機制,可以為用戶提供及時的嚴重錯誤通知和每日報告。</p>
<p> <img style="width: 50%; border: 1px solid #dddddd; border-radius: 5px;" src="https://img2018.cnblogs.com/blog/381412/201909/381412-20190930144751848-1328868168.png" alt="" width="531" height="411"></p>
<p> 在上面介紹的安裝基礎(chǔ)上,根據(jù)官方Wiki文檔,按理說我們只需要確保docker-compose.yml中的api和jobs的AppMode為Production模式并設(shè)置SMTP就可以開啟Email通知。</p>
<div id="7338-1569824950029" class="block-view code-view yne-code-theme-default" data-language="javascript" data-theme="default">
<div class="para-text">
<div class="cnblogs_code">
<pre><span style="color: #000000;">EX_AppMode: Production
EX_ConnectionStrings__Email: smtps:</span><span style="color: #008000;">//</span><span style="color: #008000;">edisonchou7%40qq.com:zltqvl2321ed@smtp.qq.com:465</span></pre>
</div>
</div>
</div>
<div> 這里的%40是@的轉(zhuǎn)義替代,在Exceptionless中會使用Decode進行解碼為@,原因好像是因為它是通過@符號分割前方的用戶名+密碼和后方的Host+Port,也是醉了。</div>
<div> 設(shè)置完成后,通過以下命令重啟docker:</div>
<div id="8469-1569825103131" class="block-view code-view yne-code-theme-default" data-language="javascript" data-theme="default">
<div class="para-text">
<div class="cnblogs_code">
<pre>docker-compose up -d</pre>
</div>
</div>
</div>
<div> docker-compose會自動幫我們重啟更改過的容器,比如api和jobs。</div>
<div> 但是,我試了很多次都發(fā)現(xiàn)還是無法正常發(fā)送Email通知,由于不影響使用,也就暫時沒去深究了,有解決的朋友可以告知并<strong>分享一下解決辦法</strong>,謝謝。</div>
<h1>四、小結(jié)</h1>
<p> 本文介紹了Exceptionless 5.0.0的容器化本地部署,主要參考自Exceptionless的Self-Host文檔。</p>
<h1>參考資料</h1>
<p>1、<a target="_blank">Exceptionless release</a></p>
<p>2、<a target="_blank">Exceptionless Self-Hosting Documention</a></p>
<p>?</p>
<div id="Copyright">