Currently im working on loadtest for websocket, but it doesnt use usual message like JSON, but it was using protobuf message.
I was successfully to send protobuf message to server.
But when I want to read message from server and write on console using this code
socket.on('message', function (message) {
console.log(`Received message: ${message}`);
});
That’s an interesting project, thanks for sharing.
The problem is that you’re logging the stringified binary message, which will only output garbage.
I’m not familiar with the protobuf JS implementation, but have you tried deserializing the received message?
According to the API docs and that demo repo, I would try this:
socket.on('message', function (message) {
let msg = new proto.Message();
let dMsg = msg.deserializeBinary(message);
// read fields from dMsg
});
Unfortunately, this is a bit hacky right now, since the WebSocket implementation in k6 only supports string messages. This should be easier now that ArrayBuffer is natively supported in goja (the JS VM k6 uses), and we’ll consider addressing this use case in upcoming versions.
What doesn’t work specifically? Do you get any errors?
That page mentions that TypeScript is optional and you can access fields in plain JS with bracket notation. That said, no, k6 doesn’t read TypeScript directly, but you could use a bundler like Webpack to pre-transform the TS to JS and load that in k6. See the template-es6 project for a start.
when i was using this method, it returned error like this
TypeError: Object has no member 'deserializeBinary'
even there are some code like this inside protofile_pb.js
/**
* Deserializes binary data (in protobuf wire format).
* @param {jspb.ByteSource} bytes The bytes to deserialize.
* @return {!proto.proto.Pong}
*/
proto.proto.Pong.deserializeBinary = function(bytes) {
var reader = new jspb.BinaryReader(bytes);
var msg = new proto.proto.Pong;
return proto.proto.Pong.deserializeBinaryFromReader(msg, reader);
};
/**
* Deserializes binary data (in protobuf wire format) from the
* given reader into the given message object.
* @param {!proto.proto.Pong} msg The message object to deserialize into.
* @param {!jspb.BinaryReader} reader The BinaryReader to use.
* @return {!proto.proto.Pong}
*/
proto.proto.Pong.deserializeBinaryFromReader = function(msg, reader) {
while (reader.nextField()) {
if (reader.isEndGroup()) {
break;
}
var field = reader.getFieldNumber();
switch (field) {
case 1:
var value = /** @type {number} */ (reader.readInt32());
msg.setEvent(value);
break;
case 2:
var value = /** @type {number} */ (reader.readInt64());
msg.setId(value);
break;
default:
reader.skipField();
break;
}
}
return msg;
};
im still trying how to map the incoming message
nb: protofile_pb.js is a converted file from protofile.proto using protoc
this issue is difficult to reproduce, so it slipped through the cracks, sorry about that.
Since the initial discussion, the binary support in k6 has improved and now the k6/ws module supports ArrayBuffer, so it should make working with binary data easier than before.
Can you share a Git repository with a minimal example that reproduces this? I’m not sure if it’s something with the way you’re bundling/loading protofile_pb.js or something with k6.
That code you shared seems to be only for the Pong WS response object. It might not be defined on whatever proto.Message() returns.
That said, there might be other ways of doing what you want. Take a look at this gist. Loading of the .proto file directly won’t work with k6, but the JSON example seems like it could. Note that you’ll need to convert the .proto to JSON beforehand, and then load it in k6 with open() instead of require().
Let us know if that works for you, otherwise please share a reproducible example.