使用dubbo框架的一些坑記錄

以下記錄都基于dubbox的使用

1.autowired一個服務(wù)失敗

服務(wù)引用配置<dubbo:reference interface="xxx">,明明就已經(jīng)聲明了xxx的服務(wù),但service bean通過autowried引用,總提示xxx不存在,原因是xxx 服務(wù)少了id的設(shè)置,查看官網(wǎng)文檔,dubbo:reference表簽,id屬性為必填項。但dubbo啟動時卻沒有發(fā)出警告,導(dǎo)致問題被隱含了。

2.超時(timeout)與重試機制(retires)

dubbo通過設(shè)置短的超時機制+重試次數(shù),馬上將當(dāng)前超時服務(wù)提供者provider切換到其他可用的provider,通過這種思路實現(xiàn)快速響應(yīng)。但對于一些新增記錄的操作來說,有可能因為設(shè)定時間內(nèi),provider無法響應(yīng),客戶端執(zhí)行n次重試,導(dǎo)致新增記錄操作的請求發(fā)了n次,數(shù)據(jù)庫里這時候保存了n條記錄數(shù)據(jù)。暫時解決方式是將那些響應(yīng)時間相對舊一些的服務(wù),它的超時時間設(shè)置長一點,并將重試次數(shù)retries設(shè)置為0

3.timeout設(shè)置問題
最近發(fā)現(xiàn)用于設(shè)置默認值的標簽<dubbo:consumer> 跟 <dubbo:provider>無法 為對應(yīng)的標簽<dubbo:reference>和<dubbo:service>設(shè)置默認值timeout。
不能進行全局配置,而只能單獨在<dubbo:reference>和<dubbo:service>上設(shè)置timeout。
還在看源碼找出問題.......,知道的麻煩告訴我一下

4.占用內(nèi)存問題:

