久久久精品网站,成人伊人网,色吧av色av,亚洲AV永久无码精品秋霞电影影院

MSXML 4.0 Service Pack 2

前沿拓展:

MSXML 4.0 Servi

MSXML全名是:「Microsoft XML Cor可普味電憲粒e Services」,主要是用來(lái)執(zhí)行或開(kāi)發(fā)經(jīng)由 XML 所設(shè)計(jì)的最新應(yīng)用程序。
   微軟留揚(yáng)左星巖吧曲傷陸附正式發(fā)布了其XML的核心服務(wù)組件—MSXML 4.0。和MSXML 3.0相比,MSXML 4.0提供了大量的新功能和功能改進(jìn)。其中包括:對(duì)XML模式語(yǔ)言的支持,更快的分析器和XSLT引擎,對(duì)XML流更好的處理,更好的一致性支持。 MSXML 4.0并不是MSXML 3.0的替代產(chǎn)品,因?yàn)樵?.0中的一些過(guò)時(shí)功能已經(jīng)在4.0中徹底去除了。所以4.0可以和3.0(甚至更早的版本)同時(shí)安裝。
  MSXML 4.0 Service Pack 2 (SP2)是MSXML 4.0和MSXML 4.0 Service Pack 1 (SP1)的完全取代版本亮穩(wěn)。它提供了大量的安全和程序錯(cuò)誤修復(fù)。
  MSXML 4.0 SP2并不能取代MSXML 3.0,因?yàn)樗巡辉僦С忠恍┡f的以及不一致的功能。所質(zhì)肥否掌權(quán)塊破以用戶可能必須同時(shí)運(yùn)行MSX嚴(yán)以合終屋業(yè)飯換ML 4.0和MSXML 3.0或更前版本。安裝Nero 8時(shí)要安裝最新版本MSXML 4.0,按正常的安裝就可以了對(duì)你的電腦沒(méi)有多大的影響


MSXML 4.0 Service Pack 2

單機(jī)百萬(wàn)連接調(diào)優(yōu)

準(zhǔn)備兩臺(tái)Linux服務(wù)器,一個(gè)充當(dāng)服務(wù)端,一個(gè)充當(dāng)客戶端。

服務(wù)端

**作系統(tǒng):CentOS 7配置:4核8GIP:192.168.118.138

客戶端

**作系統(tǒng):CentOS 7配置:4核8GIP:192.168.118.139

服務(wù)端和客戶端均要配置java環(huán)境,基于jdk1.8。

如何模擬百萬(wàn)連接#

如果服務(wù)端只開(kāi)一個(gè)端口,客戶端連接的時(shí)候,端口號(hào)是有數(shù)量限制的(非root用戶,從1024到65535,大約6w),所以服務(wù)端開(kāi)啟一個(gè)端口,客戶端和服務(wù)端的連接最多6w個(gè)左右。

為了模擬單機(jī)百萬(wàn)連接,我們?cè)诜?wù)端開(kāi)啟多個(gè)端口,例如8000~8100,一共100個(gè)端口,客戶端還是6w的連接,但是可以連接服務(wù)端的不同端口,所以就可以模擬服務(wù)端百萬(wàn)連接的情況。

準(zhǔn)備服務(wù)端程序#

服務(wù)端程序的主要邏輯是:

綁定8000端口一直到8099端口,一共100個(gè)端口,每2s鐘統(tǒng)計(jì)一下連接數(shù)。

channelActive觸發(fā)的時(shí)候,連接+1, channelInactive觸發(fā)的時(shí)候,連接-1。

代碼見(jiàn):Server.java

準(zhǔn)備客戶端程序#

客戶端程序的主要邏輯是:

循環(huán)連接服務(wù)端的端口(從8000一直到8099)。

代碼見(jiàn):Client.java

準(zhǔn)備好客戶端和服務(wù)端的代碼后,打包成Client.jar和Server.jar并上傳到客戶端和服務(wù)端的/data/app目錄下。打包配置參考pom.xml

服務(wù)端和客戶端在/data/app下分別準(zhǔn)備兩個(gè)啟動(dòng)腳本,其中服務(wù)端準(zhǔn)備的腳本為startServer.sh, 客戶端準(zhǔn)備的腳本為startClient.sh,內(nèi)容如下:

