以下記錄都基于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目錄同一級:

現(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目錄:

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>