整合K8s+SpringCloudK8s+SpringBoot+gRpc
创始人
2024-05-26 10:36:13
0

本文使用K8s当做服务注册与发现、配置管理,使用gRpc用做服务间的远程通讯

一、先准备K8s

我在本地有个K8s单机

二、准备service-provider

  1. pom


4.0.0org.springframework.bootspring-boot-starter-parent2.6.7 com.exampleservice-provider0.0.1-SNAPSHOTservice-providerservice-provider11osx-x86_64org.springframework.bootspring-boot-dependenciespomimport2.6.7org.springframework.cloudspring-cloud-dependencies2021.0.2pomimportorg.springframework.cloudspring-cloud-kubernetes-dependencies1.1.0.RELEASEpomimportorg.springframework.bootspring-boot-starter-weborg.springframework.cloudspring-cloud-starter-kubernetes-client-allorg.springframework.bootspring-boot-starter-actuatornet.devhgrpc-spring-boot-starter2.14.0.RELEASEio.grpcgrpc-protobuf1.52.1org.projectlomboklomboktrue1.18.24kr.motd.mavenos-maven-plugin1.7.1org.springframework.bootspring-boot-maven-pluginexecorg.xolstice.maven.pluginsprotobuf-maven-plugin0.6.1com.google.protobuf:protoc:3.21.7:exe:${os.detected.classifier}grpc-javaio.grpc:protoc-gen-grpc-java:1.52.1:exe:${os.detected.classifier}compilecompile-custom
  1. 配置文件 bootstrap.yaml

management:endpoint:restart:enabled: truehealth:enabled: trueinfo:enabled: trueendpoints:web:exposure:include: '*'grpc:server:port: 9090
server:port: 30000spring:application:name: service-providercloud:kubernetes:reload:enabled: trueconfig:sources:- namespace: service-k8s-demoname: service-provider-config
  1. 主类 ServiceProviderApplication

package com.example.service.provider;import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;@Slf4j
@RestController
@SpringBootApplication
@EnableDiscoveryClient
@RefreshScope
public class ServiceProviderApplication {@Value("${maple-test.message}")private String mapleTestMessage;@Autowiredprivate DemoConfig demoConfig;public static void main(String[] args) {SpringApplication.run(ServiceProviderApplication.class, args);}@GetMapping("/provider-hello")public String sayHello() {log.info("hello world");return "hello world";}@GetMapping("/provider-value-config")public String valueConfig() {log.info("直接@Value获取配置:{}", mapleTestMessage);return mapleTestMessage;}@GetMapping("/demo-config")public String demoConfig() {log.info("通过ConfigurationProperties注解获取配置:{}", demoConfig.getMessage());return demoConfig.getMessage();}
}
  1. 在 src/main/proto文件夹下新增PB文件 HelloFacade.proto

syntax = "proto3";option java_multiple_files = true;
option java_package = "com.example.service.provider.api";
option java_outer_classname = "HelloServiceProto";service HelloService {rpc SayHello (SayHelloRequest) returns (SayHelloResponse) {}
}message SayHelloRequest {string name = 1;
}message SayHelloResponse {int32 code = 1;string message = 2;bool success = 3;SayHelloData data = 4;
}message SayHelloData {string name = 1;string content = 2;
}
  1. 接口实现类

package com.example.service.provider.facade;import com.example.service.provider.DemoConfig;
import com.example.service.provider.api.HelloServiceGrpc;
import com.example.service.provider.api.SayHelloData;
import com.example.service.provider.api.SayHelloRequest;
import com.example.service.provider.api.SayHelloResponse;
import lombok.extern.slf4j.Slf4j;
import net.devh.boot.grpc.server.service.GrpcService;
import org.springframework.beans.factory.annotation.Autowired;@Slf4j
@GrpcService
public class HelloServiceImpl extends HelloServiceGrpc.HelloServiceImplBase {@Autowiredprivate DemoConfig demoConfig;@Overridepublic void sayHello(SayHelloRequest request, io.grpc.stub.StreamObserver responseObserver) {log.info("接收consumer的say hello grpc 请求");SayHelloData helloData = SayHelloData.newBuilder().setName("maple").setContent(demoConfig.getMessage()).build();SayHelloResponse.Builder builder = SayHelloResponse.newBuilder().setCode(0).setMessage("success").setSuccess(true).setData(helloData);responseObserver.onNext(builder.build());responseObserver.onCompleted();}
}
  1. Dockerfile

FROM openjdk:11-jdk-slim
ADD service-provider-0.0.1-SNAPSHOT-exec.jar service-provider.jar
ENTRYPOINT ["java", "-jar", "service-provider.jar"]
  1. K8s声明yaml文件 service-provider-deploy.yaml

