|
| 1 | +--- |
| 2 | +title: Stream |
| 3 | +excerpt: 'GRPC Streams' |
| 4 | +weight: 30 |
| 5 | +--- |
| 6 | + |
| 7 | +# Stream |
| 8 | + |
| 9 | +Using a GRPC client creates a stream. An important note that the client should be already connected (client.connect called) to the server before creating a stream. |
| 10 | + |
| 11 | +| Method | Description | |
| 12 | +| ----------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------- | |
| 13 | +| [Stream(client, url, [,params])](https://grafana.com/docs/k6/<K6_VERSION>/javascript-api/k6-net-grpc/stream) | Using a GRPC client creates a stream. | |
| 14 | +| [Stream.write(message)](https://grafana.com/docs/k6/<K6_VERSION>/javascript-api/k6-net-grpc/stream/stream-write) | Writes a message to the stream. | |
| 15 | +| [Stream.on(event, handler)](https://grafana.com/docs/k6/<K6_VERSION>/javascript-api/k6-net-grpc/stream/stream-on) | Set up handler functions for various events on the GRPC stream. | |
| 16 | +| [Stream.end()](https://grafana.com/docs/k6/<K6_VERSION>/javascript-api/k6-net-grpc/stream/stream-end) | Signals to the server that the client has finished sending. | |
| 17 | + |
| 18 | +### Examples |
| 19 | + |
| 20 | +_A k6 script that sends several randomly chosen points from the pre-generated feature database with a variable delay in between. Prints the statistics when they are sent from the server._ |
| 21 | + |
| 22 | +{{< code >}} |
| 23 | + |
| 24 | +```javascript |
| 25 | +import { Client, Stream } from 'k6/net/grpc'; |
| 26 | +import { sleep } from 'k6'; |
| 27 | + |
| 28 | +const COORD_FACTOR = 1e7; |
| 29 | + |
| 30 | +const GRPC_ADDR = __ENV.GRPC_ADDR || '127.0.0.1:10000'; |
| 31 | +const GRPC_PROTO_PATH = __ENV.GRPC_PROTO_PATH || '../../grpc_server/route_guide.proto'; |
| 32 | + |
| 33 | +const client = new Client(); |
| 34 | +client.load([], GRPC_PROTO_PATH); |
| 35 | + |
| 36 | +// a sample DB of points |
| 37 | +const DB = [ |
| 38 | + { |
| 39 | + location: { latitude: 407838351, longitude: -746143763 }, |
| 40 | + name: 'Patriots Path, Mendham, NJ 07945, USA', |
| 41 | + }, |
| 42 | + { |
| 43 | + location: { latitude: 408122808, longitude: -743999179 }, |
| 44 | + name: '101 New Jersey 10, Whippany, NJ 07981, USA', |
| 45 | + }, |
| 46 | + { |
| 47 | + location: { latitude: 413628156, longitude: -749015468 }, |
| 48 | + name: 'U.S. 6, Shohola, PA 18458, USA', |
| 49 | + }, |
| 50 | + { |
| 51 | + location: { latitude: 419999544, longitude: -740371136 }, |
| 52 | + name: '5 Conners Road, Kingston, NY 12401, USA', |
| 53 | + }, |
| 54 | + { |
| 55 | + location: { latitude: 414008389, longitude: -743951297 }, |
| 56 | + name: 'Mid Hudson Psychiatric Center, New Hampton, NY 10958, USA', |
| 57 | + }, |
| 58 | + { |
| 59 | + location: { latitude: 419611318, longitude: -746524769 }, |
| 60 | + name: '287 Flugertown Road, Livingston Manor, NY 12758, USA', |
| 61 | + }, |
| 62 | + { |
| 63 | + location: { latitude: 406109563, longitude: -742186778 }, |
| 64 | + name: '4001 Tremley Point Road, Linden, NJ 07036, USA', |
| 65 | + }, |
| 66 | + { |
| 67 | + location: { latitude: 416802456, longitude: -742370183 }, |
| 68 | + name: '352 South Mountain Road, Wallkill, NY 12589, USA', |
| 69 | + }, |
| 70 | + { |
| 71 | + location: { latitude: 412950425, longitude: -741077389 }, |
| 72 | + name: 'Bailey Turn Road, Harriman, NY 10926, USA', |
| 73 | + }, |
| 74 | + { |
| 75 | + location: { latitude: 412144655, longitude: -743949739 }, |
| 76 | + name: '193-199 Wawayanda Road, Hewitt, NJ 07421, USA', |
| 77 | + }, |
| 78 | +]; |
| 79 | + |
| 80 | +export default () => { |
| 81 | + if (__ITER == 0) { |
| 82 | + client.connect(GRPC_ADDR, { plaintext: true }); |
| 83 | + } |
| 84 | + |
| 85 | + const stream = new Stream(client, 'main.RouteGuide/RecordRoute'); |
| 86 | + |
| 87 | + stream.on('data', (stats) => { |
| 88 | + console.log('Finished trip with', stats.pointCount, 'points'); |
| 89 | + console.log('Passed', stats.featureCount, 'features'); |
| 90 | + console.log('Travelled', stats.distance, 'meters'); |
| 91 | + console.log('It took', stats.elapsedTime, 'seconds'); |
| 92 | + }); |
| 93 | + |
| 94 | + stream.on('error', (err) => { |
| 95 | + console.log('Stream Error: ' + JSON.stringify(err)); |
| 96 | + }); |
| 97 | + |
| 98 | + stream.on('end', () => { |
| 99 | + client.close(); |
| 100 | + console.log('All done'); |
| 101 | + }); |
| 102 | + |
| 103 | + // send 5 random items |
| 104 | + for (let i = 0; i < 5; i++) { |
| 105 | + const point = DB[Math.floor(Math.random() * DB.length)]; |
| 106 | + pointSender(stream, point); |
| 107 | + } |
| 108 | + |
| 109 | + // close the client stream |
| 110 | + stream.end(); |
| 111 | + |
| 112 | + sleep(1); |
| 113 | +}; |
| 114 | + |
| 115 | +const pointSender = (stream, point) => { |
| 116 | + console.log( |
| 117 | + 'Visiting point ' + |
| 118 | + point.name + |
| 119 | + ' ' + |
| 120 | + point.location.latitude / COORD_FACTOR + |
| 121 | + ', ' + |
| 122 | + point.location.longitude / COORD_FACTOR |
| 123 | + ); |
| 124 | + |
| 125 | + // send the location to the server |
| 126 | + stream.write(point.location); |
| 127 | + |
| 128 | + sleep(0.5); |
| 129 | +}; |
| 130 | +``` |
| 131 | + |
| 132 | +{{< /code >}} |
| 133 | + |
| 134 | +_A k6 script that sends a rectangle message and results (features) are streamed back to the client._ |
| 135 | + |
| 136 | +{{< code >}} |
| 137 | + |
| 138 | +```javascript |
| 139 | +import { Client, Stream } from 'k6/net/grpc'; |
| 140 | +import { sleep } from 'k6'; |
| 141 | + |
| 142 | +const COORD_FACTOR = 1e7; |
| 143 | + |
| 144 | +const GRPC_ADDR = __ENV.GRPC_ADDR || '127.0.0.1:10000'; |
| 145 | +const GRPC_PROTO_PATH = __ENV.GRPC_PROTO_PATH || '../../grpc_server/route_guide.proto'; |
| 146 | + |
| 147 | +const client = new Client(); |
| 148 | + |
| 149 | +client.load([], GRPC_PROTO_PATH); |
| 150 | + |
| 151 | +export default () => { |
| 152 | + client.connect(GRPC_ADDR, { plaintext: true }); |
| 153 | + |
| 154 | + const stream = new Stream(client, 'main.FeatureExplorer/ListFeatures', null); |
| 155 | + |
| 156 | + stream.on('data', function (feature) { |
| 157 | + console.log( |
| 158 | + 'Found feature called "' + |
| 159 | + feature.name + |
| 160 | + '" at ' + |
| 161 | + feature.location.latitude / COORD_FACTOR + |
| 162 | + ', ' + |
| 163 | + feature.location.longitude / COORD_FACTOR |
| 164 | + ); |
| 165 | + }); |
| 166 | + |
| 167 | + stream.on('end', function () { |
| 168 | + // The server has finished sending |
| 169 | + client.close(); |
| 170 | + console.log('All done'); |
| 171 | + }); |
| 172 | + |
| 173 | + stream.on('error', function (e) { |
| 174 | + // An error has occurred and the stream has been closed. |
| 175 | + console.log('Error: ' + JSON.stringify(e)); |
| 176 | + }); |
| 177 | + |
| 178 | + // send a message to the server |
| 179 | + stream.write({ |
| 180 | + lo: { |
| 181 | + latitude: 400000000, |
| 182 | + longitude: -750000000, |
| 183 | + }, |
| 184 | + hi: { |
| 185 | + latitude: 420000000, |
| 186 | + longitude: -730000000, |
| 187 | + }, |
| 188 | + }); |
| 189 | + |
| 190 | + sleep(0.5); |
| 191 | +}; |
| 192 | +``` |
| 193 | + |
| 194 | +{{< /code >}} |
| 195 | + |
| 196 | +The preceding examples use a demo server, which you can run with the following command (Golang should be installed) in [k6 repository's root](https://github.com/grafana/k6): |
| 197 | + |
| 198 | +{{< code >}} |
| 199 | + |
| 200 | +```bash |
| 201 | +$ go run -mod=mod examples/grpc_server/*.go |
| 202 | +``` |
| 203 | + |
| 204 | +{{< /code >}} |
0 commit comments