├── .mvn └── wrapper │ ├── maven-wrapper.jar │ ├── maven-wrapper.properties │ └── MavenWrapperDownloader.java ├── spring-boot-istio-server ├── src │ └── main │ │ ├── resources │ │ └── application.yml │ │ └── java │ │ └── site │ │ └── wendev │ │ └── spring │ │ └── boot │ │ └── istio │ │ └── server │ │ ├── HelloServerApplication.java │ │ ├── configuraton │ │ ├── GrpcCommandLineRunner.java │ │ └── GrpcServerConfiguration.java │ │ └── service │ │ └── HelloServiceImpl.java ├── Dockerfile └── pom.xml ├── spring-boot-istio-client ├── src │ └── main │ │ ├── resources │ │ └── application.yml │ │ └── java │ │ └── site │ │ └── wendev │ │ └── spring │ │ └── boot │ │ └── istio │ │ └── client │ │ ├── HelloClientApplication.java │ │ ├── configuration │ │ ├── GrpcClientCommandLineRunner.java │ │ └── GrpcClientConfiguration.java │ │ └── controller │ │ └── HelloController.java ├── Dockerfile └── pom.xml ├── spring-boot-istio-api ├── src │ └── main │ │ ├── proto │ │ └── hello.proto │ │ └── java │ │ └── site │ │ └── wendev │ │ └── spring │ │ └── boot │ │ └── istio │ │ └── client │ │ └── api │ │ ├── HelloWorldGrpc.java │ │ └── HelloWorldService.java └── pom.xml ├── .gitignore ├── prod ├── ingress.yml ├── istio-gateway.yml ├── spring-boot-istio-client.yml └── spring-boot-istio-server.yml ├── pom.xml ├── mvnw.cmd ├── mvnw └── README.md /.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenDev/spring-boot-istio-demo/HEAD/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /spring-boot-istio-server/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 18080 3 | spring: 4 | application: 5 | name: spring-boot-istio-server 6 | grpc: 7 | server-port: 18888 8 | -------------------------------------------------------------------------------- /spring-boot-istio-client/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 19090 3 | spring: 4 | application: 5 | name: spring-boot-istio-client 6 | server-host: ${server-host} 7 | server-port: ${server-port} -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar 3 | -------------------------------------------------------------------------------- /spring-boot-istio-server/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM openjdk:8u121-jdk 2 | RUN /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \ 3 | && echo 'Asia/Shanghai' >/etc/timezone 4 | ADD /target/spring-boot-istio-server-0.0.1-SNAPSHOT.jar / 5 | ENV SERVER_PORT="18080" 6 | ENTRYPOINT java -jar /spring-boot-istio-server-0.0.1-SNAPSHOT.jar 7 | -------------------------------------------------------------------------------- /spring-boot-istio-api/src/main/proto/hello.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option java_package = "site.wendev.spring.boot.istio.api"; 4 | option java_outer_classname = "HelloWorldService"; 5 | 6 | package helloworld; 7 | 8 | service HelloWorld { 9 | rpc SayHello (HelloRequest) returns (HelloResponse) {} 10 | } 11 | 12 | message HelloRequest { 13 | string name = 1; 14 | } 15 | 16 | message HelloResponse { 17 | string message = 1; 18 | } 19 | -------------------------------------------------------------------------------- /spring-boot-istio-client/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM openjdk:8u121-jdk 2 | RUN /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \ 3 | && echo 'Asia/Shanghai' >/etc/timezone 4 | ADD /target/spring-boot-istio-client-0.0.1-SNAPSHOT.jar / 5 | ENV GRPC_SERVER_HOST="spring-boot-istio-server" 6 | ENV GRPC_SERVER_PORT="18888" 7 | ENTRYPOINT java -jar /spring-boot-istio-client-0.0.1-SNAPSHOT.jar \ 8 | --server-host=$GRPC_SERVER_HOST \ 9 | --server-port=$GRPC_SERVER_PORT 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/** 5 | !**/src/test/** 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | 30 | ### VS Code ### 31 | .vscode/ 32 | -------------------------------------------------------------------------------- /spring-boot-istio-client/src/main/java/site/wendev/spring/boot/istio/client/HelloClientApplication.java: -------------------------------------------------------------------------------- 1 | package site.wendev.spring.boot.istio.client; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | /** 7 | * @author 江文 8 | * @date 2020/4/12 3:06 下午 9 | */ 10 | @SpringBootApplication 11 | public class HelloClientApplication { 12 | public static void main(String[] args) { 13 | SpringApplication.run(HelloClientApplication.class, args); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /spring-boot-istio-server/src/main/java/site/wendev/spring/boot/istio/server/HelloServerApplication.java: -------------------------------------------------------------------------------- 1 | package site.wendev.spring.boot.istio.server; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | /** 7 | * @author 江文 8 | * @date 2020/4/12 2:48 下午 9 | */ 10 | @SpringBootApplication 11 | public class HelloServerApplication { 12 | public static void main(String[] args) { 13 | SpringApplication.run(HelloServerApplication.class, args); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /prod/ingress.yml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.k8s.io/v1beta1 2 | kind: Ingress 3 | metadata: 4 | name: nginx-web 5 | annotations: 6 | kubernetes.io/ingress.class: "nginx" 7 | nginx.ingress.kubernetes.io/use-reges: "true" 8 | nginx.ingress.kubernetes.io/proxy-connect-timeout: "600" 9 | nginx.ingress.kubernetes.io/proxy-send-timeout: "600" 10 | nginx.ingress.kubernetes.io/proxy-read-timeout: "600" 11 | nginx.ingress.kubernetes.io/proxy-body-size: "10m" 12 | nginx.ingress.kubernetes.io/rewrite-target: / 13 | spec: 14 | rules: 15 | - host: dev.wendev.site 16 | http: 17 | paths: 18 | - path: / 19 | backend: 20 | serviceName: spring-boot-istio-client 21 | servicePort: 19090 -------------------------------------------------------------------------------- /prod/istio-gateway.yml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.istio.io/v1alpha3 2 | kind: Gateway 3 | metadata: 4 | name: spring-boot-istio-gateway 5 | spec: 6 | selector: 7 | istio: ingressgateway 8 | servers: 9 | - port: 10 | number: 80 11 | name: http 12 | protocol: HTTP 13 | hosts: 14 | - "*" 15 | --- 16 | apiVersion: networking.istio.io/v1alpha3 17 | kind: VirtualService 18 | metadata: 19 | name: spring-boot-istio 20 | spec: 21 | hosts: 22 | - "*" 23 | gateways: 24 | - spring-boot-istio-gateway 25 | http: 26 | - match: 27 | - uri: 28 | exact: /hello 29 | route: 30 | - destination: 31 | host: spring-boot-istio-client 32 | port: 33 | number: 19090 34 | -------------------------------------------------------------------------------- /spring-boot-istio-server/src/main/java/site/wendev/spring/boot/istio/server/configuraton/GrpcCommandLineRunner.java: -------------------------------------------------------------------------------- 1 | package site.wendev.spring.boot.istio.server.configuraton; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.boot.CommandLineRunner; 5 | import org.springframework.stereotype.Component; 6 | 7 | /** 8 | * 加入gRPC的启动、停止等逻辑到Spring Boot的生命周期中 9 | * 10 | * @author 江文 11 | * @date 2020/4/12 3:10 下午 12 | */ 13 | @Component 14 | public class GrpcCommandLineRunner implements CommandLineRunner { 15 | @Autowired 16 | GrpcServerConfiguration configuration; 17 | 18 | @Override 19 | public void run(String... args) throws Exception { 20 | configuration.start(); 21 | configuration.block(); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /prod/spring-boot-istio-client.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: spring-boot-istio-client 5 | spec: 6 | type: ClusterIP 7 | ports: 8 | - name: http 9 | port: 19090 10 | targetPort: 19090 11 | selector: 12 | app: spring-boot-istio-client 13 | --- 14 | apiVersion: apps/v1 15 | kind: Deployment 16 | metadata: 17 | name: spring-boot-istio-client 18 | spec: 19 | replicas: 1 20 | selector: 21 | matchLabels: 22 | app: spring-boot-istio-client 23 | template: 24 | metadata: 25 | labels: 26 | app: spring-boot-istio-client 27 | spec: 28 | containers: 29 | - name: spring-boot-istio-client 30 | image: wendev-docker.pkg.coding.net/develop/docker/spring-boot-istio-client:0.0.1-SNAPSHOT 31 | imagePullPolicy: Always 32 | tty: true 33 | ports: 34 | - name: http 35 | protocol: TCP 36 | containerPort: 19090 37 | -------------------------------------------------------------------------------- /prod/spring-boot-istio-server.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: spring-boot-istio-server 5 | spec: 6 | type: ClusterIP 7 | ports: 8 | - name: http 9 | port: 18080 10 | targetPort: 18080 11 | - name: grpc 12 | port: 18888 13 | targetPort: 18888 14 | selector: 15 | app: spring-boot-istio-server 16 | --- 17 | apiVersion: apps/v1 18 | kind: Deployment 19 | metadata: 20 | name: spring-boot-istio-server 21 | spec: 22 | replicas: 1 23 | selector: 24 | matchLabels: 25 | app: spring-boot-istio-server 26 | template: 27 | metadata: 28 | labels: 29 | app: spring-boot-istio-server 30 | spec: 31 | containers: 32 | - name: spring-boot-istio-server 33 | image: wendev-docker.pkg.coding.net/develop/docker/spring-boot-istio-server:0.0.1-SNAPSHOT 34 | imagePullPolicy: Always 35 | tty: true 36 | ports: 37 | - name: http 38 | protocol: TCP 39 | containerPort: 18080 40 | - name: grpc 41 | protocol: TCP 42 | containerPort: 18888 43 | -------------------------------------------------------------------------------- /spring-boot-istio-client/src/main/java/site/wendev/spring/boot/istio/client/configuration/GrpcClientCommandLineRunner.java: -------------------------------------------------------------------------------- 1 | package site.wendev.spring.boot.istio.client.configuration; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.boot.CommandLineRunner; 6 | import org.springframework.stereotype.Component; 7 | 8 | import java.util.concurrent.TimeUnit; 9 | 10 | /** 11 | * 加入gRPC Client的启动、停止等逻辑到Spring Boot生命周期中 12 | * 13 | * @author 江文 14 | * @date 2020/4/12 3:36 下午 15 | */ 16 | @Component 17 | @Slf4j 18 | public class GrpcClientCommandLineRunner implements CommandLineRunner { 19 | @Autowired 20 | GrpcClientConfiguration configuration; 21 | 22 | @Override 23 | public void run(String... args) { 24 | // 开启gRPC客户端 25 | configuration.start(); 26 | 27 | // 添加客户端关闭的逻辑 28 | Runtime.getRuntime().addShutdownHook(new Thread(() -> { 29 | try { 30 | configuration.shutdown(); 31 | } catch (InterruptedException e) { 32 | e.printStackTrace(); 33 | } 34 | })); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /spring-boot-istio-server/src/main/java/site/wendev/spring/boot/istio/server/service/HelloServiceImpl.java: -------------------------------------------------------------------------------- 1 | package site.wendev.spring.boot.istio.server.service; 2 | 3 | import io.grpc.stub.StreamObserver; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.springframework.stereotype.Component; 6 | import site.wendev.spring.boot.istio.client.api.HelloWorldGrpc; 7 | import site.wendev.spring.boot.istio.client.api.HelloWorldService; 8 | 9 | /** 10 | * 服务端业务逻辑实现 11 | * 12 | * @author 江文 13 | * @date 2020/4/12 2:49 下午 14 | */ 15 | @Slf4j 16 | @Component 17 | public class HelloServiceImpl extends HelloWorldGrpc.HelloWorldImplBase { 18 | @Override 19 | public void sayHello(HelloWorldService.HelloRequest request, 20 | StreamObserver responseObserver) { 21 | // 根据请求对象建立响应对象,返回响应信息 22 | HelloWorldService.HelloResponse response = HelloWorldService.HelloResponse 23 | .newBuilder() 24 | .setMessage(String.format("Hello, %s. This message comes from gRPC.", request.getName())) 25 | .build(); 26 | responseObserver.onNext(response); 27 | responseObserver.onCompleted(); 28 | log.info("Client Message Received:[{}]", request.getName()); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /spring-boot-istio-client/src/main/java/site/wendev/spring/boot/istio/client/controller/HelloController.java: -------------------------------------------------------------------------------- 1 | package site.wendev.spring.boot.istio.client.controller; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.web.bind.annotation.*; 6 | import site.wendev.spring.boot.istio.client.api.HelloWorldService; 7 | import site.wendev.spring.boot.istio.client.configuration.GrpcClientConfiguration; 8 | 9 | /** 10 | * 客户端业务逻辑实现 11 | * 12 | * @author 江文 13 | * @date 2020/4/12 3:26 下午 14 | */ 15 | @RestController 16 | @Slf4j 17 | public class HelloController { 18 | @Autowired 19 | GrpcClientConfiguration configuration; 20 | 21 | @GetMapping("/hello") 22 | public String hello(@RequestParam(name = "name", defaultValue = "JiangWen", required = false) String name) { 23 | // 构建一个请求 24 | HelloWorldService.HelloRequest request = HelloWorldService.HelloRequest 25 | .newBuilder() 26 | .setName(name) 27 | .build(); 28 | 29 | // 使用stub发送请求至服务端 30 | HelloWorldService.HelloResponse response = configuration.getStub().sayHello(request); 31 | log.info("Server response received: [{}]", response.getMessage()); 32 | return response.getMessage(); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /spring-boot-istio-client/src/main/java/site/wendev/spring/boot/istio/client/configuration/GrpcClientConfiguration.java: -------------------------------------------------------------------------------- 1 | package site.wendev.spring.boot.istio.client.configuration; 2 | 3 | import io.grpc.ManagedChannel; 4 | import io.grpc.ManagedChannelBuilder; 5 | import lombok.extern.slf4j.Slf4j; 6 | import org.springframework.beans.factory.annotation.Value; 7 | import org.springframework.stereotype.Component; 8 | import site.wendev.spring.boot.istio.client.api.HelloWorldGrpc; 9 | 10 | import java.util.concurrent.TimeUnit; 11 | 12 | /** 13 | * gRPC Client的配置——启动、建立channel、获取stub、关闭等 14 | * 需要注册为Spring Bean 15 | * 16 | * @author 江文 17 | * @date 2020/4/12 3:27 下午 18 | */ 19 | @Slf4j 20 | @Component 21 | public class GrpcClientConfiguration { 22 | /** gRPC Server的地址 */ 23 | @Value("${server-host}") 24 | private String host; 25 | 26 | /** gRPC Server的端口 */ 27 | @Value("${server-port}") 28 | private int port; 29 | 30 | private ManagedChannel channel; 31 | private HelloWorldGrpc.HelloWorldBlockingStub stub; 32 | 33 | public void start() { 34 | // 开启channel 35 | channel = ManagedChannelBuilder.forAddress(host, port).usePlaintext().build(); 36 | 37 | // 通过channel获取到服务端的stub 38 | stub = HelloWorldGrpc.newBlockingStub(channel); 39 | log.info("gRPC client started, server address: {}:{}", host, port); 40 | } 41 | 42 | public void shutdown() throws InterruptedException { 43 | // 调用shutdown方法后等待1秒关闭channel 44 | channel.shutdown().awaitTermination(1, TimeUnit.SECONDS); 45 | log.info("gRPC client shut down successfully."); 46 | } 47 | 48 | public HelloWorldGrpc.HelloWorldBlockingStub getStub() { 49 | return this.stub; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | spring-boot-istio-api 7 | spring-boot-istio-server 8 | spring-boot-istio-client 9 | 10 | 11 | org.springframework.boot 12 | spring-boot-starter-parent 13 | 2.2.6.RELEASE 14 | 15 | 16 | site.wendev 17 | spring-boot-istio 18 | 0.0.1-SNAPSHOT 19 | spring-boot-istio 20 | Demo project for Spring Boot With Istio. 21 | pom 22 | 23 | 24 | 1.8 25 | 26 | 27 | 28 | 29 | 30 | io.grpc 31 | grpc-all 32 | 1.28.1 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /spring-boot-istio-server/src/main/java/site/wendev/spring/boot/istio/server/configuraton/GrpcServerConfiguration.java: -------------------------------------------------------------------------------- 1 | package site.wendev.spring.boot.istio.server.configuraton; 2 | 3 | import io.grpc.Server; 4 | import io.grpc.ServerBuilder; 5 | import lombok.extern.slf4j.Slf4j; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.beans.factory.annotation.Value; 8 | import org.springframework.stereotype.Component; 9 | import site.wendev.spring.boot.istio.server.service.HelloServiceImpl; 10 | 11 | import java.io.IOException; 12 | 13 | /** 14 | * gRPC Server的配置——启动、关闭等 15 | * 需要使用@Component注解注册为一个Spring Bean 16 | * 17 | * @author 江文 18 | * @date 2020/4/12 2:56 下午 19 | */ 20 | @Slf4j 21 | @Component 22 | public class GrpcServerConfiguration { 23 | @Autowired 24 | HelloServiceImpl service; 25 | 26 | /** 注入配置文件中的端口信息 */ 27 | @Value("${grpc.server-port}") 28 | private int port; 29 | private Server server; 30 | 31 | public void start() throws IOException { 32 | // 构建服务端 33 | log.info("Starting gRPC on port {}.", port); 34 | server = ServerBuilder.forPort(port).addService(service).build().start(); 35 | log.info("gRPC server started, listening on {}.", port); 36 | 37 | // 添加服务端关闭的逻辑 38 | Runtime.getRuntime().addShutdownHook(new Thread(() -> { 39 | log.info("Shutting down gRPC server."); 40 | GrpcServerConfiguration.this.stop(); 41 | log.info("gRPC server shut down successfully."); 42 | })); 43 | } 44 | 45 | private void stop() { 46 | if (server != null) { 47 | // 关闭服务端 48 | server.shutdown(); 49 | } 50 | } 51 | 52 | public void block() throws InterruptedException { 53 | if (server != null) { 54 | // 服务端启动后直到应用关闭都处于阻塞状态,方便接收请求 55 | server.awaitTermination(); 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /spring-boot-istio-api/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | spring-boot-istio 7 | site.wendev 8 | 0.0.1-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | spring-boot-istio-api 13 | 14 | 15 | 16 | io.grpc 17 | grpc-all 18 | 19 | 20 | javax.annotation 21 | javax.annotation-api 22 | 1.3.2 23 | 24 | 25 | 26 | 27 | 28 | 29 | kr.motd.maven 30 | os-maven-plugin 31 | 1.6.2 32 | 33 | 34 | 35 | 36 | org.xolstice.maven.plugins 37 | protobuf-maven-plugin 38 | 0.6.1 39 | 40 | com.google.protobuf:protoc:3.11.3:exe:${os.detected.classifier} 41 | grpc-java 42 | io.grpc:protoc-gen-grpc-java:1.28.1:exe:${os.detected.classifier} 43 | /Users/jiangwen/tools/protoc-3.11.3/bin/protoc 44 | 45 | 46 | 47 | 48 | compile 49 | compile-custom 50 | 51 | 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /spring-boot-istio-client/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | spring-boot-istio 7 | site.wendev 8 | 0.0.1-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | spring-boot-istio-client 13 | 14 | 15 | 16 | site.wendev 17 | spring-boot-istio-api 18 | 0.0.1-SNAPSHOT 19 | 20 | 21 | 22 | org.springframework.boot 23 | spring-boot-starter-actuator 24 | 25 | 26 | org.springframework.boot 27 | spring-boot-starter-web 28 | 29 | 30 | 31 | org.springframework.boot 32 | spring-boot-devtools 33 | runtime 34 | true 35 | 36 | 37 | org.projectlombok 38 | lombok 39 | true 40 | 41 | 42 | org.springframework.boot 43 | spring-boot-starter-test 44 | test 45 | 46 | 47 | org.junit.vintage 48 | junit-vintage-engine 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | org.springframework.boot 58 | spring-boot-maven-plugin 59 | 60 | true 61 | 62 | 63 | 64 | com.spotify 65 | dockerfile-maven-plugin 66 | 1.4.13 67 | 68 | 69 | javax.activation 70 | activation 71 | 1.1 72 | 73 | 74 | 75 | 76 | default 77 | 78 | build 79 | push 80 | 81 | 82 | 83 | 84 | wendev-docker.pkg.coding.net/develop/docker/${project.artifactId} 85 | 86 | ${project.version} 87 | 88 | ${project.build.finalName}.jar 89 | 90 | 91 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /spring-boot-istio-server/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | spring-boot-istio 7 | site.wendev 8 | 0.0.1-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | spring-boot-istio-server 13 | 14 | 1.8 15 | 16 | 17 | 18 | 19 | site.wendev 20 | spring-boot-istio-api 21 | 0.0.1-SNAPSHOT 22 | 23 | 24 | 25 | org.springframework.boot 26 | spring-boot-starter-actuator 27 | 28 | 29 | org.springframework.boot 30 | spring-boot-starter-web 31 | 32 | 33 | 34 | org.springframework.boot 35 | spring-boot-devtools 36 | runtime 37 | true 38 | 39 | 40 | org.projectlombok 41 | lombok 42 | true 43 | 44 | 45 | org.springframework.boot 46 | spring-boot-starter-test 47 | test 48 | 49 | 50 | org.junit.vintage 51 | junit-vintage-engine 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | org.springframework.boot 61 | spring-boot-maven-plugin 62 | 63 | true 64 | 65 | 66 | 67 | com.spotify 68 | dockerfile-maven-plugin 69 | 1.4.13 70 | 71 | 72 | javax.activation 73 | activation 74 | 1.1 75 | 76 | 77 | 78 | 79 | default 80 | 81 | build 82 | push 83 | 84 | 85 | 86 | 87 | wendev-docker.pkg.coding.net/develop/docker/${project.artifactId} 88 | 89 | ${project.version} 90 | 91 | ${project.build.finalName}.jar 92 | 93 | 94 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /.mvn/wrapper/MavenWrapperDownloader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2007-present the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import java.net.*; 18 | import java.io.*; 19 | import java.nio.channels.*; 20 | import java.util.Properties; 21 | 22 | public class MavenWrapperDownloader { 23 | 24 | private static final String WRAPPER_VERSION = "0.5.6"; 25 | /** 26 | * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided. 27 | */ 28 | private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/" 29 | + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar"; 30 | 31 | /** 32 | * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to 33 | * use instead of the default one. 34 | */ 35 | private static final String MAVEN_WRAPPER_PROPERTIES_PATH = 36 | ".mvn/wrapper/maven-wrapper.properties"; 37 | 38 | /** 39 | * Path where the maven-wrapper.jar will be saved to. 40 | */ 41 | private static final String MAVEN_WRAPPER_JAR_PATH = 42 | ".mvn/wrapper/maven-wrapper.jar"; 43 | 44 | /** 45 | * Name of the property which should be used to override the default download url for the wrapper. 46 | */ 47 | private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl"; 48 | 49 | public static void main(String args[]) { 50 | System.out.println("- Downloader started"); 51 | File baseDirectory = new File(args[0]); 52 | System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath()); 53 | 54 | // If the maven-wrapper.properties exists, read it and check if it contains a custom 55 | // wrapperUrl parameter. 56 | File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH); 57 | String url = DEFAULT_DOWNLOAD_URL; 58 | if (mavenWrapperPropertyFile.exists()) { 59 | FileInputStream mavenWrapperPropertyFileInputStream = null; 60 | try { 61 | mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile); 62 | Properties mavenWrapperProperties = new Properties(); 63 | mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream); 64 | url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url); 65 | } catch (IOException e) { 66 | System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'"); 67 | } finally { 68 | try { 69 | if (mavenWrapperPropertyFileInputStream != null) { 70 | mavenWrapperPropertyFileInputStream.close(); 71 | } 72 | } catch (IOException e) { 73 | // Ignore ... 74 | } 75 | } 76 | } 77 | System.out.println("- Downloading from: " + url); 78 | 79 | File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); 80 | if (!outputFile.getParentFile().exists()) { 81 | if (!outputFile.getParentFile().mkdirs()) { 82 | System.out.println( 83 | "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'"); 84 | } 85 | } 86 | System.out.println("- Downloading to: " + outputFile.getAbsolutePath()); 87 | try { 88 | downloadFileFromURL(url, outputFile); 89 | System.out.println("Done"); 90 | System.exit(0); 91 | } catch (Throwable e) { 92 | System.out.println("- Error downloading"); 93 | e.printStackTrace(); 94 | System.exit(1); 95 | } 96 | } 97 | 98 | private static void downloadFileFromURL(String urlString, File destination) throws Exception { 99 | if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) { 100 | String username = System.getenv("MVNW_USERNAME"); 101 | char[] password = System.getenv("MVNW_PASSWORD").toCharArray(); 102 | Authenticator.setDefault(new Authenticator() { 103 | @Override 104 | protected PasswordAuthentication getPasswordAuthentication() { 105 | return new PasswordAuthentication(username, password); 106 | } 107 | }); 108 | } 109 | URL website = new URL(urlString); 110 | ReadableByteChannel rbc; 111 | rbc = Channels.newChannel(website.openStream()); 112 | FileOutputStream fos = new FileOutputStream(destination); 113 | fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); 114 | fos.close(); 115 | rbc.close(); 116 | } 117 | 118 | } 119 | -------------------------------------------------------------------------------- /mvnw.cmd: -------------------------------------------------------------------------------- 1 | @REM ---------------------------------------------------------------------------- 2 | @REM Licensed to the Apache Software Foundation (ASF) under one 3 | @REM or more contributor license agreements. See the NOTICE file 4 | @REM distributed with this work for additional information 5 | @REM regarding copyright ownership. The ASF licenses this file 6 | @REM to you under the Apache License, Version 2.0 (the 7 | @REM "License"); you may not use this file except in compliance 8 | @REM with the License. You may obtain a copy of the License at 9 | @REM 10 | @REM https://www.apache.org/licenses/LICENSE-2.0 11 | @REM 12 | @REM Unless required by applicable law or agreed to in writing, 13 | @REM software distributed under the License is distributed on an 14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | @REM KIND, either express or implied. See the License for the 16 | @REM specific language governing permissions and limitations 17 | @REM under the License. 18 | @REM ---------------------------------------------------------------------------- 19 | 20 | @REM ---------------------------------------------------------------------------- 21 | @REM Maven Start Up Batch script 22 | @REM 23 | @REM Required ENV vars: 24 | @REM JAVA_HOME - location of a JDK home dir 25 | @REM 26 | @REM Optional ENV vars 27 | @REM M2_HOME - location of maven2's installed home dir 28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands 29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending 30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven 31 | @REM e.g. to debug Maven itself, use 32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files 34 | @REM ---------------------------------------------------------------------------- 35 | 36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' 37 | @echo off 38 | @REM set title of command window 39 | title %0 40 | @REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' 41 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% 42 | 43 | @REM set %HOME% to equivalent of $HOME 44 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") 45 | 46 | @REM Execute a user defined script before this one 47 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre 48 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending 49 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" 50 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" 51 | :skipRcPre 52 | 53 | @setlocal 54 | 55 | set ERROR_CODE=0 56 | 57 | @REM To isolate internal variables from possible post scripts, we use another setlocal 58 | @setlocal 59 | 60 | @REM ==== START VALIDATION ==== 61 | if not "%JAVA_HOME%" == "" goto OkJHome 62 | 63 | echo. 64 | echo Error: JAVA_HOME not found in your environment. >&2 65 | echo Please set the JAVA_HOME variable in your environment to match the >&2 66 | echo location of your Java installation. >&2 67 | echo. 68 | goto error 69 | 70 | :OkJHome 71 | if exist "%JAVA_HOME%\bin\java.exe" goto init 72 | 73 | echo. 74 | echo Error: JAVA_HOME is set to an invalid directory. >&2 75 | echo JAVA_HOME = "%JAVA_HOME%" >&2 76 | echo Please set the JAVA_HOME variable in your environment to match the >&2 77 | echo location of your Java installation. >&2 78 | echo. 79 | goto error 80 | 81 | @REM ==== END VALIDATION ==== 82 | 83 | :init 84 | 85 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn". 86 | @REM Fallback to current working directory if not found. 87 | 88 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% 89 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir 90 | 91 | set EXEC_DIR=%CD% 92 | set WDIR=%EXEC_DIR% 93 | :findBaseDir 94 | IF EXIST "%WDIR%"\.mvn goto baseDirFound 95 | cd .. 96 | IF "%WDIR%"=="%CD%" goto baseDirNotFound 97 | set WDIR=%CD% 98 | goto findBaseDir 99 | 100 | :baseDirFound 101 | set MAVEN_PROJECTBASEDIR=%WDIR% 102 | cd "%EXEC_DIR%" 103 | goto endDetectBaseDir 104 | 105 | :baseDirNotFound 106 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR% 107 | cd "%EXEC_DIR%" 108 | 109 | :endDetectBaseDir 110 | 111 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig 112 | 113 | @setlocal EnableExtensions EnableDelayedExpansion 114 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a 115 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% 116 | 117 | :endReadAdditionalConfig 118 | 119 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" 120 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" 121 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 122 | 123 | set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" 124 | 125 | FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( 126 | IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B 127 | ) 128 | 129 | @REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central 130 | @REM This allows using the maven wrapper in projects that prohibit checking in binary data. 131 | if exist %WRAPPER_JAR% ( 132 | if "%MVNW_VERBOSE%" == "true" ( 133 | echo Found %WRAPPER_JAR% 134 | ) 135 | ) else ( 136 | if not "%MVNW_REPOURL%" == "" ( 137 | SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" 138 | ) 139 | if "%MVNW_VERBOSE%" == "true" ( 140 | echo Couldn't find %WRAPPER_JAR%, downloading it ... 141 | echo Downloading from: %DOWNLOAD_URL% 142 | ) 143 | 144 | powershell -Command "&{"^ 145 | "$webclient = new-object System.Net.WebClient;"^ 146 | "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ 147 | "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ 148 | "}"^ 149 | "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ 150 | "}" 151 | if "%MVNW_VERBOSE%" == "true" ( 152 | echo Finished downloading %WRAPPER_JAR% 153 | ) 154 | ) 155 | @REM End of extension 156 | 157 | @REM Provide a "standardized" way to retrieve the CLI args that will 158 | @REM work with both Windows and non-Windows executions. 159 | set MAVEN_CMD_LINE_ARGS=%* 160 | 161 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* 162 | if ERRORLEVEL 1 goto error 163 | goto end 164 | 165 | :error 166 | set ERROR_CODE=1 167 | 168 | :end 169 | @endlocal & set ERROR_CODE=%ERROR_CODE% 170 | 171 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost 172 | @REM check for post script, once with legacy .bat ending and once with .cmd ending 173 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" 174 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" 175 | :skipRcPost 176 | 177 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' 178 | if "%MAVEN_BATCH_PAUSE%" == "on" pause 179 | 180 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% 181 | 182 | exit /B %ERROR_CODE% 183 | -------------------------------------------------------------------------------- /mvnw: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # ---------------------------------------------------------------------------- 3 | # Licensed to the Apache Software Foundation (ASF) under one 4 | # or more contributor license agreements. See the NOTICE file 5 | # distributed with this work for additional information 6 | # regarding copyright ownership. The ASF licenses this file 7 | # to you under the Apache License, Version 2.0 (the 8 | # "License"); you may not use this file except in compliance 9 | # with the License. You may obtain a copy of the License at 10 | # 11 | # https://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, 14 | # software distributed under the License is distributed on an 15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | # KIND, either express or implied. See the License for the 17 | # specific language governing permissions and limitations 18 | # under the License. 19 | # ---------------------------------------------------------------------------- 20 | 21 | # ---------------------------------------------------------------------------- 22 | # Maven Start Up Batch script 23 | # 24 | # Required ENV vars: 25 | # ------------------ 26 | # JAVA_HOME - location of a JDK home dir 27 | # 28 | # Optional ENV vars 29 | # ----------------- 30 | # M2_HOME - location of maven2's installed home dir 31 | # MAVEN_OPTS - parameters passed to the Java VM when running Maven 32 | # e.g. to debug Maven itself, use 33 | # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 34 | # MAVEN_SKIP_RC - flag to disable loading of mavenrc files 35 | # ---------------------------------------------------------------------------- 36 | 37 | if [ -z "$MAVEN_SKIP_RC" ]; then 38 | 39 | if [ -f /etc/mavenrc ]; then 40 | . /etc/mavenrc 41 | fi 42 | 43 | if [ -f "$HOME/.mavenrc" ]; then 44 | . "$HOME/.mavenrc" 45 | fi 46 | 47 | fi 48 | 49 | # OS specific support. $var _must_ be set to either true or false. 50 | cygwin=false 51 | darwin=false 52 | mingw=false 53 | case "$(uname)" in 54 | CYGWIN*) cygwin=true ;; 55 | MINGW*) mingw=true ;; 56 | Darwin*) 57 | darwin=true 58 | # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home 59 | # See https://developer.apple.com/library/mac/qa/qa1170/_index.html 60 | if [ -z "$JAVA_HOME" ]; then 61 | if [ -x "/usr/libexec/java_home" ]; then 62 | export JAVA_HOME="$(/usr/libexec/java_home)" 63 | else 64 | export JAVA_HOME="/Library/Java/Home" 65 | fi 66 | fi 67 | ;; 68 | esac 69 | 70 | if [ -z "$JAVA_HOME" ]; then 71 | if [ -r /etc/gentoo-release ]; then 72 | JAVA_HOME=$(java-config --jre-home) 73 | fi 74 | fi 75 | 76 | if [ -z "$M2_HOME" ]; then 77 | ## resolve links - $0 may be a link to maven's home 78 | PRG="$0" 79 | 80 | # need this for relative symlinks 81 | while [ -h "$PRG" ]; do 82 | ls=$(ls -ld "$PRG") 83 | link=$(expr "$ls" : '.*-> \(.*\)$') 84 | if expr "$link" : '/.*' >/dev/null; then 85 | PRG="$link" 86 | else 87 | PRG="$(dirname "$PRG")/$link" 88 | fi 89 | done 90 | 91 | saveddir=$(pwd) 92 | 93 | M2_HOME=$(dirname "$PRG")/.. 94 | 95 | # make it fully qualified 96 | M2_HOME=$(cd "$M2_HOME" && pwd) 97 | 98 | cd "$saveddir" 99 | # echo Using m2 at $M2_HOME 100 | fi 101 | 102 | # For Cygwin, ensure paths are in UNIX format before anything is touched 103 | if $cygwin; then 104 | [ -n "$M2_HOME" ] && 105 | M2_HOME=$(cygpath --unix "$M2_HOME") 106 | [ -n "$JAVA_HOME" ] && 107 | JAVA_HOME=$(cygpath --unix "$JAVA_HOME") 108 | [ -n "$CLASSPATH" ] && 109 | CLASSPATH=$(cygpath --path --unix "$CLASSPATH") 110 | fi 111 | 112 | # For Mingw, ensure paths are in UNIX format before anything is touched 113 | if $mingw; then 114 | [ -n "$M2_HOME" ] && 115 | M2_HOME="$( ( 116 | cd "$M2_HOME" 117 | pwd 118 | ))" 119 | [ -n "$JAVA_HOME" ] && 120 | JAVA_HOME="$( ( 121 | cd "$JAVA_HOME" 122 | pwd 123 | ))" 124 | fi 125 | 126 | if [ -z "$JAVA_HOME" ]; then 127 | javaExecutable="$(which javac)" 128 | if [ -n "$javaExecutable" ] && ! [ "$(expr \"$javaExecutable\" : '\([^ ]*\)')" = "no" ]; then 129 | # readlink(1) is not available as standard on Solaris 10. 130 | readLink=$(which readlink) 131 | if [ ! $(expr "$readLink" : '\([^ ]*\)') = "no" ]; then 132 | if $darwin; then 133 | javaHome="$(dirname \"$javaExecutable\")" 134 | javaExecutable="$(cd \"$javaHome\" && pwd -P)/javac" 135 | else 136 | javaExecutable="$(readlink -f \"$javaExecutable\")" 137 | fi 138 | javaHome="$(dirname \"$javaExecutable\")" 139 | javaHome=$(expr "$javaHome" : '\(.*\)/bin') 140 | JAVA_HOME="$javaHome" 141 | export JAVA_HOME 142 | fi 143 | fi 144 | fi 145 | 146 | if [ -z "$JAVACMD" ]; then 147 | if [ -n "$JAVA_HOME" ]; then 148 | if [ -x "$JAVA_HOME/jre/sh/java" ]; then 149 | # IBM's JDK on AIX uses strange locations for the executables 150 | JAVACMD="$JAVA_HOME/jre/sh/java" 151 | else 152 | JAVACMD="$JAVA_HOME/bin/java" 153 | fi 154 | else 155 | JAVACMD="$(which java)" 156 | fi 157 | fi 158 | 159 | if [ ! -x "$JAVACMD" ]; then 160 | echo "Error: JAVA_HOME is not defined correctly." >&2 161 | echo " We cannot execute $JAVACMD" >&2 162 | exit 1 163 | fi 164 | 165 | if [ -z "$JAVA_HOME" ]; then 166 | echo "Warning: JAVA_HOME environment variable is not set." 167 | fi 168 | 169 | CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher 170 | 171 | # traverses directory structure from process work directory to filesystem root 172 | # first directory with .mvn subdirectory is considered project base directory 173 | find_maven_basedir() { 174 | 175 | if [ -z "$1" ]; then 176 | echo "Path not specified to find_maven_basedir" 177 | return 1 178 | fi 179 | 180 | basedir="$1" 181 | wdir="$1" 182 | while [ "$wdir" != '/' ]; do 183 | if [ -d "$wdir"/.mvn ]; then 184 | basedir=$wdir 185 | break 186 | fi 187 | # workaround for JBEAP-8937 (on Solaris 10/Sparc) 188 | if [ -d "${wdir}" ]; then 189 | wdir=$( 190 | cd "$wdir/.." 191 | pwd 192 | ) 193 | fi 194 | # end of workaround 195 | done 196 | echo "${basedir}" 197 | } 198 | 199 | # concatenates all lines of a file 200 | concat_lines() { 201 | if [ -f "$1" ]; then 202 | echo "$(tr -s '\n' ' ' <"$1")" 203 | fi 204 | } 205 | 206 | BASE_DIR=$(find_maven_basedir "$(pwd)") 207 | if [ -z "$BASE_DIR" ]; then 208 | exit 1 209 | fi 210 | 211 | ########################################################################################## 212 | # Extension to allow automatically downloading the maven-wrapper.jar from Maven-central 213 | # This allows using the maven wrapper in projects that prohibit checking in binary data. 214 | ########################################################################################## 215 | if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then 216 | if [ "$MVNW_VERBOSE" = true ]; then 217 | echo "Found .mvn/wrapper/maven-wrapper.jar" 218 | fi 219 | else 220 | if [ "$MVNW_VERBOSE" = true ]; then 221 | echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." 222 | fi 223 | if [ -n "$MVNW_REPOURL" ]; then 224 | jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" 225 | else 226 | jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" 227 | fi 228 | while IFS="=" read key value; do 229 | case "$key" in wrapperUrl) 230 | jarUrl="$value" 231 | break 232 | ;; 233 | esac 234 | done <"$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" 235 | if [ "$MVNW_VERBOSE" = true ]; then 236 | echo "Downloading from: $jarUrl" 237 | fi 238 | wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" 239 | if $cygwin; then 240 | wrapperJarPath=$(cygpath --path --windows "$wrapperJarPath") 241 | fi 242 | 243 | if command -v wget >/dev/null; then 244 | if [ "$MVNW_VERBOSE" = true ]; then 245 | echo "Found wget ... using wget" 246 | fi 247 | if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then 248 | wget "$jarUrl" -O "$wrapperJarPath" 249 | else 250 | wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" 251 | fi 252 | elif command -v curl >/dev/null; then 253 | if [ "$MVNW_VERBOSE" = true ]; then 254 | echo "Found curl ... using curl" 255 | fi 256 | if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then 257 | curl -o "$wrapperJarPath" "$jarUrl" -f 258 | else 259 | curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f 260 | fi 261 | 262 | else 263 | if [ "$MVNW_VERBOSE" = true ]; then 264 | echo "Falling back to using Java to download" 265 | fi 266 | javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" 267 | # For Cygwin, switch paths to Windows format before running javac 268 | if $cygwin; then 269 | javaClass=$(cygpath --path --windows "$javaClass") 270 | fi 271 | if [ -e "$javaClass" ]; then 272 | if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then 273 | if [ "$MVNW_VERBOSE" = true ]; then 274 | echo " - Compiling MavenWrapperDownloader.java ..." 275 | fi 276 | # Compiling the Java class 277 | ("$JAVA_HOME/bin/javac" "$javaClass") 278 | fi 279 | if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then 280 | # Running the downloader 281 | if [ "$MVNW_VERBOSE" = true ]; then 282 | echo " - Running MavenWrapperDownloader.java ..." 283 | fi 284 | ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") 285 | fi 286 | fi 287 | fi 288 | fi 289 | ########################################################################################## 290 | # End of extension 291 | ########################################################################################## 292 | 293 | export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} 294 | if [ "$MVNW_VERBOSE" = true ]; then 295 | echo $MAVEN_PROJECTBASEDIR 296 | fi 297 | MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" 298 | 299 | # For Cygwin, switch paths to Windows format before running java 300 | if $cygwin; then 301 | [ -n "$M2_HOME" ] && 302 | M2_HOME=$(cygpath --path --windows "$M2_HOME") 303 | [ -n "$JAVA_HOME" ] && 304 | JAVA_HOME=$(cygpath --path --windows "$JAVA_HOME") 305 | [ -n "$CLASSPATH" ] && 306 | CLASSPATH=$(cygpath --path --windows "$CLASSPATH") 307 | [ -n "$MAVEN_PROJECTBASEDIR" ] && 308 | MAVEN_PROJECTBASEDIR=$(cygpath --path --windows "$MAVEN_PROJECTBASEDIR") 309 | fi 310 | 311 | # Provide a "standardized" way to retrieve the CLI args that will 312 | # work with both Windows and non-Windows executions. 313 | MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" 314 | export MAVEN_CMD_LINE_ARGS 315 | 316 | WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 317 | 318 | exec "$JAVACMD" \ 319 | $MAVEN_OPTS \ 320 | -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ 321 | "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ 322 | ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" 323 | -------------------------------------------------------------------------------- /spring-boot-istio-api/src/main/java/site/wendev/spring/boot/istio/client/api/HelloWorldGrpc.java: -------------------------------------------------------------------------------- 1 | package site.wendev.spring.boot.istio.client.api; 2 | 3 | import static io.grpc.MethodDescriptor.generateFullMethodName; 4 | import static io.grpc.stub.ClientCalls.asyncUnaryCall; 5 | import static io.grpc.stub.ClientCalls.blockingServerStreamingCall; 6 | import static io.grpc.stub.ClientCalls.blockingUnaryCall; 7 | import static io.grpc.stub.ClientCalls.futureUnaryCall; 8 | import static io.grpc.stub.ServerCalls.asyncUnaryCall; 9 | import static io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall; 10 | 11 | /** 12 | */ 13 | @javax.annotation.Generated( 14 | value = "by gRPC proto compiler (version 1.28.1)", 15 | comments = "Source: hello.proto") 16 | public final class HelloWorldGrpc { 17 | 18 | private HelloWorldGrpc() {} 19 | 20 | public static final String SERVICE_NAME = "helloworld.HelloWorld"; 21 | 22 | // Static method descriptors that strictly reflect the proto. 23 | private static volatile io.grpc.MethodDescriptor getSayHelloMethod; 25 | 26 | @io.grpc.stub.annotations.RpcMethod( 27 | fullMethodName = SERVICE_NAME + '/' + "SayHello", 28 | requestType = HelloWorldService.HelloRequest.class, 29 | responseType = HelloWorldService.HelloResponse.class, 30 | methodType = io.grpc.MethodDescriptor.MethodType.UNARY) 31 | public static io.grpc.MethodDescriptor getSayHelloMethod() { 33 | io.grpc.MethodDescriptor getSayHelloMethod; 34 | if ((getSayHelloMethod = HelloWorldGrpc.getSayHelloMethod) == null) { 35 | synchronized (HelloWorldGrpc.class) { 36 | if ((getSayHelloMethod = HelloWorldGrpc.getSayHelloMethod) == null) { 37 | HelloWorldGrpc.getSayHelloMethod = getSayHelloMethod = 38 | io.grpc.MethodDescriptor.newBuilder() 39 | .setType(io.grpc.MethodDescriptor.MethodType.UNARY) 40 | .setFullMethodName(generateFullMethodName(SERVICE_NAME, "SayHello")) 41 | .setSampledToLocalTracing(true) 42 | .setRequestMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( 43 | HelloWorldService.HelloRequest.getDefaultInstance())) 44 | .setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( 45 | HelloWorldService.HelloResponse.getDefaultInstance())) 46 | .setSchemaDescriptor(new HelloWorldMethodDescriptorSupplier("SayHello")) 47 | .build(); 48 | } 49 | } 50 | } 51 | return getSayHelloMethod; 52 | } 53 | 54 | /** 55 | * Creates a new async stub that supports all call types for the service 56 | */ 57 | public static HelloWorldStub newStub(io.grpc.Channel channel) { 58 | io.grpc.stub.AbstractStub.StubFactory factory = 59 | new io.grpc.stub.AbstractStub.StubFactory() { 60 | @java.lang.Override 61 | public HelloWorldStub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) { 62 | return new HelloWorldStub(channel, callOptions); 63 | } 64 | }; 65 | return HelloWorldStub.newStub(factory, channel); 66 | } 67 | 68 | /** 69 | * Creates a new blocking-style stub that supports unary and streaming output calls on the service 70 | */ 71 | public static HelloWorldBlockingStub newBlockingStub( 72 | io.grpc.Channel channel) { 73 | io.grpc.stub.AbstractStub.StubFactory factory = 74 | new io.grpc.stub.AbstractStub.StubFactory() { 75 | @java.lang.Override 76 | public HelloWorldBlockingStub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) { 77 | return new HelloWorldBlockingStub(channel, callOptions); 78 | } 79 | }; 80 | return HelloWorldBlockingStub.newStub(factory, channel); 81 | } 82 | 83 | /** 84 | * Creates a new ListenableFuture-style stub that supports unary calls on the service 85 | */ 86 | public static HelloWorldFutureStub newFutureStub( 87 | io.grpc.Channel channel) { 88 | io.grpc.stub.AbstractStub.StubFactory factory = 89 | new io.grpc.stub.AbstractStub.StubFactory() { 90 | @java.lang.Override 91 | public HelloWorldFutureStub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) { 92 | return new HelloWorldFutureStub(channel, callOptions); 93 | } 94 | }; 95 | return HelloWorldFutureStub.newStub(factory, channel); 96 | } 97 | 98 | /** 99 | */ 100 | public static abstract class HelloWorldImplBase implements io.grpc.BindableService { 101 | 102 | /** 103 | */ 104 | public void sayHello(HelloWorldService.HelloRequest request, 105 | io.grpc.stub.StreamObserver responseObserver) { 106 | asyncUnimplementedUnaryCall(getSayHelloMethod(), responseObserver); 107 | } 108 | 109 | @java.lang.Override public final io.grpc.ServerServiceDefinition bindService() { 110 | return io.grpc.ServerServiceDefinition.builder(getServiceDescriptor()) 111 | .addMethod( 112 | getSayHelloMethod(), 113 | asyncUnaryCall( 114 | new MethodHandlers< 115 | HelloWorldService.HelloRequest, 116 | HelloWorldService.HelloResponse>( 117 | this, METHODID_SAY_HELLO))) 118 | .build(); 119 | } 120 | } 121 | 122 | /** 123 | */ 124 | public static final class HelloWorldStub extends io.grpc.stub.AbstractAsyncStub { 125 | private HelloWorldStub( 126 | io.grpc.Channel channel, io.grpc.CallOptions callOptions) { 127 | super(channel, callOptions); 128 | } 129 | 130 | @java.lang.Override 131 | protected HelloWorldStub build( 132 | io.grpc.Channel channel, io.grpc.CallOptions callOptions) { 133 | return new HelloWorldStub(channel, callOptions); 134 | } 135 | 136 | /** 137 | */ 138 | public void sayHello(HelloWorldService.HelloRequest request, 139 | io.grpc.stub.StreamObserver responseObserver) { 140 | asyncUnaryCall( 141 | getChannel().newCall(getSayHelloMethod(), getCallOptions()), request, responseObserver); 142 | } 143 | } 144 | 145 | /** 146 | */ 147 | public static final class HelloWorldBlockingStub extends io.grpc.stub.AbstractBlockingStub { 148 | private HelloWorldBlockingStub( 149 | io.grpc.Channel channel, io.grpc.CallOptions callOptions) { 150 | super(channel, callOptions); 151 | } 152 | 153 | @java.lang.Override 154 | protected HelloWorldBlockingStub build( 155 | io.grpc.Channel channel, io.grpc.CallOptions callOptions) { 156 | return new HelloWorldBlockingStub(channel, callOptions); 157 | } 158 | 159 | /** 160 | */ 161 | public HelloWorldService.HelloResponse sayHello(HelloWorldService.HelloRequest request) { 162 | return blockingUnaryCall( 163 | getChannel(), getSayHelloMethod(), getCallOptions(), request); 164 | } 165 | } 166 | 167 | /** 168 | */ 169 | public static final class HelloWorldFutureStub extends io.grpc.stub.AbstractFutureStub { 170 | private HelloWorldFutureStub( 171 | io.grpc.Channel channel, io.grpc.CallOptions callOptions) { 172 | super(channel, callOptions); 173 | } 174 | 175 | @java.lang.Override 176 | protected HelloWorldFutureStub build( 177 | io.grpc.Channel channel, io.grpc.CallOptions callOptions) { 178 | return new HelloWorldFutureStub(channel, callOptions); 179 | } 180 | 181 | /** 182 | */ 183 | public com.google.common.util.concurrent.ListenableFuture sayHello( 184 | HelloWorldService.HelloRequest request) { 185 | return futureUnaryCall( 186 | getChannel().newCall(getSayHelloMethod(), getCallOptions()), request); 187 | } 188 | } 189 | 190 | private static final int METHODID_SAY_HELLO = 0; 191 | 192 | private static final class MethodHandlers implements 193 | io.grpc.stub.ServerCalls.UnaryMethod, 194 | io.grpc.stub.ServerCalls.ServerStreamingMethod, 195 | io.grpc.stub.ServerCalls.ClientStreamingMethod, 196 | io.grpc.stub.ServerCalls.BidiStreamingMethod { 197 | private final HelloWorldImplBase serviceImpl; 198 | private final int methodId; 199 | 200 | MethodHandlers(HelloWorldImplBase serviceImpl, int methodId) { 201 | this.serviceImpl = serviceImpl; 202 | this.methodId = methodId; 203 | } 204 | 205 | @java.lang.Override 206 | @java.lang.SuppressWarnings("unchecked") 207 | public void invoke(Req request, io.grpc.stub.StreamObserver responseObserver) { 208 | switch (methodId) { 209 | case METHODID_SAY_HELLO: 210 | serviceImpl.sayHello((HelloWorldService.HelloRequest) request, 211 | (io.grpc.stub.StreamObserver) responseObserver); 212 | break; 213 | default: 214 | throw new AssertionError(); 215 | } 216 | } 217 | 218 | @java.lang.Override 219 | @java.lang.SuppressWarnings("unchecked") 220 | public io.grpc.stub.StreamObserver invoke( 221 | io.grpc.stub.StreamObserver responseObserver) { 222 | switch (methodId) { 223 | default: 224 | throw new AssertionError(); 225 | } 226 | } 227 | } 228 | 229 | private static abstract class HelloWorldBaseDescriptorSupplier 230 | implements io.grpc.protobuf.ProtoFileDescriptorSupplier, io.grpc.protobuf.ProtoServiceDescriptorSupplier { 231 | HelloWorldBaseDescriptorSupplier() {} 232 | 233 | @java.lang.Override 234 | public com.google.protobuf.Descriptors.FileDescriptor getFileDescriptor() { 235 | return HelloWorldService.getDescriptor(); 236 | } 237 | 238 | @java.lang.Override 239 | public com.google.protobuf.Descriptors.ServiceDescriptor getServiceDescriptor() { 240 | return getFileDescriptor().findServiceByName("HelloWorld"); 241 | } 242 | } 243 | 244 | private static final class HelloWorldFileDescriptorSupplier 245 | extends HelloWorldBaseDescriptorSupplier { 246 | HelloWorldFileDescriptorSupplier() {} 247 | } 248 | 249 | private static final class HelloWorldMethodDescriptorSupplier 250 | extends HelloWorldBaseDescriptorSupplier 251 | implements io.grpc.protobuf.ProtoMethodDescriptorSupplier { 252 | private final String methodName; 253 | 254 | HelloWorldMethodDescriptorSupplier(String methodName) { 255 | this.methodName = methodName; 256 | } 257 | 258 | @java.lang.Override 259 | public com.google.protobuf.Descriptors.MethodDescriptor getMethodDescriptor() { 260 | return getServiceDescriptor().findMethodByName(methodName); 261 | } 262 | } 263 | 264 | private static volatile io.grpc.ServiceDescriptor serviceDescriptor; 265 | 266 | public static io.grpc.ServiceDescriptor getServiceDescriptor() { 267 | io.grpc.ServiceDescriptor result = serviceDescriptor; 268 | if (result == null) { 269 | synchronized (HelloWorldGrpc.class) { 270 | result = serviceDescriptor; 271 | if (result == null) { 272 | serviceDescriptor = result = io.grpc.ServiceDescriptor.newBuilder(SERVICE_NAME) 273 | .setSchemaDescriptor(new HelloWorldFileDescriptorSupplier()) 274 | .addMethod(getSayHelloMethod()) 275 | .build(); 276 | } 277 | } 278 | } 279 | return result; 280 | } 281 | } 282 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 使用Spring Boot+gRPC构建微服务并部署到Istio 2 | 3 | 作为`Service Mesh`和云原生技术的忠实拥护者,我却一直没有开发过Service Mesh的应用。正好最近受够了Spring Cloud的“折磨”,对Kubernetes也可以熟练使用了,而且网上几乎没有Spring Boot微服务部署到Istio的案例,我就开始考虑用Spring Boot写个微服务的Demo并且部署到Istio。项目本身不复杂,就是发送一个字符串并且返回一个字符串的最简单的Demo。 4 | 5 | > 题外话:我本来是想用Spring MVC写的——因为周围有的同学不相信Spring MVC也可以开发微服务,但是Spring MVC的各种配置和依赖问题把我整的想吐,为了少掉几根头发,还是用了方便好用的Spring Boot。 6 | 7 | **本项目的所有代码都上传到了GitHub,地址:** https://github.com/WenDev/spring-boot-istio-demo **如果有帮助的话不要吝啬你的Star和Fork呀,非常感谢~** 8 | 9 | ## 为什么要用Istio? 10 | 11 | 目前,对于Java技术栈来说,构建微服务的最佳选择是`Spring Boot`而Spring Boot一般搭配目前落地案例很多的微服务框架`Spring Cloud`来使用。 12 | 13 | Spring Cloud看似很完美,但是在实际上手开发后,很容易就会发现Spring Cloud存在以下比较严重的问题: 14 | 15 | - 服务治理相关的逻辑存在于Spring Cloud Netflix等SDK中,与业务代码紧密耦合。 16 | - SDK对业务代码侵入太大,SDK发生升级且无法向下兼容时,业务代码必须做出改变以适配SDK的升级——即使业务逻辑并没有发生任何变化。 17 | - 各种组件令人眼花缭乱,质量也参差不齐,学习成本太高,且组件之间代码很难完全复用,仅仅为了实现治理逻辑而学习SDK也并不是很好的选择。 18 | - 绑定于Java技术栈,虽然可以接入其他语言但要手动实现服务治理相关的逻辑,不符合微服务“可以用多种语言进行开发”的原则。 19 | - Spring Cloud仅仅是一个开发框架,没有实现微服务所必须的服务调度、资源分配等功能,这些需求要借助Kubernetes等平台来完成。但Spring Cloud与Kubernetes功能上有重合,且部分功能也存在冲突,二者很难完美配合。 20 | 21 | 替代Spring Cloud的选择有没有呢?有!它就是`Istio`。 22 | 23 | Istio彻底把治理逻辑从业务代码中剥离出来,成为了独立的进程(Sidecar)。部署时两者部署在一起,在一个Pod里共同运行,业务代码完全感知不到Sidecar的存在。这就实现了治理逻辑对业务代码的零侵入——实际上不仅是代码没有侵入,在运行时两者也没有任何的耦合。这使得不同的微服务完全可以使用不同语言、不同技术栈来开发,也不用担心服务治理问题,可以说这是一种很优雅的解决方案了。 24 | 25 | 所以,“为什么要使用Istio”这个问题也就迎刃而解了——因为Istio解决了传统微服务诸如业务逻辑与服务治理逻辑耦合、不能很好地实现跨语言等痛点,而且非常容易使用。只要会用Kubernetes,学习Istio的使用一点都不困难。 26 | 27 | ## 为什么要使用gRPC作为通信框架? 28 | 29 | 在微服务架构中,服务之间的通信是一个比较大的问题,一般采用RPC或者RESTful API来实现。 30 | 31 | Spring Boot可以使用`RestTemplate`调用远程服务,但这种方式不直观,代码也比较复杂,进行跨语言通信也是个比较大的问题;而`gRPC`相比Dubbo等常见的Java RPC框架更加轻量,使用起来也很方便,代码可读性高,并且与Istio和Kubernetes可以很好地进行整合,在Protobuf和HTTP2的加持下性能也还不错,所以这次选择了gRPC来解决Spring Boot微服务间通信的问题。并且,虽然gRPC没有服务发现、负载均衡等能力,但是Istio在这方面就非常强大,两者形成了完美的互补关系。 32 | 33 | 由于考虑到各种`grpc-spring-boot-starter`可能会对Spring Boot与Istio的整合产生不可知的副作用,所以这一次我没有用任何的`grpc-spring-boot-starter`,而是直接手写了gRPC与Spring Boot的整合。不想借助第三方框架整合gRPC和Spring Boot的可以简单参考一下我的实现。 34 | 35 | ## 编写业务代码 36 | 37 | 首先使用`Spring Initializr`建立父级项目`spring-boot-istio`,并引入`gRPC`的依赖。pom文件如下: 38 | 39 | ```xml 40 | 41 | 43 | 4.0.0 44 | 45 | spring-boot-istio-api 46 | spring-boot-istio-server 47 | spring-boot-istio-client 48 | 49 | 50 | org.springframework.boot 51 | spring-boot-starter-parent 52 | 2.2.6.RELEASE 53 | 54 | 55 | site.wendev 56 | spring-boot-istio 57 | 0.0.1-SNAPSHOT 58 | spring-boot-istio 59 | Demo project for Spring Boot With Istio. 60 | pom 61 | 62 | 63 | 1.8 64 | 65 | 66 | 67 | 68 | 69 | io.grpc 70 | grpc-all 71 | 1.28.1 72 | 73 | 74 | 75 | 76 | 77 | ``` 78 | 79 | 然后建立公共依赖模块`spring-boot-istio-api`,pom文件如下,主要就是gRPC的一些依赖: 80 | 81 | ```xml 82 | 83 | 86 | 87 | spring-boot-istio 88 | site.wendev 89 | 0.0.1-SNAPSHOT 90 | 91 | 4.0.0 92 | 93 | spring-boot-istio-api 94 | 95 | 96 | 97 | io.grpc 98 | grpc-all 99 | 100 | 101 | javax.annotation 102 | javax.annotation-api 103 | 1.3.2 104 | 105 | 106 | 107 | 108 | 109 | 110 | kr.motd.maven 111 | os-maven-plugin 112 | 1.6.2 113 | 114 | 115 | 116 | 117 | org.xolstice.maven.plugins 118 | protobuf-maven-plugin 119 | 0.6.1 120 | 121 | com.google.protobuf:protoc:3.11.3:exe:${os.detected.classifier} 122 | grpc-java 123 | io.grpc:protoc-gen-grpc-java:1.28.1:exe:${os.detected.classifier} 124 | /Users/jiangwen/tools/protoc-3.11.3/bin/protoc 125 | 126 | 127 | 128 | 129 | compile 130 | compile-custom 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | ``` 139 | 140 | 建立src/main/proto文件夹,在此文件夹下建立`hello.proto`,定义服务间的接口如下: 141 | 142 | ```protobuf 143 | syntax = "proto3"; 144 | 145 | option java_package = "site.wendev.spring.boot.istio.api"; 146 | option java_outer_classname = "HelloWorldService"; 147 | 148 | package helloworld; 149 | 150 | service HelloWorld { 151 | rpc SayHello (HelloRequest) returns (HelloResponse) {} 152 | } 153 | 154 | message HelloRequest { 155 | string name = 1; 156 | } 157 | 158 | message HelloResponse { 159 | string message = 1; 160 | } 161 | 162 | ``` 163 | 164 | 很简单,就是发送一个`name`返回一个带`name`的`message`。 165 | 166 | 然后生成服务端和客户端的代码,并且放到java文件夹下。这部分内容可以参考gRPC的官方文档。 167 | 168 | 有了API模块之后,就可以编写服务提供者(服务端)和服务消费者(客户端)了。这里我们重点看一下如何整合gRPC和Spring Boot。 169 | 170 | ### 服务端 171 | 172 | 业务代码非常简单: 173 | 174 | ```java 175 | /** 176 | * 服务端业务逻辑实现 177 | * 178 | * @author 江文 179 | * @date 2020/4/12 2:49 下午 180 | */ 181 | @Slf4j 182 | @Component 183 | public class HelloServiceImpl extends HelloWorldGrpc.HelloWorldImplBase { 184 | @Override 185 | public void sayHello(HelloWorldService.HelloRequest request, 186 | StreamObserver responseObserver) { 187 | // 根据请求对象建立响应对象,返回响应信息 188 | HelloWorldService.HelloResponse response = HelloWorldService.HelloResponse 189 | .newBuilder() 190 | .setMessage(String.format("Hello, %s. This message comes from gRPC.", request.getName())) 191 | .build(); 192 | responseObserver.onNext(response); 193 | responseObserver.onCompleted(); 194 | log.info("Client Message Received:[{}]", request.getName()); 195 | } 196 | } 197 | 198 | ``` 199 | 200 | 光有业务代码还不行,我们还需要在应用启动时把gRPC Server也给一起启动起来。首先写一下Server端的启动、关闭等逻辑: 201 | 202 | ```java 203 | /** 204 | * gRPC Server的配置——启动、关闭等 205 | * 需要使用@Component注解注册为一个Spring Bean 206 | * 207 | * @author 江文 208 | * @date 2020/4/12 2:56 下午 209 | */ 210 | @Slf4j 211 | @Component 212 | public class GrpcServerConfiguration { 213 | @Autowired 214 | HelloServiceImpl service; 215 | 216 | /** 注入配置文件中的端口信息 */ 217 | @Value("${grpc.server-port}") 218 | private int port; 219 | private Server server; 220 | 221 | public void start() throws IOException { 222 | // 构建服务端 223 | log.info("Starting gRPC on port {}.", port); 224 | server = ServerBuilder.forPort(port).addService(service).build().start(); 225 | log.info("gRPC server started, listening on {}.", port); 226 | 227 | // 添加服务端关闭的逻辑 228 | Runtime.getRuntime().addShutdownHook(new Thread(() -> { 229 | log.info("Shutting down gRPC server."); 230 | GrpcServerConfiguration.this.stop(); 231 | log.info("gRPC server shut down successfully."); 232 | })); 233 | } 234 | 235 | private void stop() { 236 | if (server != null) { 237 | // 关闭服务端 238 | server.shutdown(); 239 | } 240 | } 241 | 242 | public void block() throws InterruptedException { 243 | if (server != null) { 244 | // 服务端启动后直到应用关闭都处于阻塞状态,方便接收请求 245 | server.awaitTermination(); 246 | } 247 | } 248 | } 249 | 250 | ``` 251 | 252 | 定义好gRPC的启动、停止等逻辑后,就可以使用`CommandLineRunner`把它加入到Spring Boot的启动中去了: 253 | 254 | ```java 255 | /** 256 | * 加入gRPC Server的启动、停止等逻辑到Spring Boot的生命周期中 257 | * 258 | * @author 江文 259 | * @date 2020/4/12 3:10 下午 260 | */ 261 | @Component 262 | public class GrpcCommandLineRunner implements CommandLineRunner { 263 | @Autowired 264 | GrpcServerConfiguration configuration; 265 | 266 | @Override 267 | public void run(String... args) throws Exception { 268 | configuration.start(); 269 | configuration.block(); 270 | } 271 | } 272 | 273 | ``` 274 | 275 | 之所以要把gRPC的逻辑注册成Spring Bean,就是因为在这里要获取到它的实例并进行相应的操作。 276 | 277 | 这样,在启动Spring Boot时,由于CommandLineRunner的存在,gRPC服务端也就可以一同启动了。 278 | 279 | ### 客户端 280 | 281 | 业务代码同样非常简单: 282 | 283 | ```java 284 | /** 285 | * 客户端业务逻辑实现 286 | * 287 | * @author 江文 288 | * @date 2020/4/12 3:26 下午 289 | */ 290 | @RestController 291 | @Slf4j 292 | public class HelloController { 293 | @Autowired 294 | GrpcClientConfiguration configuration; 295 | 296 | @GetMapping("/hello") 297 | public String hello(@RequestParam(name = "name", defaultValue = "JiangWen", required = false) String name) { 298 | // 构建一个请求 299 | HelloWorldService.HelloRequest request = HelloWorldService.HelloRequest 300 | .newBuilder() 301 | .setName(name) 302 | .build(); 303 | 304 | // 使用stub发送请求至服务端 305 | HelloWorldService.HelloResponse response = configuration.getStub().sayHello(request); 306 | log.info("Server response received: [{}]", response.getMessage()); 307 | return response.getMessage(); 308 | } 309 | } 310 | 311 | ``` 312 | 313 | 在启动客户端时,我们需要打开gRPC的客户端,并获取到`channel`和`stub`以进行RPC通信,来看看gRPC客户端的实现逻辑: 314 | 315 | ```java 316 | /** 317 | * gRPC Client的配置——启动、建立channel、获取stub、关闭等 318 | * 需要注册为Spring Bean 319 | * 320 | * @author 江文 321 | * @date 2020/4/12 3:27 下午 322 | */ 323 | @Slf4j 324 | @Component 325 | public class GrpcClientConfiguration { 326 | /** gRPC Server的地址 */ 327 | @Value("${server-host}") 328 | private String host; 329 | 330 | /** gRPC Server的端口 */ 331 | @Value("${server-port}") 332 | private int port; 333 | 334 | private ManagedChannel channel; 335 | private HelloWorldGrpc.HelloWorldBlockingStub stub; 336 | 337 | public void start() { 338 | // 开启channel 339 | channel = ManagedChannelBuilder.forAddress(host, port).usePlaintext().build(); 340 | 341 | // 通过channel获取到服务端的stub 342 | stub = HelloWorldGrpc.newBlockingStub(channel); 343 | log.info("gRPC client started, server address: {}:{}", host, port); 344 | } 345 | 346 | public void shutdown() throws InterruptedException { 347 | // 调用shutdown方法后等待1秒关闭channel 348 | channel.shutdown().awaitTermination(1, TimeUnit.SECONDS); 349 | log.info("gRPC client shut down successfully."); 350 | } 351 | 352 | public HelloWorldGrpc.HelloWorldBlockingStub getStub() { 353 | return this.stub; 354 | } 355 | } 356 | 357 | ``` 358 | 359 | 比服务端要简单一些。 360 | 361 | 最后,仍然需要一个CommandLineRunner把这些启动逻辑加入到Spring Boot的启动过程中: 362 | 363 | ```java 364 | /** 365 | * 加入gRPC Client的启动、停止等逻辑到Spring Boot生命周期中 366 | * 367 | * @author 江文 368 | * @date 2020/4/12 3:36 下午 369 | */ 370 | @Component 371 | @Slf4j 372 | public class GrpcClientCommandLineRunner implements CommandLineRunner { 373 | @Autowired 374 | GrpcClientConfiguration configuration; 375 | 376 | @Override 377 | public void run(String... args) { 378 | // 开启gRPC客户端 379 | configuration.start(); 380 | 381 | // 添加客户端关闭的逻辑 382 | Runtime.getRuntime().addShutdownHook(new Thread(() -> { 383 | try { 384 | configuration.shutdown(); 385 | } catch (InterruptedException e) { 386 | e.printStackTrace(); 387 | } 388 | })); 389 | } 390 | } 391 | 392 | ``` 393 | 394 | ## 编写Dockerfile 395 | 396 | 业务代码跑通之后,就可以制作Docker镜像,准备部署到Istio中去了。 397 | 398 | 在开始编写Dockerfile之前,先改动一下客户端的配置文件: 399 | 400 | ```yaml 401 | server: 402 | port: 19090 403 | spring: 404 | application: 405 | name: spring-boot-istio-client 406 | server-host: ${server-host} 407 | server-port: ${server-port} 408 | 409 | ``` 410 | 411 | 接下来编写Dockerfile: 412 | 413 | 服务端: 414 | 415 | ```dockerfile 416 | FROM openjdk:8u121-jdk 417 | RUN /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \ 418 | && echo 'Asia/Shanghai' >/etc/timezone 419 | ADD /target/spring-boot-istio-server-0.0.1-SNAPSHOT.jar / 420 | ENV SERVER_PORT="18080" 421 | ENTRYPOINT java -jar /spring-boot-istio-server-0.0.1-SNAPSHOT.jar 422 | 423 | ``` 424 | 425 | 主要是规定服务端应用的端口为18080,并且在容器启动时让服务端也一起启动。 426 | 427 | 客户端: 428 | 429 | ```dockerfile 430 | FROM openjdk:8u121-jdk 431 | RUN /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \ 432 | && echo 'Asia/Shanghai' >/etc/timezone 433 | ADD /target/spring-boot-istio-client-0.0.1-SNAPSHOT.jar / 434 | ENV GRPC_SERVER_HOST="spring-boot-istio-server" 435 | ENV GRPC_SERVER_PORT="18888" 436 | ENTRYPOINT java -jar /spring-boot-istio-client-0.0.1-SNAPSHOT.jar \ 437 | --server-host=$GRPC_SERVER_HOST \ 438 | --server-port=$GRPC_SERVER_PORT 439 | 440 | ``` 441 | 442 | 可以看到这里添加了启动参数,配合前面的配置,当这个镜像部署到Kubernetes集群时,就可以在Kubernetes的配合之下通过服务名找到服务端了。 443 | 444 | 同时,服务端和客户端的pom文件中添加: 445 | 446 | ```xml 447 | 448 | 449 | 450 | org.springframework.boot 451 | spring-boot-maven-plugin 452 | 453 | true 454 | 455 | 456 | 457 | com.spotify 458 | dockerfile-maven-plugin 459 | 1.4.13 460 | 461 | 462 | javax.activation 463 | activation 464 | 1.1 465 | 466 | 467 | 468 | 469 | default 470 | 471 | build 472 | push 473 | 474 | 475 | 476 | 477 | wendev-docker.pkg.coding.net/develop/docker/${project.artifactId} 478 | 479 | ${project.version} 480 | 481 | ${project.build.finalName}.jar 482 | 483 | 484 | 485 | 486 | 487 | ``` 488 | 489 | 这样执行`mvn clean package`时就可以同时把docker镜像构建出来了。 490 | 491 | ## 编写部署文件 492 | 493 | 有了镜像之后,就可以写部署文件了: 494 | 495 | 服务端: 496 | 497 | ```yaml 498 | apiVersion: v1 499 | kind: Service 500 | metadata: 501 | name: spring-boot-istio-server 502 | spec: 503 | type: ClusterIP 504 | ports: 505 | - name: http 506 | port: 18080 507 | targetPort: 18080 508 | - name: grpc 509 | port: 18888 510 | targetPort: 18888 511 | selector: 512 | app: spring-boot-istio-server 513 | --- 514 | apiVersion: apps/v1 515 | kind: Deployment 516 | metadata: 517 | name: spring-boot-istio-server 518 | spec: 519 | replicas: 1 520 | selector: 521 | matchLabels: 522 | app: spring-boot-istio-server 523 | template: 524 | metadata: 525 | labels: 526 | app: spring-boot-istio-server 527 | spec: 528 | containers: 529 | - name: spring-boot-istio-server 530 | image: wendev-docker.pkg.coding.net/develop/docker/spring-boot-istio-server:0.0.1-SNAPSHOT 531 | imagePullPolicy: Always 532 | tty: true 533 | ports: 534 | - name: http 535 | protocol: TCP 536 | containerPort: 18080 537 | - name: grpc 538 | protocol: TCP 539 | containerPort: 18888 540 | 541 | ``` 542 | 543 | 主要是暴露服务端的端口:18080和gRPC Server的端口18888,以便可以从Pod外部访问服务端。 544 | 545 | 客户端: 546 | 547 | ```yaml 548 | apiVersion: v1 549 | kind: Service 550 | metadata: 551 | name: spring-boot-istio-client 552 | spec: 553 | type: ClusterIP 554 | ports: 555 | - name: http 556 | port: 19090 557 | targetPort: 19090 558 | selector: 559 | app: spring-boot-istio-client 560 | --- 561 | apiVersion: apps/v1 562 | kind: Deployment 563 | metadata: 564 | name: spring-boot-istio-client 565 | spec: 566 | replicas: 1 567 | selector: 568 | matchLabels: 569 | app: spring-boot-istio-client 570 | template: 571 | metadata: 572 | labels: 573 | app: spring-boot-istio-client 574 | spec: 575 | containers: 576 | - name: spring-boot-istio-client 577 | image: wendev-docker.pkg.coding.net/develop/docker/spring-boot-istio-client:0.0.1-SNAPSHOT 578 | imagePullPolicy: Always 579 | tty: true 580 | ports: 581 | - name: http 582 | protocol: TCP 583 | containerPort: 19090 584 | 585 | ``` 586 | 587 | 主要是暴露客户端的端口19090,以便访问客户端并调用服务端。 588 | 589 | 如果想先试试把它们部署到k8s可不可以正常访问,可以这样配置Ingress: 590 | 591 | ```yaml 592 | apiVersion: networking.k8s.io/v1beta1 593 | kind: Ingress 594 | metadata: 595 | name: nginx-web 596 | annotations: 597 | kubernetes.io/ingress.class: "nginx" 598 | nginx.ingress.kubernetes.io/use-reges: "true" 599 | nginx.ingress.kubernetes.io/proxy-connect-timeout: "600" 600 | nginx.ingress.kubernetes.io/proxy-send-timeout: "600" 601 | nginx.ingress.kubernetes.io/proxy-read-timeout: "600" 602 | nginx.ingress.kubernetes.io/proxy-body-size: "10m" 603 | nginx.ingress.kubernetes.io/rewrite-target: / 604 | spec: 605 | rules: 606 | - host: dev.wendev.site 607 | http: 608 | paths: 609 | - path: / 610 | backend: 611 | serviceName: spring-boot-istio-client 612 | servicePort: 19090 613 | ``` 614 | 615 | Istio的网关配置文件与k8s不大一样: 616 | 617 | ```yaml 618 | apiVersion: networking.istio.io/v1alpha3 619 | kind: Gateway 620 | metadata: 621 | name: spring-boot-istio-gateway 622 | spec: 623 | selector: 624 | istio: ingressgateway 625 | servers: 626 | - port: 627 | number: 80 628 | name: http 629 | protocol: HTTP 630 | hosts: 631 | - "*" 632 | --- 633 | apiVersion: networking.istio.io/v1alpha3 634 | kind: VirtualService 635 | metadata: 636 | name: spring-boot-istio 637 | spec: 638 | hosts: 639 | - "*" 640 | gateways: 641 | - spring-boot-istio-gateway 642 | http: 643 | - match: 644 | - uri: 645 | exact: /hello 646 | route: 647 | - destination: 648 | host: spring-boot-istio-client 649 | port: 650 | number: 19090 651 | 652 | ``` 653 | 654 | 主要就是暴露`/hello`这个路径,并且指定对应的服务和端口。 655 | 656 | ## 部署应用到Istio 657 | 658 | 首先搭建k8s集群并且安装istio。我使用的k8s版本是`1.16.0`,Istio版本是最新的`1.6.0-alpha.1`,使用`istioctl`命令安装Istio。建议跑通官方的`bookinfo`示例之后再来部署本项目。 659 | 660 | 注:以下命令都是在开启了自动注入Sidecar的前提下运行的 661 | 662 | 我是在虚拟机中运行的k8s,所以`istio-ingressgateway`没有外部ip: 663 | 664 | ```bash 665 | $ kubectl get svc istio-ingressgateway -n istio-system 666 | NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE 667 | istio-ingressgateway NodePort 10.97.158.232 15020:30388/TCP,80:31690/TCP,443:31493/TCP,15029:32182/TCP,15030:31724/TCP,15031:30887/TCP,15032:30369/TCP,31400:31122/TCP,15443:31545/TCP 26h 668 | ``` 669 | 670 | 所以,需要设置IP和端口,以NodePort的方式访问gateway: 671 | 672 | ```bash 673 | export INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http2")].nodePort}') 674 | export SECURE_INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="https")].nodePort}') 675 | export INGRESS_HOST=127.0.0.1 676 | export GATEWAY_URL=$INGRESS_HOST:$INGRESS_PORT 677 | ``` 678 | 679 | 这样就可以了。 680 | 681 | 接下来部署服务: 682 | 683 | ```bash 684 | $ kubectl apply -f spring-boot-istio-server.yml 685 | $ kubectl apply -f spring-boot-istio-client.yml 686 | $ kubectl apply -f istio-gateway.yml 687 | ``` 688 | 689 | 必须要等到两个pod全部变为Running而且Ready变为2/2才算部署完成。 690 | 691 | 接下来就可以通过 692 | 693 | ```bash 694 | curl -s http://${GATEWAY_URL}/hello 695 | ``` 696 | 697 | 访问到服务了。如果成功返回了`Hello, JiangWen. This message comes from gRPC.`的结果,没有出错则说明部署完成。 698 | 699 | -------------------------------------------------------------------------------- /spring-boot-istio-api/src/main/java/site/wendev/spring/boot/istio/client/api/HelloWorldService.java: -------------------------------------------------------------------------------- 1 | // Generated by the protocol buffer compiler. DO NOT EDIT! 2 | // source: hello.proto 3 | 4 | package site.wendev.spring.boot.istio.client.api; 5 | 6 | public final class HelloWorldService { 7 | private HelloWorldService() {} 8 | public static void registerAllExtensions( 9 | com.google.protobuf.ExtensionRegistryLite registry) { 10 | } 11 | 12 | public static void registerAllExtensions( 13 | com.google.protobuf.ExtensionRegistry registry) { 14 | registerAllExtensions( 15 | (com.google.protobuf.ExtensionRegistryLite) registry); 16 | } 17 | public interface HelloRequestOrBuilder extends 18 | // @@protoc_insertion_point(interface_extends:helloworld.HelloRequest) 19 | com.google.protobuf.MessageOrBuilder { 20 | 21 | /** 22 | * string name = 1; 23 | * @return The name. 24 | */ 25 | java.lang.String getName(); 26 | /** 27 | * string name = 1; 28 | * @return The bytes for name. 29 | */ 30 | com.google.protobuf.ByteString 31 | getNameBytes(); 32 | } 33 | /** 34 | * Protobuf type {@code helloworld.HelloRequest} 35 | */ 36 | public static final class HelloRequest extends 37 | com.google.protobuf.GeneratedMessageV3 implements 38 | // @@protoc_insertion_point(message_implements:helloworld.HelloRequest) 39 | HelloRequestOrBuilder { 40 | private static final long serialVersionUID = 0L; 41 | // Use HelloRequest.newBuilder() to construct. 42 | private HelloRequest(com.google.protobuf.GeneratedMessageV3.Builder builder) { 43 | super(builder); 44 | } 45 | private HelloRequest() { 46 | name_ = ""; 47 | } 48 | 49 | @java.lang.Override 50 | @SuppressWarnings({"unused"}) 51 | protected java.lang.Object newInstance( 52 | UnusedPrivateParameter unused) { 53 | return new HelloRequest(); 54 | } 55 | 56 | @java.lang.Override 57 | public final com.google.protobuf.UnknownFieldSet 58 | getUnknownFields() { 59 | return this.unknownFields; 60 | } 61 | private HelloRequest( 62 | com.google.protobuf.CodedInputStream input, 63 | com.google.protobuf.ExtensionRegistryLite extensionRegistry) 64 | throws com.google.protobuf.InvalidProtocolBufferException { 65 | this(); 66 | if (extensionRegistry == null) { 67 | throw new java.lang.NullPointerException(); 68 | } 69 | com.google.protobuf.UnknownFieldSet.Builder unknownFields = 70 | com.google.protobuf.UnknownFieldSet.newBuilder(); 71 | try { 72 | boolean done = false; 73 | while (!done) { 74 | int tag = input.readTag(); 75 | switch (tag) { 76 | case 0: 77 | done = true; 78 | break; 79 | case 10: { 80 | java.lang.String s = input.readStringRequireUtf8(); 81 | 82 | name_ = s; 83 | break; 84 | } 85 | default: { 86 | if (!parseUnknownField( 87 | input, unknownFields, extensionRegistry, tag)) { 88 | done = true; 89 | } 90 | break; 91 | } 92 | } 93 | } 94 | } catch (com.google.protobuf.InvalidProtocolBufferException e) { 95 | throw e.setUnfinishedMessage(this); 96 | } catch (java.io.IOException e) { 97 | throw new com.google.protobuf.InvalidProtocolBufferException( 98 | e).setUnfinishedMessage(this); 99 | } finally { 100 | this.unknownFields = unknownFields.build(); 101 | makeExtensionsImmutable(); 102 | } 103 | } 104 | public static final com.google.protobuf.Descriptors.Descriptor 105 | getDescriptor() { 106 | return HelloWorldService.internal_static_helloworld_HelloRequest_descriptor; 107 | } 108 | 109 | @java.lang.Override 110 | protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable 111 | internalGetFieldAccessorTable() { 112 | return HelloWorldService.internal_static_helloworld_HelloRequest_fieldAccessorTable 113 | .ensureFieldAccessorsInitialized( 114 | HelloWorldService.HelloRequest.class, HelloWorldService.HelloRequest.Builder.class); 115 | } 116 | 117 | public static final int NAME_FIELD_NUMBER = 1; 118 | private volatile java.lang.Object name_; 119 | /** 120 | * string name = 1; 121 | * @return The name. 122 | */ 123 | public java.lang.String getName() { 124 | java.lang.Object ref = name_; 125 | if (ref instanceof java.lang.String) { 126 | return (java.lang.String) ref; 127 | } else { 128 | com.google.protobuf.ByteString bs = 129 | (com.google.protobuf.ByteString) ref; 130 | java.lang.String s = bs.toStringUtf8(); 131 | name_ = s; 132 | return s; 133 | } 134 | } 135 | /** 136 | * string name = 1; 137 | * @return The bytes for name. 138 | */ 139 | public com.google.protobuf.ByteString 140 | getNameBytes() { 141 | java.lang.Object ref = name_; 142 | if (ref instanceof java.lang.String) { 143 | com.google.protobuf.ByteString b = 144 | com.google.protobuf.ByteString.copyFromUtf8( 145 | (java.lang.String) ref); 146 | name_ = b; 147 | return b; 148 | } else { 149 | return (com.google.protobuf.ByteString) ref; 150 | } 151 | } 152 | 153 | private byte memoizedIsInitialized = -1; 154 | @java.lang.Override 155 | public final boolean isInitialized() { 156 | byte isInitialized = memoizedIsInitialized; 157 | if (isInitialized == 1) return true; 158 | if (isInitialized == 0) return false; 159 | 160 | memoizedIsInitialized = 1; 161 | return true; 162 | } 163 | 164 | @java.lang.Override 165 | public void writeTo(com.google.protobuf.CodedOutputStream output) 166 | throws java.io.IOException { 167 | if (!getNameBytes().isEmpty()) { 168 | com.google.protobuf.GeneratedMessageV3.writeString(output, 1, name_); 169 | } 170 | unknownFields.writeTo(output); 171 | } 172 | 173 | @java.lang.Override 174 | public int getSerializedSize() { 175 | int size = memoizedSize; 176 | if (size != -1) return size; 177 | 178 | size = 0; 179 | if (!getNameBytes().isEmpty()) { 180 | size += com.google.protobuf.GeneratedMessageV3.computeStringSize(1, name_); 181 | } 182 | size += unknownFields.getSerializedSize(); 183 | memoizedSize = size; 184 | return size; 185 | } 186 | 187 | @java.lang.Override 188 | public boolean equals(final java.lang.Object obj) { 189 | if (obj == this) { 190 | return true; 191 | } 192 | if (!(obj instanceof HelloWorldService.HelloRequest)) { 193 | return super.equals(obj); 194 | } 195 | HelloWorldService.HelloRequest other = (HelloWorldService.HelloRequest) obj; 196 | 197 | if (!getName() 198 | .equals(other.getName())) return false; 199 | if (!unknownFields.equals(other.unknownFields)) return false; 200 | return true; 201 | } 202 | 203 | @java.lang.Override 204 | public int hashCode() { 205 | if (memoizedHashCode != 0) { 206 | return memoizedHashCode; 207 | } 208 | int hash = 41; 209 | hash = (19 * hash) + getDescriptor().hashCode(); 210 | hash = (37 * hash) + NAME_FIELD_NUMBER; 211 | hash = (53 * hash) + getName().hashCode(); 212 | hash = (29 * hash) + unknownFields.hashCode(); 213 | memoizedHashCode = hash; 214 | return hash; 215 | } 216 | 217 | public static HelloWorldService.HelloRequest parseFrom( 218 | java.nio.ByteBuffer data) 219 | throws com.google.protobuf.InvalidProtocolBufferException { 220 | return PARSER.parseFrom(data); 221 | } 222 | public static HelloWorldService.HelloRequest parseFrom( 223 | java.nio.ByteBuffer data, 224 | com.google.protobuf.ExtensionRegistryLite extensionRegistry) 225 | throws com.google.protobuf.InvalidProtocolBufferException { 226 | return PARSER.parseFrom(data, extensionRegistry); 227 | } 228 | public static HelloWorldService.HelloRequest parseFrom( 229 | com.google.protobuf.ByteString data) 230 | throws com.google.protobuf.InvalidProtocolBufferException { 231 | return PARSER.parseFrom(data); 232 | } 233 | public static HelloWorldService.HelloRequest parseFrom( 234 | com.google.protobuf.ByteString data, 235 | com.google.protobuf.ExtensionRegistryLite extensionRegistry) 236 | throws com.google.protobuf.InvalidProtocolBufferException { 237 | return PARSER.parseFrom(data, extensionRegistry); 238 | } 239 | public static HelloWorldService.HelloRequest parseFrom(byte[] data) 240 | throws com.google.protobuf.InvalidProtocolBufferException { 241 | return PARSER.parseFrom(data); 242 | } 243 | public static HelloWorldService.HelloRequest parseFrom( 244 | byte[] data, 245 | com.google.protobuf.ExtensionRegistryLite extensionRegistry) 246 | throws com.google.protobuf.InvalidProtocolBufferException { 247 | return PARSER.parseFrom(data, extensionRegistry); 248 | } 249 | public static HelloWorldService.HelloRequest parseFrom(java.io.InputStream input) 250 | throws java.io.IOException { 251 | return com.google.protobuf.GeneratedMessageV3 252 | .parseWithIOException(PARSER, input); 253 | } 254 | public static HelloWorldService.HelloRequest parseFrom( 255 | java.io.InputStream input, 256 | com.google.protobuf.ExtensionRegistryLite extensionRegistry) 257 | throws java.io.IOException { 258 | return com.google.protobuf.GeneratedMessageV3 259 | .parseWithIOException(PARSER, input, extensionRegistry); 260 | } 261 | public static HelloWorldService.HelloRequest parseDelimitedFrom(java.io.InputStream input) 262 | throws java.io.IOException { 263 | return com.google.protobuf.GeneratedMessageV3 264 | .parseDelimitedWithIOException(PARSER, input); 265 | } 266 | public static HelloWorldService.HelloRequest parseDelimitedFrom( 267 | java.io.InputStream input, 268 | com.google.protobuf.ExtensionRegistryLite extensionRegistry) 269 | throws java.io.IOException { 270 | return com.google.protobuf.GeneratedMessageV3 271 | .parseDelimitedWithIOException(PARSER, input, extensionRegistry); 272 | } 273 | public static HelloWorldService.HelloRequest parseFrom( 274 | com.google.protobuf.CodedInputStream input) 275 | throws java.io.IOException { 276 | return com.google.protobuf.GeneratedMessageV3 277 | .parseWithIOException(PARSER, input); 278 | } 279 | public static HelloWorldService.HelloRequest parseFrom( 280 | com.google.protobuf.CodedInputStream input, 281 | com.google.protobuf.ExtensionRegistryLite extensionRegistry) 282 | throws java.io.IOException { 283 | return com.google.protobuf.GeneratedMessageV3 284 | .parseWithIOException(PARSER, input, extensionRegistry); 285 | } 286 | 287 | @java.lang.Override 288 | public Builder newBuilderForType() { return newBuilder(); } 289 | public static Builder newBuilder() { 290 | return DEFAULT_INSTANCE.toBuilder(); 291 | } 292 | public static Builder newBuilder(HelloWorldService.HelloRequest prototype) { 293 | return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); 294 | } 295 | @java.lang.Override 296 | public Builder toBuilder() { 297 | return this == DEFAULT_INSTANCE 298 | ? new Builder() : new Builder().mergeFrom(this); 299 | } 300 | 301 | @java.lang.Override 302 | protected Builder newBuilderForType( 303 | com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { 304 | Builder builder = new Builder(parent); 305 | return builder; 306 | } 307 | /** 308 | * Protobuf type {@code helloworld.HelloRequest} 309 | */ 310 | public static final class Builder extends 311 | com.google.protobuf.GeneratedMessageV3.Builder implements 312 | // @@protoc_insertion_point(builder_implements:helloworld.HelloRequest) 313 | HelloWorldService.HelloRequestOrBuilder { 314 | public static final com.google.protobuf.Descriptors.Descriptor 315 | getDescriptor() { 316 | return HelloWorldService.internal_static_helloworld_HelloRequest_descriptor; 317 | } 318 | 319 | @java.lang.Override 320 | protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable 321 | internalGetFieldAccessorTable() { 322 | return HelloWorldService.internal_static_helloworld_HelloRequest_fieldAccessorTable 323 | .ensureFieldAccessorsInitialized( 324 | HelloWorldService.HelloRequest.class, HelloWorldService.HelloRequest.Builder.class); 325 | } 326 | 327 | // Construct using site.wendev.spring.boot.istio.api.HelloWorldService.HelloRequest.newBuilder() 328 | private Builder() { 329 | maybeForceBuilderInitialization(); 330 | } 331 | 332 | private Builder( 333 | com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { 334 | super(parent); 335 | maybeForceBuilderInitialization(); 336 | } 337 | private void maybeForceBuilderInitialization() { 338 | if (com.google.protobuf.GeneratedMessageV3 339 | .alwaysUseFieldBuilders) { 340 | } 341 | } 342 | @java.lang.Override 343 | public Builder clear() { 344 | super.clear(); 345 | name_ = ""; 346 | 347 | return this; 348 | } 349 | 350 | @java.lang.Override 351 | public com.google.protobuf.Descriptors.Descriptor 352 | getDescriptorForType() { 353 | return HelloWorldService.internal_static_helloworld_HelloRequest_descriptor; 354 | } 355 | 356 | @java.lang.Override 357 | public HelloWorldService.HelloRequest getDefaultInstanceForType() { 358 | return HelloWorldService.HelloRequest.getDefaultInstance(); 359 | } 360 | 361 | @java.lang.Override 362 | public HelloWorldService.HelloRequest build() { 363 | HelloWorldService.HelloRequest result = buildPartial(); 364 | if (!result.isInitialized()) { 365 | throw newUninitializedMessageException(result); 366 | } 367 | return result; 368 | } 369 | 370 | @java.lang.Override 371 | public HelloWorldService.HelloRequest buildPartial() { 372 | HelloWorldService.HelloRequest result = new HelloWorldService.HelloRequest(this); 373 | result.name_ = name_; 374 | onBuilt(); 375 | return result; 376 | } 377 | 378 | @java.lang.Override 379 | public Builder clone() { 380 | return super.clone(); 381 | } 382 | @java.lang.Override 383 | public Builder setField( 384 | com.google.protobuf.Descriptors.FieldDescriptor field, 385 | java.lang.Object value) { 386 | return super.setField(field, value); 387 | } 388 | @java.lang.Override 389 | public Builder clearField( 390 | com.google.protobuf.Descriptors.FieldDescriptor field) { 391 | return super.clearField(field); 392 | } 393 | @java.lang.Override 394 | public Builder clearOneof( 395 | com.google.protobuf.Descriptors.OneofDescriptor oneof) { 396 | return super.clearOneof(oneof); 397 | } 398 | @java.lang.Override 399 | public Builder setRepeatedField( 400 | com.google.protobuf.Descriptors.FieldDescriptor field, 401 | int index, java.lang.Object value) { 402 | return super.setRepeatedField(field, index, value); 403 | } 404 | @java.lang.Override 405 | public Builder addRepeatedField( 406 | com.google.protobuf.Descriptors.FieldDescriptor field, 407 | java.lang.Object value) { 408 | return super.addRepeatedField(field, value); 409 | } 410 | @java.lang.Override 411 | public Builder mergeFrom(com.google.protobuf.Message other) { 412 | if (other instanceof HelloWorldService.HelloRequest) { 413 | return mergeFrom((HelloWorldService.HelloRequest)other); 414 | } else { 415 | super.mergeFrom(other); 416 | return this; 417 | } 418 | } 419 | 420 | public Builder mergeFrom(HelloWorldService.HelloRequest other) { 421 | if (other == HelloWorldService.HelloRequest.getDefaultInstance()) return this; 422 | if (!other.getName().isEmpty()) { 423 | name_ = other.name_; 424 | onChanged(); 425 | } 426 | this.mergeUnknownFields(other.unknownFields); 427 | onChanged(); 428 | return this; 429 | } 430 | 431 | @java.lang.Override 432 | public final boolean isInitialized() { 433 | return true; 434 | } 435 | 436 | @java.lang.Override 437 | public Builder mergeFrom( 438 | com.google.protobuf.CodedInputStream input, 439 | com.google.protobuf.ExtensionRegistryLite extensionRegistry) 440 | throws java.io.IOException { 441 | HelloWorldService.HelloRequest parsedMessage = null; 442 | try { 443 | parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); 444 | } catch (com.google.protobuf.InvalidProtocolBufferException e) { 445 | parsedMessage = (HelloWorldService.HelloRequest) e.getUnfinishedMessage(); 446 | throw e.unwrapIOException(); 447 | } finally { 448 | if (parsedMessage != null) { 449 | mergeFrom(parsedMessage); 450 | } 451 | } 452 | return this; 453 | } 454 | 455 | private java.lang.Object name_ = ""; 456 | /** 457 | * string name = 1; 458 | * @return The name. 459 | */ 460 | public java.lang.String getName() { 461 | java.lang.Object ref = name_; 462 | if (!(ref instanceof java.lang.String)) { 463 | com.google.protobuf.ByteString bs = 464 | (com.google.protobuf.ByteString) ref; 465 | java.lang.String s = bs.toStringUtf8(); 466 | name_ = s; 467 | return s; 468 | } else { 469 | return (java.lang.String) ref; 470 | } 471 | } 472 | /** 473 | * string name = 1; 474 | * @return The bytes for name. 475 | */ 476 | public com.google.protobuf.ByteString 477 | getNameBytes() { 478 | java.lang.Object ref = name_; 479 | if (ref instanceof String) { 480 | com.google.protobuf.ByteString b = 481 | com.google.protobuf.ByteString.copyFromUtf8( 482 | (java.lang.String) ref); 483 | name_ = b; 484 | return b; 485 | } else { 486 | return (com.google.protobuf.ByteString) ref; 487 | } 488 | } 489 | /** 490 | * string name = 1; 491 | * @param value The name to set. 492 | * @return This builder for chaining. 493 | */ 494 | public Builder setName( 495 | java.lang.String value) { 496 | if (value == null) { 497 | throw new NullPointerException(); 498 | } 499 | 500 | name_ = value; 501 | onChanged(); 502 | return this; 503 | } 504 | /** 505 | * string name = 1; 506 | * @return This builder for chaining. 507 | */ 508 | public Builder clearName() { 509 | 510 | name_ = getDefaultInstance().getName(); 511 | onChanged(); 512 | return this; 513 | } 514 | /** 515 | * string name = 1; 516 | * @param value The bytes for name to set. 517 | * @return This builder for chaining. 518 | */ 519 | public Builder setNameBytes( 520 | com.google.protobuf.ByteString value) { 521 | if (value == null) { 522 | throw new NullPointerException(); 523 | } 524 | checkByteStringIsUtf8(value); 525 | 526 | name_ = value; 527 | onChanged(); 528 | return this; 529 | } 530 | @java.lang.Override 531 | public final Builder setUnknownFields( 532 | final com.google.protobuf.UnknownFieldSet unknownFields) { 533 | return super.setUnknownFields(unknownFields); 534 | } 535 | 536 | @java.lang.Override 537 | public final Builder mergeUnknownFields( 538 | final com.google.protobuf.UnknownFieldSet unknownFields) { 539 | return super.mergeUnknownFields(unknownFields); 540 | } 541 | 542 | 543 | // @@protoc_insertion_point(builder_scope:helloworld.HelloRequest) 544 | } 545 | 546 | // @@protoc_insertion_point(class_scope:helloworld.HelloRequest) 547 | private static final HelloWorldService.HelloRequest DEFAULT_INSTANCE; 548 | static { 549 | DEFAULT_INSTANCE = new HelloWorldService.HelloRequest(); 550 | } 551 | 552 | public static HelloWorldService.HelloRequest getDefaultInstance() { 553 | return DEFAULT_INSTANCE; 554 | } 555 | 556 | private static final com.google.protobuf.Parser 557 | PARSER = new com.google.protobuf.AbstractParser() { 558 | @java.lang.Override 559 | public HelloRequest parsePartialFrom( 560 | com.google.protobuf.CodedInputStream input, 561 | com.google.protobuf.ExtensionRegistryLite extensionRegistry) 562 | throws com.google.protobuf.InvalidProtocolBufferException { 563 | return new HelloRequest(input, extensionRegistry); 564 | } 565 | }; 566 | 567 | public static com.google.protobuf.Parser parser() { 568 | return PARSER; 569 | } 570 | 571 | @java.lang.Override 572 | public com.google.protobuf.Parser getParserForType() { 573 | return PARSER; 574 | } 575 | 576 | @java.lang.Override 577 | public HelloWorldService.HelloRequest getDefaultInstanceForType() { 578 | return DEFAULT_INSTANCE; 579 | } 580 | 581 | } 582 | 583 | public interface HelloResponseOrBuilder extends 584 | // @@protoc_insertion_point(interface_extends:helloworld.HelloResponse) 585 | com.google.protobuf.MessageOrBuilder { 586 | 587 | /** 588 | * string message = 1; 589 | * @return The message. 590 | */ 591 | java.lang.String getMessage(); 592 | /** 593 | * string message = 1; 594 | * @return The bytes for message. 595 | */ 596 | com.google.protobuf.ByteString 597 | getMessageBytes(); 598 | } 599 | /** 600 | * Protobuf type {@code helloworld.HelloResponse} 601 | */ 602 | public static final class HelloResponse extends 603 | com.google.protobuf.GeneratedMessageV3 implements 604 | // @@protoc_insertion_point(message_implements:helloworld.HelloResponse) 605 | HelloResponseOrBuilder { 606 | private static final long serialVersionUID = 0L; 607 | // Use HelloResponse.newBuilder() to construct. 608 | private HelloResponse(com.google.protobuf.GeneratedMessageV3.Builder builder) { 609 | super(builder); 610 | } 611 | private HelloResponse() { 612 | message_ = ""; 613 | } 614 | 615 | @java.lang.Override 616 | @SuppressWarnings({"unused"}) 617 | protected java.lang.Object newInstance( 618 | UnusedPrivateParameter unused) { 619 | return new HelloResponse(); 620 | } 621 | 622 | @java.lang.Override 623 | public final com.google.protobuf.UnknownFieldSet 624 | getUnknownFields() { 625 | return this.unknownFields; 626 | } 627 | private HelloResponse( 628 | com.google.protobuf.CodedInputStream input, 629 | com.google.protobuf.ExtensionRegistryLite extensionRegistry) 630 | throws com.google.protobuf.InvalidProtocolBufferException { 631 | this(); 632 | if (extensionRegistry == null) { 633 | throw new java.lang.NullPointerException(); 634 | } 635 | com.google.protobuf.UnknownFieldSet.Builder unknownFields = 636 | com.google.protobuf.UnknownFieldSet.newBuilder(); 637 | try { 638 | boolean done = false; 639 | while (!done) { 640 | int tag = input.readTag(); 641 | switch (tag) { 642 | case 0: 643 | done = true; 644 | break; 645 | case 10: { 646 | java.lang.String s = input.readStringRequireUtf8(); 647 | 648 | message_ = s; 649 | break; 650 | } 651 | default: { 652 | if (!parseUnknownField( 653 | input, unknownFields, extensionRegistry, tag)) { 654 | done = true; 655 | } 656 | break; 657 | } 658 | } 659 | } 660 | } catch (com.google.protobuf.InvalidProtocolBufferException e) { 661 | throw e.setUnfinishedMessage(this); 662 | } catch (java.io.IOException e) { 663 | throw new com.google.protobuf.InvalidProtocolBufferException( 664 | e).setUnfinishedMessage(this); 665 | } finally { 666 | this.unknownFields = unknownFields.build(); 667 | makeExtensionsImmutable(); 668 | } 669 | } 670 | public static final com.google.protobuf.Descriptors.Descriptor 671 | getDescriptor() { 672 | return HelloWorldService.internal_static_helloworld_HelloResponse_descriptor; 673 | } 674 | 675 | @java.lang.Override 676 | protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable 677 | internalGetFieldAccessorTable() { 678 | return HelloWorldService.internal_static_helloworld_HelloResponse_fieldAccessorTable 679 | .ensureFieldAccessorsInitialized( 680 | HelloWorldService.HelloResponse.class, HelloWorldService.HelloResponse.Builder.class); 681 | } 682 | 683 | public static final int MESSAGE_FIELD_NUMBER = 1; 684 | private volatile java.lang.Object message_; 685 | /** 686 | * string message = 1; 687 | * @return The message. 688 | */ 689 | public java.lang.String getMessage() { 690 | java.lang.Object ref = message_; 691 | if (ref instanceof java.lang.String) { 692 | return (java.lang.String) ref; 693 | } else { 694 | com.google.protobuf.ByteString bs = 695 | (com.google.protobuf.ByteString) ref; 696 | java.lang.String s = bs.toStringUtf8(); 697 | message_ = s; 698 | return s; 699 | } 700 | } 701 | /** 702 | * string message = 1; 703 | * @return The bytes for message. 704 | */ 705 | public com.google.protobuf.ByteString 706 | getMessageBytes() { 707 | java.lang.Object ref = message_; 708 | if (ref instanceof java.lang.String) { 709 | com.google.protobuf.ByteString b = 710 | com.google.protobuf.ByteString.copyFromUtf8( 711 | (java.lang.String) ref); 712 | message_ = b; 713 | return b; 714 | } else { 715 | return (com.google.protobuf.ByteString) ref; 716 | } 717 | } 718 | 719 | private byte memoizedIsInitialized = -1; 720 | @java.lang.Override 721 | public final boolean isInitialized() { 722 | byte isInitialized = memoizedIsInitialized; 723 | if (isInitialized == 1) return true; 724 | if (isInitialized == 0) return false; 725 | 726 | memoizedIsInitialized = 1; 727 | return true; 728 | } 729 | 730 | @java.lang.Override 731 | public void writeTo(com.google.protobuf.CodedOutputStream output) 732 | throws java.io.IOException { 733 | if (!getMessageBytes().isEmpty()) { 734 | com.google.protobuf.GeneratedMessageV3.writeString(output, 1, message_); 735 | } 736 | unknownFields.writeTo(output); 737 | } 738 | 739 | @java.lang.Override 740 | public int getSerializedSize() { 741 | int size = memoizedSize; 742 | if (size != -1) return size; 743 | 744 | size = 0; 745 | if (!getMessageBytes().isEmpty()) { 746 | size += com.google.protobuf.GeneratedMessageV3.computeStringSize(1, message_); 747 | } 748 | size += unknownFields.getSerializedSize(); 749 | memoizedSize = size; 750 | return size; 751 | } 752 | 753 | @java.lang.Override 754 | public boolean equals(final java.lang.Object obj) { 755 | if (obj == this) { 756 | return true; 757 | } 758 | if (!(obj instanceof HelloWorldService.HelloResponse)) { 759 | return super.equals(obj); 760 | } 761 | HelloWorldService.HelloResponse other = (HelloWorldService.HelloResponse) obj; 762 | 763 | if (!getMessage() 764 | .equals(other.getMessage())) return false; 765 | if (!unknownFields.equals(other.unknownFields)) return false; 766 | return true; 767 | } 768 | 769 | @java.lang.Override 770 | public int hashCode() { 771 | if (memoizedHashCode != 0) { 772 | return memoizedHashCode; 773 | } 774 | int hash = 41; 775 | hash = (19 * hash) + getDescriptor().hashCode(); 776 | hash = (37 * hash) + MESSAGE_FIELD_NUMBER; 777 | hash = (53 * hash) + getMessage().hashCode(); 778 | hash = (29 * hash) + unknownFields.hashCode(); 779 | memoizedHashCode = hash; 780 | return hash; 781 | } 782 | 783 | public static HelloWorldService.HelloResponse parseFrom( 784 | java.nio.ByteBuffer data) 785 | throws com.google.protobuf.InvalidProtocolBufferException { 786 | return PARSER.parseFrom(data); 787 | } 788 | public static HelloWorldService.HelloResponse parseFrom( 789 | java.nio.ByteBuffer data, 790 | com.google.protobuf.ExtensionRegistryLite extensionRegistry) 791 | throws com.google.protobuf.InvalidProtocolBufferException { 792 | return PARSER.parseFrom(data, extensionRegistry); 793 | } 794 | public static HelloWorldService.HelloResponse parseFrom( 795 | com.google.protobuf.ByteString data) 796 | throws com.google.protobuf.InvalidProtocolBufferException { 797 | return PARSER.parseFrom(data); 798 | } 799 | public static HelloWorldService.HelloResponse parseFrom( 800 | com.google.protobuf.ByteString data, 801 | com.google.protobuf.ExtensionRegistryLite extensionRegistry) 802 | throws com.google.protobuf.InvalidProtocolBufferException { 803 | return PARSER.parseFrom(data, extensionRegistry); 804 | } 805 | public static HelloWorldService.HelloResponse parseFrom(byte[] data) 806 | throws com.google.protobuf.InvalidProtocolBufferException { 807 | return PARSER.parseFrom(data); 808 | } 809 | public static HelloWorldService.HelloResponse parseFrom( 810 | byte[] data, 811 | com.google.protobuf.ExtensionRegistryLite extensionRegistry) 812 | throws com.google.protobuf.InvalidProtocolBufferException { 813 | return PARSER.parseFrom(data, extensionRegistry); 814 | } 815 | public static HelloWorldService.HelloResponse parseFrom(java.io.InputStream input) 816 | throws java.io.IOException { 817 | return com.google.protobuf.GeneratedMessageV3 818 | .parseWithIOException(PARSER, input); 819 | } 820 | public static HelloWorldService.HelloResponse parseFrom( 821 | java.io.InputStream input, 822 | com.google.protobuf.ExtensionRegistryLite extensionRegistry) 823 | throws java.io.IOException { 824 | return com.google.protobuf.GeneratedMessageV3 825 | .parseWithIOException(PARSER, input, extensionRegistry); 826 | } 827 | public static HelloWorldService.HelloResponse parseDelimitedFrom(java.io.InputStream input) 828 | throws java.io.IOException { 829 | return com.google.protobuf.GeneratedMessageV3 830 | .parseDelimitedWithIOException(PARSER, input); 831 | } 832 | public static HelloWorldService.HelloResponse parseDelimitedFrom( 833 | java.io.InputStream input, 834 | com.google.protobuf.ExtensionRegistryLite extensionRegistry) 835 | throws java.io.IOException { 836 | return com.google.protobuf.GeneratedMessageV3 837 | .parseDelimitedWithIOException(PARSER, input, extensionRegistry); 838 | } 839 | public static HelloWorldService.HelloResponse parseFrom( 840 | com.google.protobuf.CodedInputStream input) 841 | throws java.io.IOException { 842 | return com.google.protobuf.GeneratedMessageV3 843 | .parseWithIOException(PARSER, input); 844 | } 845 | public static HelloWorldService.HelloResponse parseFrom( 846 | com.google.protobuf.CodedInputStream input, 847 | com.google.protobuf.ExtensionRegistryLite extensionRegistry) 848 | throws java.io.IOException { 849 | return com.google.protobuf.GeneratedMessageV3 850 | .parseWithIOException(PARSER, input, extensionRegistry); 851 | } 852 | 853 | @java.lang.Override 854 | public Builder newBuilderForType() { return newBuilder(); } 855 | public static Builder newBuilder() { 856 | return DEFAULT_INSTANCE.toBuilder(); 857 | } 858 | public static Builder newBuilder(HelloWorldService.HelloResponse prototype) { 859 | return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); 860 | } 861 | @java.lang.Override 862 | public Builder toBuilder() { 863 | return this == DEFAULT_INSTANCE 864 | ? new Builder() : new Builder().mergeFrom(this); 865 | } 866 | 867 | @java.lang.Override 868 | protected Builder newBuilderForType( 869 | com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { 870 | Builder builder = new Builder(parent); 871 | return builder; 872 | } 873 | /** 874 | * Protobuf type {@code helloworld.HelloResponse} 875 | */ 876 | public static final class Builder extends 877 | com.google.protobuf.GeneratedMessageV3.Builder implements 878 | // @@protoc_insertion_point(builder_implements:helloworld.HelloResponse) 879 | HelloWorldService.HelloResponseOrBuilder { 880 | public static final com.google.protobuf.Descriptors.Descriptor 881 | getDescriptor() { 882 | return HelloWorldService.internal_static_helloworld_HelloResponse_descriptor; 883 | } 884 | 885 | @java.lang.Override 886 | protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable 887 | internalGetFieldAccessorTable() { 888 | return HelloWorldService.internal_static_helloworld_HelloResponse_fieldAccessorTable 889 | .ensureFieldAccessorsInitialized( 890 | HelloWorldService.HelloResponse.class, HelloWorldService.HelloResponse.Builder.class); 891 | } 892 | 893 | // Construct using site.wendev.spring.boot.istio.api.HelloWorldService.HelloResponse.newBuilder() 894 | private Builder() { 895 | maybeForceBuilderInitialization(); 896 | } 897 | 898 | private Builder( 899 | com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { 900 | super(parent); 901 | maybeForceBuilderInitialization(); 902 | } 903 | private void maybeForceBuilderInitialization() { 904 | if (com.google.protobuf.GeneratedMessageV3 905 | .alwaysUseFieldBuilders) { 906 | } 907 | } 908 | @java.lang.Override 909 | public Builder clear() { 910 | super.clear(); 911 | message_ = ""; 912 | 913 | return this; 914 | } 915 | 916 | @java.lang.Override 917 | public com.google.protobuf.Descriptors.Descriptor 918 | getDescriptorForType() { 919 | return HelloWorldService.internal_static_helloworld_HelloResponse_descriptor; 920 | } 921 | 922 | @java.lang.Override 923 | public HelloWorldService.HelloResponse getDefaultInstanceForType() { 924 | return HelloWorldService.HelloResponse.getDefaultInstance(); 925 | } 926 | 927 | @java.lang.Override 928 | public HelloWorldService.HelloResponse build() { 929 | HelloWorldService.HelloResponse result = buildPartial(); 930 | if (!result.isInitialized()) { 931 | throw newUninitializedMessageException(result); 932 | } 933 | return result; 934 | } 935 | 936 | @java.lang.Override 937 | public HelloWorldService.HelloResponse buildPartial() { 938 | HelloWorldService.HelloResponse result = new HelloWorldService.HelloResponse(this); 939 | result.message_ = message_; 940 | onBuilt(); 941 | return result; 942 | } 943 | 944 | @java.lang.Override 945 | public Builder clone() { 946 | return super.clone(); 947 | } 948 | @java.lang.Override 949 | public Builder setField( 950 | com.google.protobuf.Descriptors.FieldDescriptor field, 951 | java.lang.Object value) { 952 | return super.setField(field, value); 953 | } 954 | @java.lang.Override 955 | public Builder clearField( 956 | com.google.protobuf.Descriptors.FieldDescriptor field) { 957 | return super.clearField(field); 958 | } 959 | @java.lang.Override 960 | public Builder clearOneof( 961 | com.google.protobuf.Descriptors.OneofDescriptor oneof) { 962 | return super.clearOneof(oneof); 963 | } 964 | @java.lang.Override 965 | public Builder setRepeatedField( 966 | com.google.protobuf.Descriptors.FieldDescriptor field, 967 | int index, java.lang.Object value) { 968 | return super.setRepeatedField(field, index, value); 969 | } 970 | @java.lang.Override 971 | public Builder addRepeatedField( 972 | com.google.protobuf.Descriptors.FieldDescriptor field, 973 | java.lang.Object value) { 974 | return super.addRepeatedField(field, value); 975 | } 976 | @java.lang.Override 977 | public Builder mergeFrom(com.google.protobuf.Message other) { 978 | if (other instanceof HelloWorldService.HelloResponse) { 979 | return mergeFrom((HelloWorldService.HelloResponse)other); 980 | } else { 981 | super.mergeFrom(other); 982 | return this; 983 | } 984 | } 985 | 986 | public Builder mergeFrom(HelloWorldService.HelloResponse other) { 987 | if (other == HelloWorldService.HelloResponse.getDefaultInstance()) return this; 988 | if (!other.getMessage().isEmpty()) { 989 | message_ = other.message_; 990 | onChanged(); 991 | } 992 | this.mergeUnknownFields(other.unknownFields); 993 | onChanged(); 994 | return this; 995 | } 996 | 997 | @java.lang.Override 998 | public final boolean isInitialized() { 999 | return true; 1000 | } 1001 | 1002 | @java.lang.Override 1003 | public Builder mergeFrom( 1004 | com.google.protobuf.CodedInputStream input, 1005 | com.google.protobuf.ExtensionRegistryLite extensionRegistry) 1006 | throws java.io.IOException { 1007 | HelloWorldService.HelloResponse parsedMessage = null; 1008 | try { 1009 | parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); 1010 | } catch (com.google.protobuf.InvalidProtocolBufferException e) { 1011 | parsedMessage = (HelloWorldService.HelloResponse) e.getUnfinishedMessage(); 1012 | throw e.unwrapIOException(); 1013 | } finally { 1014 | if (parsedMessage != null) { 1015 | mergeFrom(parsedMessage); 1016 | } 1017 | } 1018 | return this; 1019 | } 1020 | 1021 | private java.lang.Object message_ = ""; 1022 | /** 1023 | * string message = 1; 1024 | * @return The message. 1025 | */ 1026 | public java.lang.String getMessage() { 1027 | java.lang.Object ref = message_; 1028 | if (!(ref instanceof java.lang.String)) { 1029 | com.google.protobuf.ByteString bs = 1030 | (com.google.protobuf.ByteString) ref; 1031 | java.lang.String s = bs.toStringUtf8(); 1032 | message_ = s; 1033 | return s; 1034 | } else { 1035 | return (java.lang.String) ref; 1036 | } 1037 | } 1038 | /** 1039 | * string message = 1; 1040 | * @return The bytes for message. 1041 | */ 1042 | public com.google.protobuf.ByteString 1043 | getMessageBytes() { 1044 | java.lang.Object ref = message_; 1045 | if (ref instanceof String) { 1046 | com.google.protobuf.ByteString b = 1047 | com.google.protobuf.ByteString.copyFromUtf8( 1048 | (java.lang.String) ref); 1049 | message_ = b; 1050 | return b; 1051 | } else { 1052 | return (com.google.protobuf.ByteString) ref; 1053 | } 1054 | } 1055 | /** 1056 | * string message = 1; 1057 | * @param value The message to set. 1058 | * @return This builder for chaining. 1059 | */ 1060 | public Builder setMessage( 1061 | java.lang.String value) { 1062 | if (value == null) { 1063 | throw new NullPointerException(); 1064 | } 1065 | 1066 | message_ = value; 1067 | onChanged(); 1068 | return this; 1069 | } 1070 | /** 1071 | * string message = 1; 1072 | * @return This builder for chaining. 1073 | */ 1074 | public Builder clearMessage() { 1075 | 1076 | message_ = getDefaultInstance().getMessage(); 1077 | onChanged(); 1078 | return this; 1079 | } 1080 | /** 1081 | * string message = 1; 1082 | * @param value The bytes for message to set. 1083 | * @return This builder for chaining. 1084 | */ 1085 | public Builder setMessageBytes( 1086 | com.google.protobuf.ByteString value) { 1087 | if (value == null) { 1088 | throw new NullPointerException(); 1089 | } 1090 | checkByteStringIsUtf8(value); 1091 | 1092 | message_ = value; 1093 | onChanged(); 1094 | return this; 1095 | } 1096 | @java.lang.Override 1097 | public final Builder setUnknownFields( 1098 | final com.google.protobuf.UnknownFieldSet unknownFields) { 1099 | return super.setUnknownFields(unknownFields); 1100 | } 1101 | 1102 | @java.lang.Override 1103 | public final Builder mergeUnknownFields( 1104 | final com.google.protobuf.UnknownFieldSet unknownFields) { 1105 | return super.mergeUnknownFields(unknownFields); 1106 | } 1107 | 1108 | 1109 | // @@protoc_insertion_point(builder_scope:helloworld.HelloResponse) 1110 | } 1111 | 1112 | // @@protoc_insertion_point(class_scope:helloworld.HelloResponse) 1113 | private static final HelloWorldService.HelloResponse DEFAULT_INSTANCE; 1114 | static { 1115 | DEFAULT_INSTANCE = new HelloWorldService.HelloResponse(); 1116 | } 1117 | 1118 | public static HelloWorldService.HelloResponse getDefaultInstance() { 1119 | return DEFAULT_INSTANCE; 1120 | } 1121 | 1122 | private static final com.google.protobuf.Parser 1123 | PARSER = new com.google.protobuf.AbstractParser() { 1124 | @java.lang.Override 1125 | public HelloResponse parsePartialFrom( 1126 | com.google.protobuf.CodedInputStream input, 1127 | com.google.protobuf.ExtensionRegistryLite extensionRegistry) 1128 | throws com.google.protobuf.InvalidProtocolBufferException { 1129 | return new HelloResponse(input, extensionRegistry); 1130 | } 1131 | }; 1132 | 1133 | public static com.google.protobuf.Parser parser() { 1134 | return PARSER; 1135 | } 1136 | 1137 | @java.lang.Override 1138 | public com.google.protobuf.Parser getParserForType() { 1139 | return PARSER; 1140 | } 1141 | 1142 | @java.lang.Override 1143 | public HelloWorldService.HelloResponse getDefaultInstanceForType() { 1144 | return DEFAULT_INSTANCE; 1145 | } 1146 | 1147 | } 1148 | 1149 | private static final com.google.protobuf.Descriptors.Descriptor 1150 | internal_static_helloworld_HelloRequest_descriptor; 1151 | private static final 1152 | com.google.protobuf.GeneratedMessageV3.FieldAccessorTable 1153 | internal_static_helloworld_HelloRequest_fieldAccessorTable; 1154 | private static final com.google.protobuf.Descriptors.Descriptor 1155 | internal_static_helloworld_HelloResponse_descriptor; 1156 | private static final 1157 | com.google.protobuf.GeneratedMessageV3.FieldAccessorTable 1158 | internal_static_helloworld_HelloResponse_fieldAccessorTable; 1159 | 1160 | public static com.google.protobuf.Descriptors.FileDescriptor 1161 | getDescriptor() { 1162 | return descriptor; 1163 | } 1164 | private static com.google.protobuf.Descriptors.FileDescriptor 1165 | descriptor; 1166 | static { 1167 | java.lang.String[] descriptorData = { 1168 | "\n\013hello.proto\022\nhelloworld\"\034\n\014HelloReques" + 1169 | "t\022\014\n\004name\030\001 \001(\t\" \n\rHelloResponse\022\017\n\007mess" + 1170 | "age\030\001 \001(\t2O\n\nHelloWorld\022A\n\010SayHello\022\030.he" + 1171 | "lloworld.HelloRequest\032\031.helloworld.Hello" + 1172 | "Response\"\000B6\n!site.wendev.spring.boot.is" + 1173 | "tio.apiB\021HelloWorldServiceb\006proto3" 1174 | }; 1175 | descriptor = com.google.protobuf.Descriptors.FileDescriptor 1176 | .internalBuildGeneratedFileFrom(descriptorData, 1177 | new com.google.protobuf.Descriptors.FileDescriptor[] { 1178 | }); 1179 | internal_static_helloworld_HelloRequest_descriptor = 1180 | getDescriptor().getMessageTypes().get(0); 1181 | internal_static_helloworld_HelloRequest_fieldAccessorTable = new 1182 | com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( 1183 | internal_static_helloworld_HelloRequest_descriptor, 1184 | new java.lang.String[] { "Name", }); 1185 | internal_static_helloworld_HelloResponse_descriptor = 1186 | getDescriptor().getMessageTypes().get(1); 1187 | internal_static_helloworld_HelloResponse_fieldAccessorTable = new 1188 | com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( 1189 | internal_static_helloworld_HelloResponse_descriptor, 1190 | new java.lang.String[] { "Message", }); 1191 | } 1192 | 1193 | // @@protoc_insertion_point(outer_class_scope) 1194 | } 1195 | --------------------------------------------------------------------------------