apiVersion: v1
kind: Namespace
metadata:name: service-k8s-demolabels:name: service-k8s-demo---apiVersion: v1
kind: ServiceAccount
metadata:name: service-k8s-demonamespace: service-k8s-demo---kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:namespace: service-k8s-demoname: service-k8s-demo
rules:- apiGroups:- ""resources:- services- configmaps- endpoints- nodes- pods- secrets- namespacesverbs:- get- list- watch---apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:name: service-k8s-demonamespace: service-k8s-demo
subjects:
- kind: ServiceAccountname: service-k8s-demonamespace: service-k8s-demo
roleRef:kind: ClusterRolename: service-k8s-demoapiGroup: rbac.authorization.k8s.io---apiVersion: apps/v1
kind: Deployment
metadata:name: service-providernamespace: service-k8s-demolabels:app: service-provider
spec:replicas: 1template:metadata:name: service-providerlabels:app: service-providerspec:containers:- name: service-providerimage: service-provider:1.0imagePullPolicy: IfNotPresentports:- name: httpprotocol: TCPcontainerPort: 30000- name: grpcprotocol: TCPcontainerPort: 9090serviceAccountName: service-k8s-demorestartPolicy: Alwaysselector:matchLabels:app: service-provider---apiVersion: v1
kind: Service
metadata:name: service-providernamespace: service-k8s-demo
spec:selector:app: service-providerports:- port: 80targetPort: 30000name: http- port: 9090targetPort: 9090name: grpc#clusterIP: Nonetype: NodePort
  1. K8s声明yaml文件 service-provider-config.yaml

apiVersion: v1
kind: ConfigMap
metadata:name: service-provider-confignamespace: service-k8s-demo
data:bean.message: Hello World!maple-test.message: maple for dev config map in k8sredis.ip: 111 in k8s
  1. 本地启动测试

三、准备service-consumer

  1. pom


4.0.0org.springframework.bootspring-boot-starter-parent2.6.7 com.exampleservice-consumer0.0.1-SNAPSHOTservice-consumerservice-consumer11org.springframework.bootspring-boot-dependenciespomimport2.6.7org.springframework.cloudspring-cloud-dependencies2021.0.2pomimportorg.springframework.cloudspring-cloud-kubernetes-dependencies1.1.10.RELEASEpomimportcom.exampleservice-provider0.0.1-SNAPSHOTorg.springframework.bootspring-boot-starter-weborg.springframework.bootspring-boot-starter-actuatororg.springframework.cloudspring-cloud-starter-kubernetes-client-allorg.projectlomboklomboktrue1.18.24net.devhgrpc-spring-boot-starter2.14.0.RELEASEio.grpcgrpc-protobuf1.52.1kr.motd.mavenos-maven-plugin1.7.1org.springframework.bootspring-boot-maven-pluginexecorg.xolstice.maven.pluginsprotobuf-maven-plugin0.6.1com.google.protobuf:protoc:3.21.7:exe:${os.detected.classifier}grpc-javaio.grpc:protoc-gen-grpc-java:1.52.1:exe:${os.detected.classifier}compilecompile-custom

  1. 配置文件 bootstrap.yaml

management:endpoint:restart:enabled: truehealth:enabled: trueinfo:enabled: trueendpoints:web:exposure:include: '*'grpc:server:port: 9091client:service-provider:negotiation-type: plaintextenable-keep-alive: truekeep-alive-without-calls: trueaddress: 'static://service-provider:9090'server:port: 30001
spring:application:name: service-consumercloud:kubernetes:reload:enabled: trueconfig:sources:- namespace: service-k8s-demoname: service-consumer-config
  1. 主类 ServiceConsumerApplication

package com.example.service.consumer;import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.List;@Slf4j
@RestController
@EnableDiscoveryClient
@SpringBootApplication
@RequiredArgsConstructor
@RefreshScope
public class ServiceConsumerApplication {private final DiscoveryClient discoveryClient;private final ProviderServiceGrpcClient providerServiceGrpcClient;public static void main(String[] args) {SpringApplication.run(ServiceConsumerApplication.class, args);}@Value("${consumer.body}")private String consumerBody;@GetMapping("/grpc/hello")public String sayHello() {log.info("消费服务:service-consumer grpc 调用 service-provider");return providerServiceGrpcClient.sayHello();}@GetMapping("/consumerBody")public String consumerBody() {log.info("获取配置consumerBody:{}", consumerBody);return consumerBody;}@GetMapping("/consumers/services")public List findServices() {log.info("当前注册中心下所有服务");List services = discoveryClient.getServices();services.stream().map(discoveryClient::getInstances).forEach(v ->v.forEach(s -> System.out.printf("%s:%s  uri:%s%n", s.getHost(), s.getPort(), s.getUri())));return services;}
}
  1. gRpc调用Provider ProviderServiceGrpcClient

package com.example.service.consumer;import com.example.service.provider.api.HelloServiceGrpc;
import com.example.service.provider.api.SayHelloRequest;
import com.example.service.provider.api.SayHelloResponse;
import net.devh.boot.grpc.client.inject.GrpcClient;
import org.springframework.stereotype.Service;@Service
public class ProviderServiceGrpcClient {@GrpcClient("service-provider")private HelloServiceGrpc.HelloServiceBlockingStub helloServiceBlockingStub;public String sayHello() {SayHelloRequest request = SayHelloRequest.newBuilder().setName("maple123").build();SayHelloResponse sayHelloResponse = helloServiceBlockingStub.sayHello(request);return sayHelloResponse.toString();}
}
  1. Dockerfile

