![](/img/trans.png)
[英]How to close AsyncHttpClient with Netty for an asynchronous Http request?
[英]How can I send multiple http requests asynchronous with Netty?
我試圖異步發送大量的http發布請求到一個服務器。 我的目標是將每個響應與其原始請求進行比較。
為此,我將關注Netty Snoop示例 。
但是,此示例(以及其他http示例)不包括如何異步發送多個請求,也不包括如何將它們隨后鏈接到相應的請求。
所有類似的問題(例如這一個 , 這個或者這個問題 ,都實現了SimpleChannelUpstreamHandler類,它來自netty 3並且不再存在於4.0中( 文檔netty 4.0 )
任何人都知道如何在netty 4.0中解決這個問題?
編輯:
我的問題是雖然我向頻道寫了很多消息,但我只收到非常慢的響應(1響應/秒,而希望接收幾千/秒)。 為了澄清這一點,讓我發布到目前為止我所得到的內容。 我確信我發送請求的服務器也可以處理大量流量。
到目前為止我得到了什么:
import java.net.URI
import java.nio.charset.StandardCharsets
import java.io.File
import io.netty.bootstrap.Bootstrap
import io.netty.buffer.{Unpooled, ByteBuf}
import io.netty.channel.{ChannelHandlerContext, SimpleChannelInboundHandler, ChannelInitializer}
import io.netty.channel.socket.SocketChannel
import io.netty.channel.socket.nio.NioSocketChannel
import io.netty.handler.codec.http._
import io.netty.handler.timeout.IdleStateHandler
import io.netty.util.{ReferenceCountUtil, CharsetUtil}
import io.netty.channel.nio.NioEventLoopGroup
import scala.io.Source
object ClientTest {
val URL = System.getProperty("url", MY_URL)
val configuration = new Configuration
def main(args: Array[String]) {
println("Starting client")
start()
}
def start(): Unit = {
val group = new NioEventLoopGroup()
try {
val uri: URI = new URI(URL)
val host: String= {val h = uri.getHost(); if (h != null) h else "127.0.0.1"}
val port: Int = {val p = uri.getPort; if (p != -1) p else 80}
val b = new Bootstrap()
b.group(group)
.channel(classOf[NioSocketChannel])
.handler(new HttpClientInitializer())
val ch = b.connect(host, port).sync().channel()
val logFolder: File = new File(configuration.LOG_FOLDER)
val fileToProcess: Array[File] = logFolder.listFiles()
for (file <- fileToProcess){
val name: String = file.getName()
val source = Source.fromFile(configuration.LOG_FOLDER + "/" + name)
val lineIterator: Iterator[String] = source.getLines()
while (lineIterator.hasNext) {
val line = lineIterator.next()
val jsonString = parseLine(line)
val request = createRequest(jsonString, uri, host)
ch.writeAndFlush(request)
}
println("closing")
ch.closeFuture().sync()
}
} finally {
group.shutdownGracefully()
}
}
private def parseLine(line: String) = {
//do some parsing to get the json string I want
}
def createRequest(jsonString: String, uri: URI, host: String): FullHttpRequest = {
val bytebuf: ByteBuf = Unpooled.copiedBuffer(jsonString, StandardCharsets.UTF_8)
val request: FullHttpRequest = new DefaultFullHttpRequest(
HttpVersion.HTTP_1_1, HttpMethod.POST, uri.getRawPath())
request.headers().set(HttpHeaders.Names.HOST, host)
request.headers().set(HttpHeaders.Names.CONNECTION, HttpHeaders.Values.KEEP_ALIVE)
request.headers().set(HttpHeaders.Names.ACCEPT_ENCODING, HttpHeaders.Values.GZIP)
request.headers().add(HttpHeaders.Names.CONTENT_TYPE, "application/json")
request.headers().set(HttpHeaders.Names.CONTENT_LENGTH, bytebuf.readableBytes())
request.content().clear().writeBytes(bytebuf)
request
}
}
class HttpClientInitializer() extends ChannelInitializer[SocketChannel] {
override def initChannel(ch: SocketChannel) = {
val pipeline = ch.pipeline()
pipeline.addLast(new HttpClientCodec())
//aggregates all http messages into one if content is chunked
pipeline.addLast(new HttpObjectAggregator(1048576))
pipeline.addLast(new IdleStateHandler(0, 0, 600))
pipeline.addLast(new HttpClientHandler())
}
}
class HttpClientHandler extends SimpleChannelInboundHandler[HttpObject] {
override def channelRead0(ctx: ChannelHandlerContext, msg: HttpObject) {
try {
msg match {
case res: FullHttpResponse =>
println("response is: " + res.content().toString(CharsetUtil.US_ASCII))
ReferenceCountUtil.retain(msg)
}
} finally {
ReferenceCountUtil.release(msg)
}
}
override def exceptionCaught(ctx: ChannelHandlerContext, e: Throwable) = {
println("HttpHandler caught exception", e)
ctx.close()
}
}
ChannelFuture cf = channel.writeAndFlush(createRequest());
以及如何將它們隨后鏈接到相應的請求。
一旦為通道分配的工作線程在通道的生命周期內不會改變。 所以我們不會受益於線程。 這是因為您保持連接處於活動狀態,因此通道保持活動狀態。
要解決此問題,您可以考慮一個頻道池(比如30)。 然后使用頻道池發出請求。
int concurrent = 30;
// Start the client.
ChannelFuture[] channels = new ChannelFuture[concurrent];
for (int i = 0; i < channels.length; i++) {
channels[i] = b.connect(host, port).sync();
}
for (int i = 0; i < 1000; i++) {
ChannelFuture requestHandle = process(channels[(i+1)%concurrent]);
// do something with the request handle
}
for (int i = 0; i < channels.length; i++) {
channels[i].channel().closeFuture().sync();
}
HTH
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.