编写proto文件
syntax = "proto3";
package helloworld;
service Greeter {
// unary call
rpc SayHello(HelloRequest) returns (HelloReply);
// server streaming call
rpc SayRepeatHello(RepeatHelloRequest) returns (stream HelloReply);
}
message HelloRequest {
string name = 1;
}
message RepeatHelloRequest {
string name = 1;
int32 count = 2;
}
message HelloReply {
string message = 1;
}
编译proto文件
protoc -I=. helloworld.proto \
--js_out=import_style=commonjs,binary:. \
--grpc-web_out=import_style=commonjs,mode=grpcwebtext:.
在vue中导入编译生成的文件并向后端发送请求
<template>
<div id="app">
<a-button type="primary" @click="get1">
简单rpc
</a-button>
<a-button type="primary" @click="get2">
服务端流rpc
</a-button>
</div>
</template>
<script>
// 引入grpc-web生成的客户端,请求和返回参数
import {HelloRequest, RepeatHelloRequest,HelloReply} from "./proto/helloworld_pb";
import { GreeterClient } from "./proto/helloworld_grpc_web_pb";
export default {
name: 'App',
created(){
// 创建grpc-web客户端,填入enovy的地址
this.client = new GreeterClient('http://localhost:8080',null, null)
},
methods: {
/**
* 简单rpc
*/
get1(){
// 创建请求参数并赋值
var request = new HelloRequest();
request.setName('World');
// 调用客户端相应的grpc方法,发送grpc请求,并接受后台发送回来的返回值
this.client.sayHello(request, {}, (err, response) => {
if (err) {
console.log(`Unexpected error for sayHello: code = ${err.code}` +
`, message = "${err.message}"`);
} else {
// 打印返回的信息
console.log(response.getMessage());
}
});
},
/**
* 服务端流rpc
*/
get2(){
// 创建请求参数并赋值
var streamRequest = new RepeatHelloRequest();
streamRequest.setName('World');
streamRequest.setCount(5);
// 调用客户端相应的grpc方法,发送grpc请求,并接受后台发送回来的返回值
var stream = this.client.sayRepeatHello(streamRequest, {});
stream.on('data', (response) => {
// 打印返回的信息
console.log(response.getMessage());
});
stream.on('error', (err) => {
console.log(`Unexpected stream error: code = ${err.code}` +
`, message = "${err.message}"`);
});
},
}
}
</script>
<style>
</style>
配置envoy代理
admin:
access_log_path: /tmp/admin_access.log
address:
socket_address: { address: 0.0.0.0, port_value: 9901 }
static_resources:
listeners:
- name: listener_0
address:
socket_address: { address: 0.0.0.0, port_value: 8080 }
filter_chains:
- filters:
- name: envoy.filters.network.http_connection_manager
typed_config:
"@type": type.googleapis.com/envoy.config.filter.network.http_connection_manager.v2.HttpConnectionManager
codec_type: auto
stat_prefix: ingress_http
route_config:
name: local_route
virtual_hosts:
- name: local_service
domains: ["*"]
routes:
- match: { prefix: "/" }
route:
cluster: greeter_service
max_grpc_timeout: 0s
cors:
allow_origin_string_match:
- prefix: "*"
allow_methods: GET, PUT, DELETE, POST, OPTIONS
allow_headers: keep-alive,user-agent,cache-control,content-type,content-transfer-encoding,custom-header-1,x-accept-content-transfer-encoding,x-accept-response-streaming,x-user-agent,x-grpc-web,grpc-timeout
max_age: "1728000"
expose_headers: custom-header-1,grpc-status,grpc-message
http_filters:
- name: envoy.filters.http.grpc_web
- name: envoy.filters.http.cors
- name: envoy.filters.http.router
clusters:
- name: greeter_service
connect_timeout: 0.25s
type: logical_dns
http2_protocol_options: {}
lb_policy: round_robin
#win/mac hosts: Use address: host.docker.internal instead of address: localhost in the line below
load_assignment:
cluster_name: cluster_0
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: 0.0.0.0
port_value: 9090