Limitierung eines Upload oder Download-Streams

fifibellt

Grünschnabel
hi,

weiß jemand wie man bei einem Upload- bzw Download-Servlet die Transfer-Rate limitiert, sprich:
- Ein Upload geht mit maximalst 50 KB
- Ein Download mit maximalst 50KB

Und nicht mit externen Tools die bandbreite limitieren sondern mit java im Servlet selbst. Geht sowas grundsätzlich gar nicht oder doch und wie? Irgendwelche Tipps wo man dazu Informationen finden würde?
Was mich auch interessieren würde wäre:
Kann man auf die gesendeten Packete soweit zugreifen dass man die ähnlich wie bei QoS Prioritäten vergeben kann?

Umgebung wäre ein Servlet Container wie Tomcat, Jetty oder ähnliches

gruß & danke
sebastian
 
Hallo,

ich würd das so machen (wobei ich nicht weis ob das so mit der Servlet spec Konform ist, wenn ich den Servlet-Thread selber blocke...)

Schau mal hier:
Java:
/**
 * 
 */
package de.tutorials;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.concurrent.TimeUnit;

/**
 * @author Thomas.Darimont
 * 
 */
public class ThrottledOutputStream extends FilterOutputStream {

    int maxKiloBytesPerSecond;
    long maxBytesPerMilliSecond;
    long startTimeMillis = -1;
    long overallBytesWritten;
    boolean verbose;

    public ThrottledOutputStream(OutputStream out) {
        super(out);
    }