內(nèi)存滿了以后常見影響:
<ul>
<li>A.導(dǎo)致接口異常(如數(shù)據(jù)請求失?。?</li>
<li>B.導(dǎo)致程序啟動國漫</li>
</ul>

項目拆由原來單一個應(yīng)用(可以看成單一個provider)按照業(yè)務(wù)功能便捷,拆分成好幾個provider, 但不是全部都拆了出來,還保留了一個原始比較大的provider。

基本上每個provider 至少占用100M 的內(nèi)存,有的還會占用300M,對于原始provider 會用上500M內(nèi)存!!!

也就是說比如原來單一個provider 跑程序可能占用 500M以上的內(nèi)存,經(jīng)過拆分若干過以后,就會變成 500M + ( 100M~300M ) * N。

我們這邊服務(wù)器配置比較低,基本上要兩臺服務(wù)器才能把所有provider部署下來,不然全部部署同一個服務(wù)器,最后一個啟動的provider有可能因為內(nèi)存滿了,而加載很慢,從而影響整個應(yīng)用服務(wù)不能正常運作。

PS:內(nèi)存相關(guān)檢測工具提示 top命令、jmap命令、MAT(memory analyzer tool)工具。

3.多個Provider更新維護腳本
關(guān)鍵詞 : svn + maven + shell
另外一點:由于拆分了好多個服務(wù),所以如果要一次批量全部更新的話,要在linux上不斷的cd 、 nohup java -jar ......

A.svn搭建
搭建一個專門用來 存放各個環(huán)境(如開發(fā)環(huán)境、測試環(huán)境)的運行目錄所需要的程序,包括provider, web部署目錄。
更新的時候,先本地把包提交到svn ,然后登上運行的服務(wù)器進行svn checkout。
PS:如果是生產(chǎn)環(huán)境的包就不能這樣做,有可能需要新建一個目錄然后checkout。

B.運行腳本startup.sh
為每一個provider 編寫startup.sh 腳本:
<pre>

! /bin/sh

jar=find . -iname "*.jar" -maxdepth 1
conf=pwd
conf=$conf/spring-config.xml
echo "using spring config file:$conf"
nohup java -Ddubbo.container=spring -Ddubbo.spring.config=spring-config.xml -jar $jar &
</pre>
放在maven 項目 src, 即與main 、test目錄同一級:

dir.png

現(xiàn)在有了每個provider 的startup.sh了,為了一件啟動,所以還需要寫一個總運行的腳本,
startup_all.sh :
<pre>

! /bin/sh

echo 'please run this shell using command "source"'

echo "shell start...";

cur=pwd

modules=("providerA"
"providerB");

for module in ${modules[*]}; do

binpath="$module/bin/"

echo "$module starting..."

cd $cur;
temp=pwd

echo "cd $temp "

cd $binpath;
temp=pwd
echo "cd $temp"
./startup.sh;
done;
</pre>

由于開發(fā)環(huán)境或測試環(huán)境服務(wù)器內(nèi)存不夠,有可能要將不同的provider部署到不同的服務(wù)器上,這時就要把startup_all.sh 文件拆分成兩個文件來運行。

C.Maven 處理
自動將所有項目輸出目錄 指向同一個 目錄下,目錄結(jié)構(gòu)例如
buildAll
buildAll/ProviderA
buildAll/ProviderB
只需要在pom文件 build標簽中設(shè)定directory的值即可
<pre>
<build>
<finalName>cn-jufuns-residences-origin-provider</finalName>
<directory>../../buildAll/${build.env}/${artifactId}</directory>
</pre>
其中${build.env} 可選的值為dev 、test、 production,分別表示開發(fā)環(huán)境、測試環(huán)境、生產(chǎn)環(huán)境。由parent 項目(定義所有子項目的依賴)里的pom 文件定義。

另外由于maven 輸出包含一些多余文件,所以我利用maven resources插件將需要的文件 或目錄 ,如jar,lib目錄,properties文件,shell文件,拷貝到輸出目錄底下的bin目錄:


dir2.png

maven 插件配置:
<pre>

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<executions>
<execution>
<id>copy-resources</id>
<phase>install</phase>
<goals>
<goal>copy-resources</goal>
</goals>

        <configuration>
            <outputDirectory>${build.directory}/bin</outputDirectory>
            <resources>
                <resource>
                    <directory>src/sh</directory>
                    <includes>
                        <include>*.*</include>
                    </includes>
                </resource>
                <resource>
                    <directory>src/main/resources/</directory>
                    <includes>
                        <include>*.*</include>
                    </includes>
                </resource>
                <resource>
                    <directory>${build.directory}</directory>
                    <includes>
                        <include>*.jar</include>
                        <include>lib</include>
                    </includes>
                </resource>
            </resources>

        </configuration>
    </execution>
    <!-- 拷貝lib目錄 -->
    <execution>
        <id>copy-lib</id>
        <phase>install</phase>
        <goals>
            <goal>copy-resources</goal>
        </goals>

        <configuration>
            <outputDirectory>${build.directory}/bin/lib</outputDirectory>
            <resources>

                <resource>
                    <directory>${build.directory}/lib</directory>
                    <includes>
                        <include>*.*</include>
                    </includes>
                </resource>
            </resources>

        </configuration>
    </execution>


</executions>

</plugin>
</pre>
這里要主要這個插件一定要放到最后,所以要注意下phase 這個值。

4.聚合日志Flume 使用

A.版本升級
dubbo 官方原始版本,包括dubbox 使用的還是log4j 1.X版本,為了使用Flume日志器,需要將dubbo升級為log4j2 版本。
(如果直接使用log4j 1.X版本 + Flume Appender 會報異常,提示Flume Appender 不能占用當(dāng)前線程進行工作,而log4j2 是支持異步日志器 AsyncLogger,所以升級到log4j2版本)
如果沒記錯,由于spring 3.x 對log4j2 版本不支持,所以同時也把spring 3.x 升級到4.0。

B.Flume搭建一些bug
配置好Flume以后,客戶端log4j2 遠程傳送日志到Flume時,提示"拒絕連接",
百度了一下,說是avroSource 綁定IP 不能指定localhost 或127.0.0.1 或0.0.0.0,改了以后就正常使用了。下面是Flume properties配置文件信息:
<pre>
a1.sources = r1
a1.channels = memoryChannel
a1.sinks = fileRollSink

seqSource

a1.sources.seqSource.type = seq

agent.sources.seqSource.channels = fileChannel

avro source for log4j

a1.sources.r1.type = avro
a1.sources.r1.channels = memoryChannel
a1.sources.r1.bind = 172.16.3.213
a1.sources.r1.port = 44446

sink configuration

fileRollSink

a1.sinks.fileRollSink.type = file_roll
a1.sinks.fileRollSink.sink.serializer = TEXT
a1.sinks.fileRollSink.sink.directory = /opt/app_logs/
a1.sinks.fileRollSink.sink.pathManager = ROLLTIME
a1.sinks.fileRollSink.sink.pathManager.prefix = all-app-
a1.sinks.fileRollSink.sink.pathManager.extension = log
a1.sinks.fileRollSink.sink.rollInterval = 3600
a1.sinks.fileRollSink.batchSize = 100
a1.sinks.fileRollSink.channel = memoryChannel

loggerSink

a1.sinks.loggerSink.type = logger
a1.sinks.loggerSink.channel = memoryChannel

channels configuration

fileChannel

a1.channels.fileChannel.type = file

a1.channels.fileChannel.dataDirs = /Users/IssacChow/workstation/apache/flume/apache-flume-1.7.0-bin/datadir

a1.channels.fileChannel.checkpointDir = /Users/IssacChow/workstation/apache/flume/apache-flume-1.7.0-bin/checkpointdir

memoryChannel

a1.channels.memoryChannel.type = memory
a1.channels.memoryChannel.capacity = 1000
a1.channels.memoryChannel.transactionCapacity = 100
</pre>

運行腳本startup.sh :
<pre>

! /bin/sh

nohup ./bin/flume-ng agent -n "a1" --conf "./conf" -f "./conf/flume-conf.properties" &
</pre>

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容