我们有一个系统,客户端发出HTTP GET请求,系统对后端进行一些处理,压缩结果,然后将其发送给客户端.由于处理可能需要一些时间,我们将其作为ZipOutputStream包装发送response.getOutputStream().
但是,当我们在第一个中有非常少量的数据ZipEntry,而第二个条目需要很长时间时,客户端使用的浏览器会超时.我们已经尝试刷新流缓冲区,但是在向流写入至少1000个字节之前,似乎没有响应发送到浏览器.奇怪的是,一旦发送了前1000个字节,后续的刷新似乎工作正常.
我尝试将代码拆解为裸露的示例:
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
try {
ZipOutputStream _zos = new ZipOutputStream( response.getOutputStream());
ZipEntry _ze = null;
long startTime = System.currentTimeMillis();
long _lByteCount = 0;
response.setContentType("application/zip");
while (_lByteCount < 2000) {
_ze = new ZipEntry("foo");
_zos.putNextEntry( _ze );
//writes 100 bytes and then waits 10 seconds
_lByteCount += StreamWriter.write(
new ByteArrayInputStream(DataGenerator.getOutput().toByteArray()),
_zos );
System.out.println("Zip: " + _lByteCount + " Time: " + ((System.currentTimeMillis() - startTime) …Run Code Online (Sandbox Code Playgroud) 我测试HttpResponse#flushBuffer及PrintWriter#flush上Tomcat 7下方,但它似乎是回应,而忽略了他们比尽快冲洗过线的内容符合市场预期.
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/HelloServlet")
public class HelloServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
PrintWriter pw = response.getWriter();
pw.println("say hi now");
pw.flush();
response.flushBuffer();
try {
Thread.sleep(5000);
} catch (Exception e) {
}
pw.println("say bye in 5 seconds");
}
}
Run Code Online (Sandbox Code Playgroud)
在延迟之后,浏览器一起显示"hi"和"bye".这是不正当行为还是打算?
@编辑
根据@Tomasz Nurkiewicz我的建议,我再次测试,curl然后问题就消失了.似乎标准的浏览器和tcp/ip …
我正在尝试实现一个用于流式传输大型对象的servlet:
oracle.sql.BLOB blob = rs.getBLOB('obj');
InputStream in = blob.getBinaryStream();
int bufferSize = 1024;
byte[] buffer = new byte[bufferSize];
ServletOutputStream out = response.getOutputStream();
int counter=0
while((length=in.read(buffer)) != -1){
out.write(buffer,0,length);
counter++;
if(counter % 10 == 0){
counter=0;
response.flushBuffer();
}
Run Code Online (Sandbox Code Playgroud)
此代码假设通过chunck将数据发送到客户端块.现在发生的事情是,当我传输大对象(100 MB)时,内存会上升,如果有多个并行下载/流,服务器有时会死掉.
为什么这flushBuffer()不是向客户端发送数据?只有在响应关闭后,客户端才会弹出打开/保存文件.
如何将文本输出流式传输到浏览器上的页面以显示可能需要大约15-20秒的操作进度?我已经尝试HttpServletResponse直接写入输出流,但用户在整个过程完成后仍然可以看到完整的输出.
这是我到目前为止所尝试的
@RequestMapping(value = "/test")
public void test(HttpServletResponse response)
throws IOException, InterruptedException {
response.getOutputStream().println("Hello");
response.getOutputStream().flush();
Thread.sleep(2000);
response.getOutputStream().println("How");
response.getOutputStream().flush();
Thread.sleep(2000);
response.getOutputStream().println("are");
response.getOutputStream().flush();
Thread.sleep(2000);
response.getOutputStream().println("you");
response.getOutputStream().flush();
}
Run Code Online (Sandbox Code Playgroud) 我刚刚编写了一个小程序来测试一些东西,如下所示:
public class Main {
public static void main(String[] args){
ServerSocket serverSocket = null;
Socket clientSocket = null;
DataInputStream dataInputStream= null;
BufferedWriter bufferedWriter = null;
String line ;
try {
serverSocket = new ServerSocket(80);
clientSocket = serverSocket.accept();
dataInputStream = new DataInputStream(clientSocket.getInputStream());
while((line = dataInputStream.readLine()) != null){
System.out.println(line);
}
bufferedWriter = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream()));
bufferedWriter.write("HTTP/1.0 200 OK \n Date: Fri, 31 Dec 1999 23:59:59 GMT \n Content-Type: text/html \n Content-Length: 1354 \n <html>abcde<html/>");
bufferedWriter.flush();
} catch (IOException e) {
System.out.println("socket port …Run Code Online (Sandbox Code Playgroud) 我一直试图在网上澄清这个问题一段时间没有成功,所以我会试着在这里问一下.
我想找到一些资源或示例,它展示了我如何构建端到端完全反压的REST服务+客户端.我的意思是,我希望看到,给定一个实现Reactive Streams的REST客户端(无论是在Akka,JS还是其他),我将拥有(并能够"可视化")整个处理过程中的背压.构建REST服务器,例如使用Akka-Http.
为了清楚起见,我正在寻找类似下面的话题(但我找不到幻灯片或视频来确认):http://oredev.org/2014/sessions/reactive-streaming-restful-applications-with-akka -http
我对大多数示例的怀疑是关于这样一个事实:我可以找到很多案例,其中REST服务(服务器)使用Akka Http和Akka流作为后端,但我不确定背压是通过HTTP"通信"的和REST,如果客户端正在实现Reactive Streams.在这种情况下,我是否可以通过TCP/HTTP或仅仅2个独立的流桥接一个"流"?这是我的主要怀疑和困惑.
希望我足够清楚,有人能够对此事有所了解.
无论如何,谢谢!