startServer.sh

java -jar server.jar -Xms6.5g -Xmx6.5g -XX:NewSize=5.5g -XX:MaxNewSize=5.5g -XX:MaxDirectMemorySize=1g

startClient.sh

java -jar client.jar -Xms6.5g -Xmx6.5g -XX:NewSize=5.5g -XX:MaxNewSize=5.5g -XX:MaxDirectMemorySize=1g

腳本文件見(jiàn):startServer.sh 和 startClient.sh

先啟動(dòng)服務(wù)端

cd /data/app/

./startServer.sh

查看日志,待服務(wù)端把100個(gè)端口都綁定好以后。

在啟動(dòng)客戶端

cd /data/app/

./startClient.sh

第二查看服務(wù)端日志,服務(wù)端在支撐了3942個(gè)端口號(hào)以后,報(bào)了如下錯(cuò)誤:

Caused by: java.io.IOException: Too many open files
at sun.nio.ch.FileDispatcherImpl.init(Native Method)
at sun.nio.ch.FileDispatcherImpl.<clinit>(FileDispatcherImpl.java:35)
突破局部文件句柄限制#

使用ulimit -n命令可以查看一個(gè)jvm進(jìn)程最多可以打開(kāi)的文件個(gè)數(shù),這個(gè)是局部文件句柄限制,默認(rèn)是1024,我們可以修改這個(gè)值

vi /etc/security/limits.conf

增加如下兩行

* hard nofile 1000000
* soft nofile 1000000

以上配置表示每個(gè)進(jìn)程可以打開(kāi)的最大文件數(shù)是一百萬(wàn)。

突破全局文件句柄限制#

除了突破局部文件句柄數(shù)限制,還需要突破全局文件句柄數(shù)限制,修改如下配置文件

vi /proc/sys/fs/file-max

將這個(gè)數(shù)量修改為一百萬(wàn)

echo 1000000 > /proc/sys/fs/file-max

通過(guò)這種方式修改的配置在重啟后失效,如果要使重啟也生效,需要修改如下配置

vi /etc/sysctl.conf

在文件末尾加上

fs.file-max=1000000

服務(wù)端和客戶端在調(diào)整完局部文件句柄限制和全局文件句柄限制后,再次啟動(dòng)服務(wù)端,待端口綁定完畢后,啟動(dòng)客戶端。

查看服務(wù)端日志,可以看到,服務(wù)端單機(jī)連接數(shù)已經(jīng)達(dá)到百萬(wàn)級(jí)別。

…..
connections: 434703
connections: 438238
connections: 441195
connections: 444082
connections: 447596
…..
connections: 920435
connections: 920437
connections: 920439
connections: 920442
connections: 920443
connections: 920445
…..

Netty應(yīng)用級(jí)別調(diào)優(yōu)#場(chǎng)景#

服務(wù)端接受到客戶端的數(shù)據(jù),進(jìn)行一些相對(duì)耗時(shí)的**作(比如數(shù)據(jù)庫(kù)查詢,數(shù)據(jù)處理),第二把結(jié)果返回給客戶端。

模擬耗時(shí)**作#

在服務(wù)端,模擬通過(guò)sleep方法來(lái)模擬耗時(shí)**作,規(guī)則如下:

在90.0%情況下,處理時(shí)間為1ms在95.0%情況下,處理時(shí)間為10ms在99.0%情況下,處理時(shí)間為100ms在99.9%情況下,處理時(shí)間為1000ms

代碼如下

protected Object getResult(ByteBuf data) {
int level = ThreadLocalRandom.current().nextInt(1, 1000);
int time;
if (level <= 900) {
time = 1;
} else if (level <= 950) {
time = 10;
} else if (level <= 990) {
time = 100;
} else {
time = 1000;
}
try {
Thread.sleep(time);
} catch (InterruptedException e) {
}
return data;
}
客戶端統(tǒng)計(jì)QPS和AVG邏輯#

