一.环境准备
java版本:jdk16
linux虚拟机(部署nacos)
nacos版本:2.0.3
开发工具:idea
二.新建父项目
pom文件:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.zjlab.grpc</groupId> <artifactId>grpcdemo</artifactId> <version>1.0-SNAPSHOT</version> <packaging>pom</packaging> <modules> <module>grpc-api</module> <module>user-server</module> <module>client</module> </modules> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.3.5.RELEASE</version> <relativePath/> </parent> <properties> <alibaba.version>2021.1</alibaba.version> <cloud.version>2020.0.4</cloud.version> </properties> <dependencies> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.20</version> <optional>true</optional> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-dependencies</artifactId> <version>${alibaba.version}</version> <type>pom</type> <scope>import</scope> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-dependencies --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Hoxton.SR8</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.4</version> </dependency <dependency> <groupId>net.devh</groupId> <artifactId>grpc-client-spring-boot-starter</artifactId> <version>2.10.1.RELEASE</version> </dependency> <dependency> <groupId>net.devh</groupId> <artifactId>grpc-server-spring-boot-starter</artifactId> <version>2.10.1.RELEASE</version> </dependency> </dependencies> </dependencyManagement> </project>
可以看到分布式项目中主要分为三个模块
1.grpc-api 提供grpc能力,主要用来将proto生成相应的java代码
2.user-server模块 用户模块,主要提供grpc-server能力
3.client模块 对外提供http接口,调用grpc-server,此模块作为grpc-client
扫描二维码关注公众号,回复: 15971677 查看本文章注意:lombok的版本要在1.18.20以上,否则编译报错(踩了坑)
三.新建grpc-api项目
pom文件:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <groupId>com.zjlab.grpc</groupId> <artifactId>grpcdemo</artifactId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <groupId>com.zjlab.grpc</groupId> <artifactId>grpc-api</artifactId> <properties> <maven.compiler.source>16</maven.compiler.source> <maven.compiler.target>16</maven.compiler.target> </properties> <dependencies> <dependency> <groupId>net.devh</groupId> <artifactId>grpc-server-spring-boot-starter</artifactId> </dependency> </dependencies> <build> <extensions> <extension> <groupId>kr.motd.maven</groupId> <artifactId>os-maven-plugin</artifactId> <version>1.6.2</version> </extension> </extensions> <plugins> <plugin> <groupId>org.xolstice.maven.plugins</groupId> <artifactId>protobuf-maven-plugin</artifactId> <version>0.6.1</version> <configuration> <protocArtifact>com.google.protobuf:protoc:3.12.0:exe:${os.detected.classifier}</protocArtifact> <pluginId>grpc-java</pluginId> <pluginArtifact>io.grpc:protoc-gen-grpc-java:1.34.1:exe:${os.detected.classifier}</pluginArtifact> <!--设置grpc生成代码到指定路径--> <outputDirectory>${project.basedir}/src/main/java</outputDirectory> <!--生成代码前是否清空目录--> <clearOutputDirectory>false</clearOutputDirectory> </configuration> <executions> <execution> <goals> <goal>compile</goal> <goal>compile-custom</goal> </goals> </execution> </executions> </plugin> <!-- 设置多个源文件夹 --> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>build-helper-maven-plugin</artifactId> <version>3.0.0</version> <executions> <!-- 添加主源码目录 --> <execution> <id>add-source</id> <phase>generate-sources</phase> <goals> <goal>add-source</goal> </goals> <configuration> <sources> <source>${project.basedir}/src/main/gen</source> <source>${project.basedir}/src/main/java</source> </sources> </configuration> </execution> </executions> </plugin> </plugins> </build> </project>
编写proto:
syntax = "proto3"; option java_multiple_files = true; package com.zjlab.grpc.proto; // 问好类 service Greeter { // 问候方法 rpc SayHello (HelloRequest) returns (HelloReply); } // 请求类 message HelloRequest { string name = 1; } // 回应类 message HelloReply { string message = 1; }
指定了将proto编译成java代码的输出路径和proto中的package相同
接下来就是安装proto的idea插件:
执行完compile命令即可生成文件
注意:如果编译报以下错误(mac电脑m1芯片,又是踩坑):
需要在maven里做如下配置
<profile> <id>apple-silicon</id> <properties> <os.detected.classifier>osx-x86_64</os.detected.classifier> </properties> </profile> <activeProfiles> <activeProfile>apple-silicon</activeProfile> <!-- 与 上面的profile 中的id对应 --> </activeProfiles>
四.新建user-server项目
结构:
pom文件:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <groupId>com.zjlab.grpc</groupId> <artifactId>grpcdemo</artifactId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>user-server</artifactId> <properties> <maven.compiler.source>16</maven.compiler.source> <maven.compiler.target>16</maven.compiler.target> </properties> <dependencies> <dependency> <groupId>net.devh</groupId> <artifactId>grpc-server-spring-boot-starter</artifactId> </dependency> <dependency> <groupId>net.devh</groupId> <artifactId>grpc-client-spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.12.0</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-autoconfigure</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <dependency> <groupId>com.zjlab.grpc</groupId> <artifactId>grpc-api</artifactId> <version>1.0-SNAPSHOT</version> <scope>compile</scope> </dependency> </dependencies> </project>
GreetImpl:package com.zjlab.grpc.user.impl; import com.zjlab.grpc.proto.GreeterGrpc; import com.zjlab.grpc.proto.HelloReply; import com.zjlab.grpc.proto.HelloRequest; import io.grpc.stub.StreamObserver; import net.devh.boot.grpc.server.service.GrpcService; /** * @author bing.bai * @create 2022/6/28 */ @GrpcService public class GreetImpl extends GreeterGrpc.GreeterImplBase { @Override public void sayHello(HelloRequest req, StreamObserver<HelloReply> responseObserver) { HelloReply reply = HelloReply.newBuilder().setMessage(("Hello " + req.getName())).build(); responseObserver.onNext(reply); responseObserver.onCompleted(); System.out.println("Message from gRPC-Client:" + req.getName()); } }
ServerApplication:package com.zjlab.grpc.user; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; /** * @author bing.bai * @create 2022/6/28 */ @SpringBootApplication public class ServerApplication { public static void main(String[] args) { SpringApplication.run(ServerApplication.class, args); } }
yml:
grpc: client: GLOBAL: negotiation-type: plaintext enable-keep-alive: true keep-alive-without-calls: true server: port: 7777 server: port: 8081 spring: application: name: springcloud-nacos-grpc-server profiles: active: dev cloud: nacos: discovery: server-addr: 10.101.116.3:8999 enabled: true namespace: grpc config: enabled: false
五.新建client项目
结构:
pom文件:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>grpcdemo</artifactId> <groupId>com.zjlab.grpc</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>client</artifactId> <properties> <maven.compiler.source>16</maven.compiler.source> <maven.compiler.target>16</maven.compiler.target> </properties> <dependencies> <dependency> <groupId>net.devh</groupId> <artifactId>grpc-client-spring-boot-starter</artifactId> </dependency> <dependency> <groupId>net.devh</groupId> <artifactId>grpc-server-spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.12.0</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-autoconfigure</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> <version>${alibaba.version}</version> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> <version>${alibaba.version}</version> </dependency> <dependency> <groupId>com.zjlab.grpc</groupId> <artifactId>grpc-api</artifactId> <version>1.0-SNAPSHOT</version> <scope>compile</scope> </dependency> </dependencies> </project>
controller:
package com.zjlab.client.controller; import com.zjlab.grpc.proto.GreeterGrpc; import com.zjlab.grpc.proto.HelloReply; import com.zjlab.grpc.proto.HelloRequest; import lombok.extern.slf4j.Slf4j; import net.devh.boot.grpc.client.inject.GrpcClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; /** * @author bing.bai * @create 2022/6/28 */ @RestController @Slf4j public class GreetController { @GrpcClient("springcloud-nacos-grpc-server") GreeterGrpc.GreeterBlockingStub greeterStub; @GetMapping(value="greet") public String greet( String str) { HelloReply helloReply = null; System.out.println(str); try { helloReply = greeterStub.sayHello( HelloRequest.newBuilder().setName(str).build() ); return helloReply.toString(); } catch (Exception e) { log.info("ex{}",e); } return helloReply.toString(); } }
注意:最好不要在controller里写业务代码,这里是偷懒
ClientApplication:
package com.zjlab.client;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @author bing.bai
* @create 2022/6/28
*/
@SpringBootApplication
public class ClientApplication {
public static void main(String[] args) {
SpringApplication.run(ClientApplication.class, args);
}
}
yml:
grpc:
server:
port: 7778
client:
springcloud-nacos-grpc-server:
negotiation-type: plaintext
enable-keep-alive: true
keep-alive-without-calls: true
server:
port: 8089
spring:
application:
name: springcloud-nacos-grpc-client
profiles:
active: dev
cloud:
nacos:
discovery:
server-addr: 10.101.116.3:8999
namespace: grpc
config:
enabled: false
六.调试
启动user-server和client服务
可以看到nacos上注册了这两个服务
接下来调用接口:http://localhost:8089/greet?str=1
服务端打印日志:
困惑:不知道为什么 negotiation-type: plaintext 这个配置用GLOBAL不生效,一定要指定服务名