FROM openjdk:11-jdk-slim
ADD service-consumer-0.0.1-SNAPSHOT-exec.jar service-consumer.jar
ENTRYPOINT java -jar  service-consumer.jar
  1. K8s声明yaml文件 service-consumer-deploy.yaml

apiVersion: v1
kind: Namespace
metadata:name: service-k8s-demolabels:name: service-k8s-demo---apiVersion: v1
kind: ServiceAccount
metadata:name: service-k8s-demonamespace: service-k8s-demo---kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:namespace: service-k8s-demoname: service-k8s-demo
rules:- apiGroups:- ""resources:- services- configmaps- endpoints- nodes- pods- secrets- namespacesverbs:- get- list- watch---apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:name: service-k8s-demonamespace: service-k8s-demo
subjects:- kind: ServiceAccountname: service-k8s-demonamespace: service-k8s-demo
roleRef:kind: ClusterRolename: service-k8s-demoapiGroup: rbac.authorization.k8s.io---apiVersion: apps/v1
kind: Deployment
metadata:name: service-consumernamespace: service-k8s-demolabels:app: service-consumer
spec:replicas: 1template:metadata:name: service-consumerlabels:app: service-consumerspec:containers:- name: service-consumerimage: service-consumer:1.0imagePullPolicy: IfNotPresentports:- name: httpprotocol: TCPcontainerPort: 30001- name: grpcprotocol: TCPcontainerPort: 9091serviceAccountName: service-k8s-demorestartPolicy: Alwaysselector:matchLabels:app: service-consumer---apiVersion: v1
kind: Service
metadata:name: service-consumernamespace: service-k8s-demo
spec:selector:app: service-consumerports:- port: 80targetPort: 30001name: http- port: 9091targetPort: 9091name: grpctype: NodePort
  1. K8s声明yaml文件 service-consumer-config.yaml

apiVersion: v1
kind: ConfigMap
metadata:name: service-consumer-confignamespace: service-k8s-demo
data:consumer.body: "1234567890"
  1. 本地启动测试

四、打镜像

docker build -t service-provider:1.0 .
docker build -t service-consumer:1.0 .

五、执行K8s yaml文件 创建命名空间、账号、角色、部署应用、暴露端口等

kubetl apply -f service-provider-config.yaml
kubetl apply -f service-provider-deploy.yamlkubetl apply -f service-consumer-config.yaml
kubetl apply -f service-consumer-deploy.yaml

六、查看与测试

gRpc正常访问,但是发现一个问题,下面的图片,上面三个是Provider,发现负载均衡失效了,请求全都打在了一个Provider里,搜了下发现和 gRpc基于HTTP2.0 多路复用 有关,处理方案看这里

K8s中gRpc通信负载均衡失效

配置测试

动态配置测试

相关内容

热门资讯

喜欢穿一身黑的男生性格(喜欢穿... 今天百科达人给各位分享喜欢穿一身黑的男生性格的知识,其中也会对喜欢穿一身黑衣服的男人人好相处吗进行解...
发春是什么意思(思春和发春是什... 本篇文章极速百科给大家谈谈发春是什么意思,以及思春和发春是什么意思对应的知识点,希望对各位有所帮助,...
网络用语zl是什么意思(zl是... 今天给各位分享网络用语zl是什么意思的知识,其中也会对zl是啥意思是什么网络用语进行解释,如果能碰巧...
为什么酷狗音乐自己唱的歌不能下... 本篇文章极速百科小编给大家谈谈为什么酷狗音乐自己唱的歌不能下载到本地?,以及为什么酷狗下载的歌曲不是...
华为下载未安装的文件去哪找(华... 今天百科达人给各位分享华为下载未安装的文件去哪找的知识,其中也会对华为下载未安装的文件去哪找到进行解...
怎么往应用助手里添加应用(应用... 今天百科达人给各位分享怎么往应用助手里添加应用的知识,其中也会对应用助手怎么添加微信进行解释,如果能...
家里可以做假山养金鱼吗(假山能... 今天百科达人给各位分享家里可以做假山养金鱼吗的知识,其中也会对假山能放鱼缸里吗进行解释,如果能碰巧解...
四分五裂是什么生肖什么动物(四... 本篇文章极速百科小编给大家谈谈四分五裂是什么生肖什么动物,以及四分五裂打一生肖是什么对应的知识点,希...
一帆风顺二龙腾飞三阳开泰祝福语... 本篇文章极速百科给大家谈谈一帆风顺二龙腾飞三阳开泰祝福语,以及一帆风顺二龙腾飞三阳开泰祝福语结婚对应...
美团联名卡审核成功待激活(美团... 今天百科达人给各位分享美团联名卡审核成功待激活的知识,其中也会对美团联名卡审核未通过进行解释,如果能...