獲取當(dāng)前時(shí)間戳,客戶端在和服務(wù)端建立連接后,會(huì)每隔1s給服務(wù)端發(fā)送數(shù)據(jù),發(fā)送的數(shù)據(jù)就是當(dāng)前的時(shí)間戳,服務(wù)端獲取到這個(gè)時(shí)間戳以后,會(huì)把這個(gè)時(shí)間戳再次返回給客戶端,所以客戶端會(huì)拿到發(fā)送時(shí)候的時(shí)間戳,第二客戶端用當(dāng)前時(shí)間減去收到的時(shí)間戳,就是這個(gè)數(shù)據(jù)包的處理時(shí)間,記錄下這個(gè)時(shí)間,第二統(tǒng)計(jì)數(shù)據(jù)包發(fā)送的次數(shù),根據(jù)這兩個(gè)變量,可以求出QPS和AVG,其中:

QPS 等于

客戶端源碼參考:Client.java

服務(wù)端源碼參考:Server.java

服務(wù)端在不做任何優(yōu)化的情況下,關(guān)鍵代碼如下


bootstrap.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) {
ch.pipeline().addLast(new FixedLengthFrameDecoder(Long.BYTES));
ch.pipeline().addLast(/*businessGroup,*/ ServerBusinessHandler.INSTANCE);
// ch.pipeline().addLast(ServerBusinessThreadPoolHandler.INSTANCE);
}
});

@ChannelHandler.Sharable
public class ServerBusinessHandler extends SimpleChannelInboundHandler<ByteBuf> {
public static final ChannelHandler INSTANCE = new ServerBusinessHandler();

@Override
protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) {
ByteBuf data = Unpooled.directBuffer();
data.writeBytes(msg);
Object result = getResult(data);
ctx.channel().writeAndFlush(result);
}

protected Object getResult(ByteBuf data) {
int level = ThreadLocalRandom.current().nextInt(1, 1000);
int time;
if (level <= 900) {
time = 1;
} else if (level <= 950) {
time = 10;
} else if (level <= 990) {
time = 100;
} else {
time = 1000;
}

try {
Thread.sleep(time);
} catch (InterruptedException e) {
}

return data;
}

@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
// ignore
}
}

運(yùn)行服務(wù)端和客戶端,查看客戶端日志

…..
qps: 1466, avg response time: 35.68182
qps: 832, avg response time: 214.28384
qps: 932, avg response time: 352.59363
qps: 965, avg response time: 384.59448
qps: 957, avg response time: 403.33804
qps: 958, avg response time: 424.5246
qps: 966, avg response time: 433.35272
qps: 980, avg response time: 484.2116
qps: 986, avg response time: 478.5395
…..
優(yōu)化方案一:使用自定義線程池處理耗時(shí)邏輯#

將服務(wù)端代碼做如下調(diào)整

bootstrap.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) {
ch.pipeline().addLast(new FixedLengthFrameDecoder(Long.BYTES));
//ch.pipeline().addLast(/*businessGroup,*/ ServerBusinessHandler.INSTANCE);
ch.pipeline().addLast(ServerBusinessThreadPoolHandler.INSTANCE);
}
});

其中ServerBusinessThreadPoolHandler中,使用了自定義的線程池來(lái)處理耗時(shí)的getResult方法。關(guān)鍵代碼如下:

private static ExecutorService threadPool = Executors.newFixedThreadPool(1000);
@Override
protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) {
ByteBuf data = Unpooled.directBuffer();
data.writeBytes(msg);
threadPool.submit(() -> {
Object result = getResult(data);
ctx.channel().writeAndFlush(result);
});

}

再次運(yùn)行服務(wù)端和客戶端,可以查看客戶端日志,QPS和AVG指標(biāo)都有明顯的改善

….
qps: 1033, avg response time: 17.690498
qps: 1018, avg response time: 17.133448
qps: 1013, avg response time: 15.563113
qps: 1010, avg response time: 15.415672
qps: 1009, avg response time: 16.049961
qps: 1008, avg response time: 16.179882
qps: 1007, avg response time: 16.120466
qps: 1006, avg response time: 15.822202
qps: 1006, avg response time: 15.987518
….

實(shí)際生產(chǎn)過(guò)程中,Executors.newFixedThreadPool(1000);中配置的數(shù)量需要通過(guò)壓測(cè)來(lái)驗(yàn)證。

優(yōu)化方案二:使用Netty原生的線程池優(yōu)化#

