thanks nginx 对于 grpc support
安装 nginx
安装pcre
- 安装g++ 编译工具 yum install gcc-c++
C语言编写的库。安装就好
下载地址挑选合适的版本(一般选最新的版本) https://sourceforge.net/projects/pcre/files/pcre/8.43/
wget https://sourceforge.net/projects/pcre/files/pcre/8.43/pcre-8.43.tar.gz
./configure
make && make install
下载nginx最新源码包
下载 wget http://nginx.org/download/nginx-1.6.2.tar.gz
解压 tar zxvf nginx-1.6.2.tar.gz
cd nginx-1.6.2
编译
./configure --prefix=目录/nginx --with-http_stub_status_module --with-http_ssl_module --with-http_v2_module等需要安装的nginx模块
安装
make
make install
或者使用openresty
https://openresty.org/cn/download.html
集成的模块更多,如果没有什么特殊需求、个人推荐使用这个
测试nginx是否安装成功
目录/nginx/sbin -t
查看结果有successful即成功
目录/nginx/sbin -s reload
访问nginx页面,自己为例就是localhost 看到欢迎页面即可
修改nginx配置文件
- 参考配置 https://nginx.org/en/docs/http/ngx_http_grpc_module.html
- nginx 需要配置http_ssl和http_v2模块
server {
listen 80 http2;
server_name 域名可选项;
location / {
grpc_pass grpc://127.0.0.1:9090;
}
}
//利用nginx做负载均衡
upstream upback {
server 127.0.0.1:9090;
server 127.0.0.1:9091;
}
server {
listen 80 http2;
server_name 域名可选项;
location / {
grpc_pass grpc://upback;
}
}
重启然后编写客户端和服务端代码
- 定义proto文件,语法我在之前文章已经介绍过
syntax = "proto3";
option java_package = "com.xiao.proto.bean";
option java_outer_classname = "StudentProtos";
service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
message HelloRequest {
string name = 1;
}
message HelloReply {
string message = 1;
}
- gradle项目配置文件
buildscript {
dependencies {
classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.9'
}
}
plugins {
id 'java'
id "com.google.protobuf" version "0.8.9"
}
group 'com.xiao'
version '1.0-SNAPSHOT'
sourceCompatibility = 1.8
targetCompatibility = 1.8
dependencies {
implementation 'io.grpc:grpc-netty-shaded:1.21.0'
implementation 'io.grpc:grpc-protobuf:1.21.0'
implementation 'io.grpc:grpc-stub:1.21.0'
implementation 'io.netty:netty-all:4.1.34.Final'
implementation 'com.google.protobuf:protobuf-java:3.6.1'
}
protobuf {
generateProtoTasks.generatedFilesBaseDir = "src"
protoc {
artifact = "com.google.protobuf:protoc:3.6.1"
}
plugins {
grpc {
artifact = 'io.grpc:protoc-gen-grpc-java:1.21.0'
}
}
generateProtoTasks {
all()*.plugins {
grpc {
outputSubDir = 'java'
}
}
ofSourceSet('main')
}
}
sourceSets {
main {
proto {
srcDir 'src/main/proto'
}
}
}
生成配置 gradle clean generateProto
- Maven配置
<dependencies>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-netty-shaded</artifactId>
<version>1.23.0</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-protobuf</artifactId>
<version>1.23.0</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-stub</artifactId>
<version>1.23.0</version>
</dependency>
</dependencies>
<build>
<extensions>
<extension>
<groupId>kr.motd.maven</groupId>
<artifactId>os-maven-plugin</artifactId>
<version>1.5.0.Final</version>
</extension>
</extensions>
<plugins>
<plugin>
<groupId>org.xolstice.maven.plugins</groupId>
<artifactId>protobuf-maven-plugin</artifactId>
<version>0.5.1</version>
<configuration>
<protocArtifact>com.google.protobuf:protoc:3.9.0:exe:${os.detected.classifier}</protocArtifact>
<pluginId>grpc-java</pluginId>
<pluginArtifact>io.grpc:protoc-gen-grpc-java:1.23.0:exe:${os.detected.classifier}</pluginArtifact>
//修改输出目录
<outputDirectory>${basedir}/src/main/java</outputDirectory>
//这是重点不然每次都会删除之前的内容
<clearOutputDirectory>false</clearOutputDirectory>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>compile-custom</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
mvn clean package
服务端code
public class HelloWorldServer {
private static final Logger logger = Logger.getLogger(HelloWorldServer.class.getName());
private Server server;
private void start() throws IOException {
int port = 9090;
server = ServerBuilder.forPort(port)
.addService(new GreeterImpl())
.build()
.start();
logger.info("Server started, listening on " + port);
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
// Use stderr here since the logger may have been reset by its JVM shutdown hook.
System.err.println("*** shutting down gRPC server since JVM is shutting down");
HelloWorldServer.this.stop();
System.err.println("*** server shut down");
}));
}
private void stop() {
if (server != null) {
server.shutdown();
}
}
/**
* Await termination on the main thread since the grpc library uses daemon threads.
*/
private void blockUntilShutdown() throws InterruptedException {
if (server != null) {
server.awaitTermination();
}
}
/**
* Main launches the server from the command line.
*/
public static void main(String[] args) throws IOException, InterruptedException {
final HelloWorldServer server = new HelloWorldServer();
server.start();
server.blockUntilShutdown();
}
static class GreeterImpl extends GreeterGrpc.GreeterImplBase {
@Override
public void sayHello(HelloProto.HelloRequest req, StreamObserver<HelloProto.HelloReply> responseObserver) {
HelloProto.HelloReply reply = HelloProto.HelloReply.newBuilder().setMessage("Hello " + req.getName()).build();
responseObserver.onNext(reply);
responseObserver.onCompleted();
}
}
客户端code
public class HelloWorldClient {
public static void main(String[] args) {
ManagedChannel managedChannel = ManagedChannelBuilder.forTarget("域名").usePlaintext(true)
.build();
//同步处理请求
GreeterGrpc.GreeterBlockingStub greeterBlockingStub = GreeterGrpc.newBlockingStub(managedChannel);
HelloProto.HelloReply reply = greeterBlockingStub.sayHello(HelloProto.HelloRequest.newBuilder().setName("grpc-nginx").build());
System.out.println("============regret============:" + reply.getMessage());
}
}
如果是JAVA开发者,推荐将grpc交给Spring容器处理,例如SpringBoot