    @Override
    public void write(byte[] b, int off, int len) throws IOException {
        super.write(b, off, len);
        overallBytesWritten += len - off;
        if (startTimeMillis == -1) {
            startTimeMillis = System.currentTimeMillis();
        } else {
            long deltaTimeMillis = System.currentTimeMillis() - startTimeMillis;
            long expectedBytesWritten = deltaTimeMillis
                    * maxBytesPerMilliSecond;

            if (verbose) {
                // TODO use a logger here
                System.out.printf("dt: %s, eobw: %s, obw: %s\n",
                        deltaTimeMillis, expectedBytesWritten,
                        overallBytesWritten);
            }

            if (expectedBytesWritten < overallBytesWritten) {
                long deltaBytesWritten = overallBytesWritten
                        - expectedBytesWritten;
                long timeToSleepInMilliSeconds = deltaBytesWritten
                        / maxBytesPerMilliSecond;
                if (timeToSleepInMilliSeconds > 0) {
                    if (verbose) {
                        // TODO use a logger here
                        System.out.println("Sleep: "
                                + timeToSleepInMilliSeconds);
                    }
                    try {
                        TimeUnit.MILLISECONDS.sleep(timeToSleepInMilliSeconds);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    public int getMaxKiloBytesPerSecond() {
        return maxKiloBytesPerSecond;
    }

    public void setMaxKiloBytesPerSecond(int maxKiloBytesPerSecond) {
        this.maxKiloBytesPerSecond = maxKiloBytesPerSecond;
        this.maxBytesPerMilliSecond = maxKiloBytesPerSecond * 1024 / 1000;
    }

    public boolean isVerbose() {
        return verbose;
    }

    public void setVerbose(boolean verbose) {
        this.verbose = verbose;
    }

    public static void main(String[] args) throws Exception {
        File file = new File("c:/tmp/P4260910.JPG");
        FileInputStream inputStream = new FileInputStream(file);

        ThrottledOutputStream throttledOutputStream = new ThrottledOutputStream(
                new FileOutputStream("c:/tmp/test.dat"));
        throttledOutputStream.setVerbose(true);

        throttledOutputStream.setMaxKiloBytesPerSecond(64);

        long time = -System.currentTimeMillis();

        byte[] buffer = new byte[16384];

        for (int bytesRead = inputStream.read(buffer); bytesRead >= 0; bytesRead = inputStream
                .read(buffer)) {
            throttledOutputStream.write(buffer, 0, bytesRead);
        }
        throttledOutputStream.close();
        time += System.currentTimeMillis();

        System.out.println(time + " ms");
        System.out
                .println(((file.length() / 1024) / (time / 1000)) + " kb / s");
    }
}

Ausgabe:
Code:
dt: 188, eobw: 12220, obw: 32768
Sleep: 316
dt: 719, eobw: 46735, obw: 49152
Sleep: 37
dt: 1000, eobw: 65000, obw: 65536
Sleep: 8
dt: 1187, eobw: 77155, obw: 81920
Sleep: 73
dt: 1437, eobw: 93405, obw: 98304
Sleep: 75
dt: 1703, eobw: 110695, obw: 114688
Sleep: 61
dt: 1937, eobw: 125905, obw: 131072
Sleep: 79
dt: 2203, eobw: 143195, obw: 147456
Sleep: 65
dt: 2453, eobw: 159445, obw: 163840
Sleep: 67
dt: 2702, eobw: 175630, obw: 180224
Sleep: 70
dt: 2952, eobw: 191880, obw: 196608
Sleep: 72
dt: 3202, eobw: 208130, obw: 212992
Sleep: 74
dt: 3468, eobw: 225420, obw: 229376
Sleep: 60
dt: 3718, eobw: 241670, obw: 245760
Sleep: 62
dt: 3952, eobw: 256880, obw: 262144
Sleep: 80
dt: 4218, eobw: 274170, obw: 278528
Sleep: 67
dt: 4452, eobw: 289380, obw: 294912
Sleep: 85
dt: 4733, eobw: 307645, obw: 311296
Sleep: 56
dt: 4983, eobw: 323895, obw: 327680
Sleep: 58
dt: 5217, eobw: 339105, obw: 344064
Sleep: 76
dt: 5467, eobw: 355355, obw: 360448
Sleep: 78
dt: 5733, eobw: 372645, obw: 376832
Sleep: 64
dt: 5983, eobw: 388895, obw: 393216
Sleep: 66
dt: 6233, eobw: 405145, obw: 409600
Sleep: 68
dt: 6483, eobw: 421395, obw: 425984
Sleep: 70
dt: 6733, eobw: 437645, obw: 442368
Sleep: 72
dt: 6983, eobw: 453895, obw: 458752
Sleep: 74
dt: 7248, eobw: 471120, obw: 475136
Sleep: 61
dt: 7482, eobw: 486330, obw: 491520
Sleep: 79
dt: 7748, eobw: 503620, obw: 507904
Sleep: 65
dt: 7998, eobw: 519870, obw: 524288
Sleep: 67
dt: 8248, eobw: 536120, obw: 540672
Sleep: 70
dt: 8513, eobw: 553345, obw: 557056
Sleep: 57
dt: 8763, eobw: 569595, obw: 573440
Sleep: 59
dt: 8998, eobw: 584870, obw: 589824
Sleep: 76
dt: 9263, eobw: 602095, obw: 606208
Sleep: 63
dt: 9513, eobw: 618345, obw: 622592
Sleep: 65
dt: 9763, eobw: 634595, obw: 638976
Sleep: 67
dt: 10013, eobw: 650845, obw: 655360
Sleep: 69
dt: 10263, eobw: 667095, obw: 671744
Sleep: 71
dt: 10513, eobw: 683345, obw: 688128
Sleep: 73
dt: 10778, eobw: 700570, obw: 704512
Sleep: 60
dt: 11028, eobw: 716820, obw: 720896
Sleep: 62
dt: 11263, eobw: 732095, obw: 737280
Sleep: 79
dt: 11528, eobw: 749320, obw: 753664
Sleep: 66
dt: 11778, eobw: 765570, obw: 770048
Sleep: 68
dt: 12028, eobw: 781820, obw: 786432
Sleep: 70
dt: 12278, eobw: 798070, obw: 802816
Sleep: 73
dt: 12528, eobw: 814320, obw: 819200
Sleep: 75
dt: 12778, eobw: 830570, obw: 835584
Sleep: 77
dt: 13043, eobw: 847795, obw: 851968
Sleep: 64
dt: 13278, eobw: 863070, obw: 868352
Sleep: 81
dt: 13543, eobw: 880295, obw: 884736
Sleep: 68
dt: 13793, eobw: 896545, obw: 901120
Sleep: 70
dt: 14043, eobw: 912795, obw: 917504
Sleep: 72
dt: 14293, eobw: 929045, obw: 933888
Sleep: 74
dt: 14543, eobw: 945295, obw: 950272
Sleep: 76
dt: 14793, eobw: 961545, obw: 966656
Sleep: 78
dt: 15058, eobw: 978770, obw: 983040
Sleep: 65
dt: 15293, eobw: 994045, obw: 999424
Sleep: 82
dt: 15558, eobw: 1011270, obw: 1015808
Sleep: 69
dt: 15808, eobw: 1027520, obw: 1032192
Sleep: 71
dt: 16058, eobw: 1043770, obw: 1048576
Sleep: 73
dt: 16308, eobw: 1060020, obw: 1064960
Sleep: 76
dt: 16558, eobw: 1076270, obw: 1081344
Sleep: 78
dt: 16824, eobw: 1093560, obw: 1097728
Sleep: 64
dt: 17058, eobw: 1108770, obw: 1114112
Sleep: 82
dt: 17323, eobw: 1125995, obw: 1130496
Sleep: 69
dt: 17589, eobw: 1143285, obw: 1146880
Sleep: 55
dt: 17823, eobw: 1158495, obw: 1163264
Sleep: 73
dt: 18073, eobw: 1174745, obw: 1179648
Sleep: 75
dt: 18339, eobw: 1192035, obw: 1196032
Sleep: 61
dt: 18589, eobw: 1208285, obw: 1212416
Sleep: 63
dt: 18839, eobw: 1224535, obw: 1228800
Sleep: 65
dt: 19089, eobw: 1240785, obw: 1245184
Sleep: 67
dt: 19323, eobw: 1255995, obw: 1261568
Sleep: 85
dt: 19604, eobw: 1274260, obw: 1277952
Sleep: 56
dt: 19838, eobw: 1289470, obw: 1294336
Sleep: 74
dt: 20088, eobw: 1305720, obw: 1310720
Sleep: 76
dt: 20354, eobw: 1323010, obw: 1327104
Sleep: 62
dt: 20604, eobw: 1339260, obw: 1343488
Sleep: 65
dt: 20854, eobw: 1355510, obw: 1359872
Sleep: 67
dt: 21104, eobw: 1371760, obw: 1376256
Sleep: 69
dt: 21354, eobw: 1388010, obw: 1392640
Sleep: 71
dt: 21635, eobw: 1406275, obw: 1409024
Sleep: 42
dt: 21853, eobw: 1420445, obw: 1425408
Sleep: 76
dt: 22103, eobw: 1436695, obw: 1441792
Sleep: 78
dt: 22369, eobw: 1453985, obw: 1458176
Sleep: 64
dt: 22619, eobw: 1470235, obw: 1474560
Sleep: 66
dt: 22869, eobw: 1486485, obw: 1490944
Sleep: 68
dt: 23119, eobw: 1502735, obw: 1507328
Sleep: 70
dt: 23369, eobw: 1518985, obw: 1523712
Sleep: 72
dt: 23634, eobw: 1536210, obw: 1540096
Sleep: 59
dt: 23869, eobw: 1551485, obw: 1556480
Sleep: 76
dt: 24118, eobw: 1567670, obw: 1572864
Sleep: 79
dt: 24384, eobw: 1584960, obw: 1589248
Sleep: 65
dt: 24634, eobw: 1601210, obw: 1605632
Sleep: 68
dt: 24884, eobw: 1617460, obw: 1622016
Sleep: 70
dt: 25134, eobw: 1633710, obw: 1638400
Sleep: 72
dt: 25384, eobw: 1649960, obw: 1654784
Sleep: 74
dt: 25649, eobw: 1667185, obw: 1671168
Sleep: 61
dt: 25899, eobw: 1683435, obw: 1687552
Sleep: 63
dt: 26134, eobw: 1698710, obw: 1703936
Sleep: 80
dt: 26399, eobw: 1715935, obw: 1720320
Sleep: 67
dt: 26649, eobw: 1732185, obw: 1736704
Sleep: 69
dt: 26899, eobw: 1748435, obw: 1753088
Sleep: 71
dt: 27055, eobw: 1758575, obw: 1760678
Sleep: 32
27289 ms
63 kb / s

In einem DownloadServlet könnte man das dann so benutzen:
Java:
/**
 * 
 */
package de.tutorials;

import java.io.IOException;
import java.io.InputStream;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @author Thomas.Darimont
 *
 */
public class DownloadServletWithThrottledOutputStream extends HttpServlet{
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        InputStream inputStream = null; //the bytes we want to stream to the client.
        
        ThrottledOutputStream throttledOutputStream = new ThrottledOutputStream(resp.getOutputStream());
        throttledOutputStream.setMaxKiloBytesPerSecond(32);
        
        byte[] buffer = new byte[16384];

        for (int bytesRead = inputStream.read(buffer); bytesRead >= 0; bytesRead = inputStream
                .read(buffer)) {
            throttledOutputStream.write(buffer, 0, bytesRead);
        }
        
        throttledOutputStream.flush();
        inputStream.close();
        
    }
}

Btw. cool hab gerade gesehen, dass du auch beim Google Summer Of Code mitmachst :) Eure Videoconferencing Lösung schaut ja mal schick aus :)

Gruß Tom
 
Zurück