我們可以通過(guò)Netty提供的線程池來(lái)處理耗時(shí)的Handler,這樣的話,無(wú)需調(diào)整Handler的邏輯(對(duì)原有Handler無(wú)代碼侵入),關(guān)鍵代碼:

bootstrap.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) {
ch.pipeline().addLast(new FixedLengthFrameDecoder(Long.BYTES));
// ch.pipeline().addLast(ServerBusinessHandler.INSTANCE);
// 使用業(yè)務(wù)線程池方式
// ch.pipeline().addLast(ServerBusinessThreadPoolHandler.INSTANCE);
// 使用Netty自帶線程池方式
ch.pipeline().addLast(businessGroup,ServerBusinessHandler.INSTANCE);
}
});

其中businessGroup是Netty自帶的線程池

EventLoopGroup businessGroup = new NioEventLoopGroup(1000);

ServerBusinessHandler中的所有方法,都會(huì)在businessGroup中執(zhí)行。

再次啟動(dòng)服務(wù)端和客戶端,查看客戶端日志

…..
qps: 1027, avg response time: 23.833092
qps: 1017, avg response time: 20.98855
qps: 1014, avg response time: 18.220013
qps: 1012, avg response time: 17.447332
qps: 1010, avg response time: 16.502508
qps: 1010, avg response time: 15.692251
qps: 1009, avg response time: 15.968423
qps: 1008, avg response time: 15.888149
…..更多優(yōu)化建議#

參考Netty性能調(diào)優(yōu)奇技淫巧還有其他的嗎?

1.如果QPS過(guò)高,數(shù)據(jù)傳輸過(guò)快的情況下,調(diào)用writeAndFlush可以考慮拆分成多次write,第二單次flush,也就是批量flush**作

2.分配和釋放內(nèi)存盡量在reactor線程內(nèi)部做,這樣內(nèi)存就都可以在reactor線程內(nèi)部管理

3.盡量使用堆外內(nèi)存,盡量減少內(nèi)存的copy**作,使用CompositeByteBuf可以將多個(gè)ByteBuf組合到一起讀寫(xiě)

4.外部線程連續(xù)調(diào)用eventLoop的異步調(diào)用方法的時(shí)候,可以考慮把這些**作封裝成一個(gè)task,提交到eventLoop,這樣就不用多次跨線程

5.盡量調(diào)用ChannelHandlerContext.writeXXX()方法而不是channel.writeXXX()方法,前者可以減少pipeline的遍歷

6.如果一個(gè)ChannelHandler無(wú)數(shù)據(jù)共享,那么可以搞成單例模式,標(biāo)注@Shareable,節(jié)省對(duì)象開(kāi)銷(xiāo)對(duì)象

7.如果要做網(wǎng)絡(luò)**類(lèi)似的功能,盡量復(fù)用eventLoop,可以避免跨reactor線程

拓展知識(shí):

原創(chuàng)文章,作者:九賢生活小編,如若轉(zhuǎn)載,請(qǐng)注明出處:http://xiesong.cn/39415.html

所有国产黄片播放| 波多野结衣a区| 午夜激情高清无码| 超碰在线人人看| 91九色蝌蚪| 国产亚洲日韩欧洲精品| 久久久一级片| 亚洲一区嫩草| 亚洲人成高清| 国产直拍精品一区| 一区二区免费黄色片| 好男人在线观看免费视频www| 绿帽中出国产| 亚洲热视频| 亚州色欧美色日韩色| 密桃久久| 亚洲视频 用屄滿足你| 羞羞答答国产精品| 国产 欧美 日韩+人| 国产强被迫伦姧在线观看无码| 亚洲ab日韩ab| 成人h在线| 久草精品视频999| 国产国拍亚洲精品Mv在线观看| 久久毛| 加勒比色综合久久久久久久久| 非洲黑人颜射亚洲女人| 国产精品亚洲二区在线观看| 美女免费网站91| 盱眙县| 极品精品国产| 丁香花在线影院观看在线| 中外AV免费观看| 中文日韩大片在线播放| 日韩欧美狠狠| 亚洲无线视频一区| 丁香五月亚洲综合| 三级爽三级免费看| 久久精品国产亚洲av麻豆小说| 色窝窝无码视频| 少妇人妻无码永久免费视频|