목차
1. Istio를 사용하는 이유
1.1. gRPC를 통신 프레임워크로 사용하는 이유는 무엇입니까?
1.2. 비즈니스 코드 작성
1.3、 编写Dockerfile
2. 编写部署文件
3. 部署应用到Istio
Java java지도 시간 Spring Boot+gRPC를 사용하여 마이크로서비스를 구축하고 배포하는 방법

Spring Boot+gRPC를 사용하여 마이크로서비스를 구축하고 배포하는 방법

May 22, 2023 pm 08:13 PM
grpc springboot

1. Istio를 사용하는 이유

현재 Java 기술 스택의 경우 마이크로서비스 구축을 위한 최선의 선택은 Spring Boot이며, Spring Boot는 일반적으로 구현 사례가 많은 마이크로서비스 프레임워크인 Spring Cloud와 함께 사용됩니다.

Spring Cloud는 완벽해 보이지만, 실제 개발을 해보면 Spring Cloud에 다음과 같은 심각한 문제가 있음을 쉽게 발견할 수 있습니다.

  • Spring Cloud Netflix와 같은 SDK에는 서비스 거버넌스와 관련된 로직이 존재하며 이는 비즈니스와 관련됩니다. 코드가 밀접하게 결합되어 있습니다.

  • SDK가 비즈니스 코드에 너무 방해가 되어 SDK가 업그레이드되고 이전 버전과 호환될 수 없는 경우 비즈니스 로직이 전혀 변경되지 않더라도 SDK 업그레이드에 맞게 비즈니스 코드를 변경해야 합니다.

  • 다양한 구성 요소가 눈에 띄고 품질도 고르지 않습니다. 학습 비용이 너무 높으며, 구성 요소 간 코드를 완전히 재사용하기가 어렵습니다. 단지 거버넌스 로직을 구현하기 위해 SDK를 학습하는 것은 좋은 선택이 아닙니다.

  • 는 Java 기술 스택에 묶여 있습니다. 다른 언어도 연결될 수 있지만 서비스 거버넌스 관련 로직은 수동으로 구현해야 하며 이는 "다중 언어로 개발 가능"이라는 마이크로서비스 원칙을 준수하지 않습니다.

  • Spring Cloud는 개발 프레임워크일 뿐이며 마이크로서비스에 필요한 서비스 스케줄링, 리소스 할당 및 기타 기능을 구현하지 않습니다. 이러한 요구 사항은 Kubernetes와 같은 플랫폼의 도움으로 완료되어야 합니다. Spring Cloud와 Kubernetes는 기능이 겹치고, 충돌하는 기능으로 인해 둘 사이의 원활한 협업에 어려움이 발생합니다.

Spring Cloud에 대한 대안이 있나요? 가지다! 이스티오입니다.

Istio는 거버넌스 로직을 비즈니스 코드와 완전히 분리하고 독립적인 프로세스(사이드카)를 구현합니다. 배포 중에 사이드카와 비즈니스 코드는 동일한 Pod에 공존하지만 비즈니스 코드는 사이드카의 존재를 전혀 인식하지 못합니다. 이를 통해 비즈니스 코드에 대한 거버넌스 로직의 침입이 전혀 발생하지 않습니다. 실제로 코드가 침해되지 않을 뿐만 아니라 런타임 시 둘 사이에 결합도 없습니다. 이를 통해 서비스 거버넌스 문제에 대해 걱정할 필요 없이 다양한 언어와 기술 스택을 사용하여 다양한 마이크로서비스를 개발할 수 있습니다. 이는 매우 우아한 솔루션이라고 할 수 있습니다.

그래서 "Istio를 사용하는 이유"에 대한 질문은 쉽게 해결됩니다. Istio는 비즈니스 로직과 서비스 거버넌스 로직의 결합, 언어 간 구현 불가능 등 기존 마이크로서비스의 문제점을 해결하기 때문입니다. 사용하기 매우 쉽습니다. Kubernetes를 마스터하고 나면 Istio 사용 방법을 배우는 것은 어렵지 않습니다.

1.1. gRPC를 통신 프레임워크로 사용하는 이유는 무엇입니까?

마이크로서비스 아키텍처에서 서비스 간 통신은 상대적으로 큰 문제이며 일반적으로 RPC 또는 RESTful API를 사용하여 구현됩니다.

Spring Boot는 RestTemplate을 사용하여 원격 서비스를 호출할 수 있지만 이 방법은 직관적이지 않고 코드가 복잡합니다. 언어 간 통신도 큰 문제입니다. gRPC는 Dubbo와 같은 일반적인 Java RPC 프레임워크보다 가볍습니다. 사용하기도 매우 편리하고, 코드 가독성도 좋고, Protobuf와 HTTP2 지원으로 성능도 나쁘지 않아서 이번에는 gRPC를 선택했습니다. Spring Boot 마이크로서비스 간의 통신 문제입니다. 또한 gRPC에는 서비스 검색, 로드 밸런싱 및 기타 기능이 없지만 Istio는 이 점에서 매우 강력하며 둘은 완벽한 보완 관계를 형성합니다.

다양한 grpc-spring-boot-starter가 Spring Boot와 Istio 통합에 대해 알 수 없는 부작용이 있을 수 있다는 점을 고려하여 이번에는 grpc-spring-boot-starter를 사용하지 않고 직접 작성했습니다. gRPC 통합 그리고 스프링 부트. gRPC와 Spring Boot를 통합하기 위해 타사 프레임워크를 사용하고 싶지 않은 경우 간단한 구현 방법을 참조할 수 있습니다.

1.2. 비즈니스 코드 작성

먼저 Spring 초기화를 사용하여 상위 프로젝트 spring-boot-istio를 설정하고 gRPC 종속성을 도입합니다. pom 파일은 다음과 같습니다:

<?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" 
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <modules>
        <module>spring-boot-istio-api</module>
        <module>spring-boot-istio-server</module>
        <module>spring-boot-istio-client</module>
    </modules>
    <parent>
        <groupId>org.springframework.boot</groupId> 
       <artifactId>spring-boot-starter-parent</artifactId> 
       <version>2.2.6.RELEASE</version>
       <relativePath/>
     </parent>
    <groupId>site.wendev</groupId>
    <artifactId>spring-boot-istio</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>spring-boot-istio</name>
    <description>Demo project for Spring Boot With Istio.</description>
    <packaging>pom</packaging>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>io.grpc</groupId>
                <artifactId>grpc-all</artifactId>
                <version>1.28.1</version>
            </dependency>
        </dependencies>
    </dependencyManagement>
</project>
로그인 후 복사

그런 다음 공개 종속성 모듈 spring-boot-istio-api를 생성합니다. pom 파일은 다음과 같습니다. 주로 gRPC의 일부 종속성입니다:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>spring-boot-istio</artifactId>
        <groupId>site.wendev</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>spring-boot-istio-api</artifactId>
    <dependencies>
        <dependency>
            <groupId>io.grpc</groupId>
            <artifactId>grpc-all</artifactId>
        </dependency>
        <dependency>
            <groupId>javax.annotation</groupId>
            <artifactId>javax.annotation-api</artifactId>
            <version>1.3.2</version> 
       </dependency>
    </dependencies> 
   <build>
        <extensions>
            <extension>
                <groupId>kr.motd.maven</groupId>
                <artifactId>os-maven-plugin</artifactId>
                <version>1.6.2</version>
            </extension>
        </extensions>
        <plugins>
            <plugin> 
               <groupId>org.xolstice.maven.plugins</groupId>
                <artifactId>protobuf-maven-plugin</artifactId>
                <version>0.6.1</version>
                <configuration>
                    <protocArtifact>com.google.protobuf:protoc:3.11.3:exe:${os.detected.classifier}</protocArtifact>
                    <pluginId>grpc-java</pluginId>
                    <pluginArtifact>io.grpc:protoc-gen-grpc-java:1.28.1:exe:${os.detected.classifier}</pluginArtifact>
                    <protocExecutable>/Users/jiangwen/tools/protoc-3.11.3/bin/protoc</protocExecutable>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>compile</goal>
                            <goal>compile-custom</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>
로그인 후 복사

src/main/proto 폴더를 생성하고 create hello 이 폴더 아래에 .proto는 서비스 간 인터페이스를 다음과 같이 정의합니다:

syntax = "proto3";
option java_package = "site.wendev.spring.boot.istio.api";
option java_outer_classname = "HelloWorldService";
package helloworld;

service HelloWorld {
    rpc SayHello (HelloRequest)
 returns (HelloResponse) {}
}

message HelloRequest {
    string name = 1;
}
message HelloResponse {
    string message = 1;
}
로그인 후 복사

매우 간단합니다. 이름을 보내고 이름이 포함된 메시지를 반환하면 됩니다.

그런 다음 서버 및 클라이언트 코드를 생성하여 java 폴더에 넣으세요. 이 부분에 대해서는 gRPC 공식 문서를 참고하시기 바랍니다.

API 모듈이 사용 가능해지면 서비스 제공자(서버)와 서비스 소비자(클라이언트)가 개발될 수 있습니다. 여기서는 gRPC와 Spring Boot를 통합하는 방법에 중점을 둡니다.

1) 서버 측

비즈니스 코드는 매우 간단합니다.

/**
 * 服务端业务逻辑实现
 * 
 * @author 江文
 * @date 2020/4/12 2:49 下午
 */
@Slf4j
@Component
public class HelloServiceImpl extends HelloWorldGrpc.HelloWorldImplBase {
    @Override
    public void sayHello(HelloWorldService.HelloRequest request,
                         StreamObserver<HelloWorldService.HelloResponse> responseObserver) {
        // 根据请求对象建立响应对象,返回响应信息
        HelloWorldService.HelloResponse response = HelloWorldService.HelloResponse
                .newBuilder()
                .setMessage(String.format("Hello, %s. This message comes from gRPC.", request.getName()))
                .build();
        responseObserver.onNext(response);
        responseObserver.onCompleted();
        log.info("Client Message Received:[{}]", request.getName());
    }
}
로그인 후 복사

비즈니스 코드 외에도 애플리케이션이 시작될 때 동시에 gRPC 서버도 시작해야 합니다. 먼저 서버 측에 시작, 종료 및 기타 로직을 작성합니다.

/**
 * gRPC Server的配置——启动、关闭等
 * 需要使用<code>@Component</code>注解注册为一个Spring Bean
 * 
 * @author 江文
 * @date 2020/4/12 2:56 下午
 */
@Slf4j
@Componentpublic class GrpcServerConfiguration {
    @Autowired
    HelloServiceImpl service;
    /** 注入配置文件中的端口信息 */ 
   @Value("${grpc.server-port}")
    private int port;
    private Server server;
    public void start() throws IOException {
        // 构建服务端
        log.info("Starting gRPC on port {}.", port);
        server = ServerBuilder.forPort(port).addService(service).build().start();
        log.info("gRPC server started, listening on {}.", port);
        // 添加服务端关闭的逻辑
        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
            log.info("Shutting down gRPC server.");
            GrpcServerConfiguration.this.stop();
            log.info("gRPC server shut down successfully.");
        }));
    }
    private void stop() {
        if (server != null) {
            // 关闭服务端
            server.shutdown();
        }
    }
    public void block() throws InterruptedException {
        if (server != null) {
            // 服务端启动后直到应用关闭都处于阻塞状态,方便接收请求 
           server.awaitTermination();
        }
    }
}
로그인 후 복사

gRPC의 시작, 중지 및 기타 로직을 정의한 후 CommandLineRunner를 사용하여 이를 Spring Boot의 시작에 추가할 수 있습니다.

/** 
 * 加入gRPC Server的启动、停止等逻辑到Spring Boot的生命周期中
 *
 * @author 江文
 * @date 2020/4/12 3:10 下午
 */
@Component
public class GrpcCommandLineRunner implements CommandLineRunner {
    @Autowired
    GrpcServerConfiguration configuration;

    @Override
    public void run(String... args) throws Exception {
        configuration.start();
        configuration.block();
    }
}
로그인 후 복사

등록하겠습니다. gRPC의 로직 인스턴스를 얻고 해당 작업을 수행해야 하기 때문에 Spring Bean이 됩니다.

이렇게 하면 Spring Boot 시작 시 CommandLineRunner가 있기 때문에 gRPC 서버도 함께 시작할 수 있습니다.

2) 클라이언트

비즈니스 코드도 매우 간단합니다.

/**
 * 客户端业务逻辑实现
 *
 * @author 江文
 * @date 2020/4/12 3:26 下午
 */
@RestController
@Slf4j
public class HelloController {
    @Autowired
    GrpcClientConfiguration configuration;
    @GetMapping("/hello")
    public String hello(@RequestParam(name = "name", defaultValue = "JiangWen", required = false) String name) {
        // 构建一个请求        HelloWorldService.HelloRequest request = HelloWorldService.HelloRequest
                .newBuilder()
                .setName(name)
                .build();        // 使用stub发送请求至服务端
        HelloWorldService.HelloResponse response = configuration.getStub().sayHello(request);
        log.info("Server response received: [{}]", response.getMessage());
        return response.getMessage();
    }
}
로그인 후 복사

在启动客户端时,我们需要打开gRPC的客户端,并获取到channel和stub以进行RPC通信,来看看gRPC客户端的实现逻辑:

/**
 * gRPC Client的配置——启动、建立channel、获取stub、关闭等
 * 需要注册为Spring Bean
 *
 * @author 江文
 * @date 2020/4/12 3:27 下午
 */
@Slf4j
@Component
public class GrpcClientConfiguration {
    /** gRPC Server的地址 */
    @Value("${server-host}")
    private String host;
    /** gRPC Server的端口 */
    @Value("${server-port}")
    private int port;
    private ManagedChannel channel;
    private HelloWorldGrpc.HelloWorldBlockingStub stub;
    public void start() {
        // 开启channel
        channel = ManagedChannelBuilder.forAddress(host, port).usePlaintext().build();
        // 通过channel获取到服务端的stub
        stub = HelloWorldGrpc.newBlockingStub(channel);
        log.info("gRPC client started, server address: {}:{}", host, port);
    }
    public void shutdown() throws InterruptedException {
        // 调用shutdown方法后等待1秒关闭channel
        channel.shutdown().awaitTermination(1, TimeUnit.SECONDS);
        log.info("gRPC client shut down successfully.");
    }
    public HelloWorldGrpc.HelloWorldBlockingStub getStub() {
        return this.stub;
    }
}
로그인 후 복사

比服务端要简单一些。

最后,仍然需要一个CommandLineRunner把这些启动逻辑加入到Spring Boot的启动过程中:

/**
 * 加入gRPC Client的启动、停止等逻辑到Spring Boot生命周期中
 *
 * @author 江文
 * @date 2020/4/12 3:36 下午
 */
@Component
@Slf4j
public class GrpcClientCommandLineRunner implements CommandLineRunner {
    @Autowired
    GrpcClientConfiguration configuration;

    @Override
    public void run(String... args) {
        // 开启gRPC客户端
        configuration.start();
                // 添加客户端关闭的逻辑
        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
            try {
                configuration.shutdown();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }));
    }
}
로그인 후 복사

1.3、 编写Dockerfile

业务代码跑通之后,就可以制作Docker镜像,准备部署到Istio中去了。

在开始编写Dockerfile之前,先改动一下客户端的配置文件:

server:
  port: 19090
spring:
  application:
      name: spring-boot-istio-clientserver-host: ${server-host}server-port: ${server-port}
로그인 후 복사

接下来编写Dockerfile:

1) 服务端:

FROM openjdk:8u121-jdk
RUN /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
  && echo &#39;Asia/Shanghai&#39; >/etc/timezone
ADD /target/spring-boot-istio-server-0.0.1-SNAPSHOT.jar /ENV
 SERVER_PORT="18080" ENTRYPOINT java -jar /spring-boot-istio-server-0.0.1-SNAPSHOT.jar
로그인 후 복사

主要是规定服务端应用的端口为18080,并且在容器启动时让服务端也一起启动。

2) 客户端:

FROM openjdk:8u121-jdk
RUN /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
  && echo &#39;Asia/Shanghai&#39; >/etc/timezoneADD /target/spring-boot-istio-client-0.0.1-SNAPSHOT.jar /ENV GRPC_SERVER_HOST="spring-boot-istio-server"ENV GRPC_SERVER_PORT="18888"ENTRYPOINT java -jar /spring-boot-istio-client-0.0.1-SNAPSHOT.jar \ --server-host=$GRPC_SERVER_HOST \ --server-port=$GRPC_SERVER_PORT
로그인 후 복사

可以看到这里添加了启动参数,配合前面的配置,当这个镜像部署到Kubernetes集群时,就可以在Kubernetes的配合之下通过服务名找到服务端了。

同时,服务端和客户端的pom文件中添加:

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <executable>true</executable>
                </configuration>
            </plugin>
            <plugin>
                <groupId>com.spotify</groupId> 
               <artifactId>dockerfile-maven-plugin</artifactId>
                <version>1.4.13</version>
                <dependencies>
                    <dependency>
                        <groupId>javax.activation</groupId>
                        <artifactId>activation</artifactId>
                        <version>1.1</version>
                    </dependency>
                </dependencies>
                <executions>
                    <execution>
                        <id>default</id> 
                       <goals>
                            <goal>build</goal>
                            <goal>push</goal>
                       </goals>
                    </execution>
                </executions>
                <configuration>
                    <repository>wendev-docker.pkg.coding.net/develop/docker/${project.artifactId}</repository>
                    <tag>${project.version}</tag>
                    <buildArgs>
                        <JAR_FILE>${project.build.finalName}.jar</JAR_FILE>
                    </buildArgs>
                </configuration>
            </plugin>
        </plugins>
    </build>
로그인 후 복사

这样执行mvn clean package时就可以同时把docker镜像构建出来了。

2. 编写部署文件

有了镜像之后,就可以写部署文件了:

1) 服务端:

apiVersion: v1
kind:
 Servicemetadata:
  name: spring-boot-istio-server
spec:
  type: ClusterIP
  ports:
    - name: http 
      port: 18080
      targetPort: 18080
    - name: grpc
      port: 18888
      targetPort: 18888
  selector:
    app: spring-boot-istio-server

---apiVersion: apps/v1
kind:
 Deploymentmetadata:
  name: spring-boot-istio-server
spec:
  replicas: 1
  selector:
    matchLabels:
      app: spring-boot-istio-server
  template:
    metadata:
      labels:
        app: spring-boot-istio-server
    spec:
      containers:
        - name: spring-boot-istio-server
          image: wendev-docker.pkg.coding.net/develop/docker/spring-boot-istio-server:0.0.1-SNAPSHOT
          imagePullPolicy: Always
          tty: true
          ports:
            - name: http
              protocol: TCP
              containerPort: 18080 
            - name: grpc
              protocol: TCP
              containerPort: 18888
로그인 후 복사

主要是暴露服务端的端口:18080和gRPC Server的端口18888,以便可以从Pod外部访问服务端。

2) 客户端:

apiVersion: v1
kind:
 Servicemetadata:
  name:
 spring-boot-istio-client
spec:
  type: ClusterIP
  ports:
    - name: http
      port: 19090
      targetPort: 19090
  selector:
    app: spring-boot-istio-client

---apiVersion: apps/v1
kind:
 Deploymentmetadata:
  name: spring-boot-istio-client
spec:
  replicas: 1
  selector:
    matchLabels:
      app: spring-boot-istio-client
  template:
    metadata:
      labels:
        app: spring-boot-istio-client
    spec:
      containers:
        - name: spring-boot-istio-client
          image: wendev-docker.pkg.coding.net/develop/docker/spring-boot-istio-client:0.0.1-SNAPSHOT
          imagePullPolicy: Always
          tty: true
          ports:
            - name: http 
             protocol: TCP
              containerPort: 19090
로그인 후 복사

主要是暴露客户端的端口19090,以便访问客户端并调用服务端。

如果想先试试把它们部署到k8s可不可以正常访问,可以这样配置Ingress:

apiVersion: networking.k8s.io/v1beta1
kind:
 Ingressmetadata:
  name: nginx-web
  annotations:
    kubernetes.io/ingress.class: "nginx"
    nginx.ingress.kubernetes.io/use-reges: "true"
    nginx.ingress.kubernetes.io/proxy-connect-timeout: "600"
    nginx.ingress.kubernetes.io/proxy-send-timeout: "600"
    nginx.ingress.kubernetes.io/proxy-read-timeout: "600"
    nginx.ingress.kubernetes.io/proxy-body-size: "10m"
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
    - host: dev.wendev.site
      http:
        paths:
          - path: /
            backend:
              serviceName: spring-boot-istio-client
              servicePort: 19090
로그인 후 복사

Istio的网关配置文件与k8s不大一样:

apiVersion: networking.istio.io/v1alpha3
kind:
 Gatewaymetadata:
  name: spring-boot-istio-gateway
spec:
  selector:
    istio: ingressgateway
  servers:
    - port:
        number: 80
        name: http
        protocol: HTTP
      hosts:
        - "*"

---apiVersion: networking.istio.io/v1alpha3
kind: Virtual
Servicemetadata:
  name: spring-boot-istio
spec:
  hosts:
    - "*"
  gateways:
    - spring-boot-istio-gateway
  http:
    - match:
        - uri:
            exact: /hello
      route:
        - destination:
            host: spring-boot-istio-client
            port:
              number: 19090
로그인 후 복사

主要就是暴露/hello这个路径,并且指定对应的服务和端口。

3. 部署应用到Istio

首先搭建k8s集群并且安装istio。我使用的k8s版本是1.16.0,Istio版本是最新的1.6.0-alpha.1,使用istioctl命令安装Istio。建议跑通官方的bookinfo示例之后再来部署本项目。

注:以下命令都是在开启了自动注入Sidecar的前提下运行的

我是在虚拟机中运行的k8s,所以istio-ingressgateway没有外部ip:

$ kubectl get svc istio-ingressgateway -n istio-system
NAME                   TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S) 
                                                                                                                                     
AGEistio-ingressgateway   NodePort   10.97.158.232   <none>        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
로그인 후 복사

所以,需要设置IP和端口,以NodePort的方式访问gateway:

export INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath=&#39;{.spec.ports[?(@.name=="http2")].nodePort}&#39;)
export SECURE_INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath=&#39;{.spec.ports[?(@.name=="https")].nodePort}&#39;)
export INGRESS_HOST=127.0.0.1export GATEWAY_URL=$INGRESS_HOST:$INGRESS_PORT
로그인 후 복사

这样就可以了。

接下来部署服务:

$ kubectl apply -f spring-boot-istio-server.yml
$ kubectl apply -f spring-boot-istio-client.yml
$ kubectl apply -f istio-gateway.yml
로그인 후 복사

必须要等到两个pod全部变为Running而且Ready变为2/2才算部署完成。

接下来就可以通过

curl -s http://${GATEWAY_URL}/hello
로그인 후 복사

访问到服务了。如果成功返回了Hello, JiangWen. This message comes from gRPC.的结果,没有出错则说明部署完成。

위 내용은 Spring Boot+gRPC를 사용하여 마이크로서비스를 구축하고 배포하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

Springboot가 Jasypt를 통합하여 구성 파일 암호화를 구현하는 방법 Springboot가 Jasypt를 통합하여 구성 파일 암호화를 구현하는 방법 Jun 01, 2023 am 08:55 AM

Jasypt 소개 Jasypt는 개발자가 최소한의 노력으로 프로젝트에 기본 암호화 기능을 추가할 수 있게 해주며 암호화 작동 방식에 대한 깊은 이해가 필요하지 않은 단방향 및 양방향 암호화에 대한 높은 보안을 제공합니다. 표준 기반 암호화 기술. 비밀번호, 텍스트, 숫자, 바이너리 암호화... Spring 기반 애플리케이션, 개방형 API와의 통합에 적합하며 모든 JCE 공급자와 함께 사용할 수 있습니다... 다음 종속성을 추가합니다: com.github.ulisesbocchiojasypt-spring-boot-starter2. Jasypt의 이점은 코드가 유출되더라도 데이터 소스를 보장할 수 있어 시스템 보안을 보호합니다.

Redis를 사용하여 SpringBoot에서 분산 잠금을 구현하는 방법 Redis를 사용하여 SpringBoot에서 분산 잠금을 구현하는 방법 Jun 03, 2023 am 08:16 AM

1. Redis는 분산 잠금 원칙과 분산 잠금이 필요한 이유를 구현합니다. 분산 잠금에 대해 이야기하기 전에 분산 잠금이 필요한 이유를 설명해야 합니다. 분산 잠금의 반대는 독립형 잠금입니다. 다중 스레드 프로그램을 작성할 때 공유 변수를 동시에 작동하여 발생하는 데이터 문제를 방지하기 위해 일반적으로 잠금을 사용하여 공유 변수를 상호 제외합니다. 공유 변수의 사용 범위는 동일한 프로세스에 있습니다. 동시에 공유 리소스를 운영해야 하는 여러 프로세스가 있는 경우 어떻게 상호 배타적일 수 있습니까? 오늘날의 비즈니스 애플리케이션은 일반적으로 마이크로서비스 아키텍처입니다. 이는 하나의 애플리케이션이 여러 프로세스를 배포한다는 의미이기도 합니다. 여러 프로세스가 MySQL에서 동일한 레코드 행을 수정해야 하는 경우 잘못된 작업으로 인해 발생하는 더티 데이터를 방지하려면 배포가 필요합니다. 현재 소개할 스타일은 잠겨 있습니다. 포인트를 얻고 싶다

springboot가 파일을 jar 패키지로 읽은 후 파일에 액세스할 수 없는 문제를 해결하는 방법 springboot가 파일을 jar 패키지로 읽은 후 파일에 액세스할 수 없는 문제를 해결하는 방법 Jun 03, 2023 pm 04:38 PM

Springboot가 파일을 읽지만 jar 패키지로 패키징한 후 최신 개발에 액세스할 수 없습니다. springboot가 파일을 jar 패키지로 패키징한 후 파일을 읽을 수 없는 상황이 발생합니다. 그 이유는 패키징 후 파일의 가상 경로 때문입니다. 유효하지 않으며 읽기를 통해서만 액세스할 수 있습니다. 파일은 리소스 publicvoidtest(){Listnames=newArrayList();InputStreamReaderread=null;try{ClassPathResourceresource=newClassPathResource("name.txt");Input 아래에 있습니다.

SpringBoot와 SpringMVC의 비교 및 ​​차이점 분석 SpringBoot와 SpringMVC의 비교 및 ​​차이점 분석 Dec 29, 2023 am 11:02 AM

SpringBoot와 SpringMVC는 모두 Java 개발에서 일반적으로 사용되는 프레임워크이지만 둘 사이에는 몇 가지 분명한 차이점이 있습니다. 이 기사에서는 이 두 프레임워크의 기능과 용도를 살펴보고 차이점을 비교할 것입니다. 먼저 SpringBoot에 대해 알아봅시다. SpringBoot는 Spring 프레임워크를 기반으로 하는 애플리케이션의 생성 및 배포를 단순화하기 위해 Pivotal 팀에서 개발되었습니다. 독립 실행형 실행 파일을 구축하는 빠르고 가벼운 방법을 제공합니다.

gRPC를 사용하여 Golang에서 파일 업로드를 구현하는 방법은 무엇입니까? gRPC를 사용하여 Golang에서 파일 업로드를 구현하는 방법은 무엇입니까? Jun 03, 2024 pm 04:54 PM

gRPC를 사용하여 파일 업로드를 구현하는 방법은 무엇입니까? 요청 및 응답 메시지를 포함하여 지원 서비스 정의를 만듭니다. 클라이언트에서는 업로드할 파일이 열리고 청크로 분할된 다음 gRPC 스트림을 통해 서버로 스트리밍됩니다. 서버 측에서는 파일 청크가 수신되어 파일에 저장됩니다. 서버는 파일 업로드가 완료된 후 업로드 성공 여부를 나타내는 응답을 보냅니다.

SpringBoot가 Redis를 사용자 정의하여 캐시 직렬화를 구현하는 방법 SpringBoot가 Redis를 사용자 정의하여 캐시 직렬화를 구현하는 방법 Jun 03, 2023 am 11:32 AM

1. RedisAPI 기본 직렬화 메커니즘인 RedisTemplate1.1을 사용자 정의합니다. API 기반 Redis 캐시 구현은 데이터 캐싱 작업에 RedisTemplate 템플릿을 사용합니다. 여기서 RedisTemplate 클래스를 열고 클래스의 소스 코드 정보를 봅니다. 키 선언, 값의 다양한 직렬화 방법, 초기 값은 비어 있음 @NullableprivateRedisSe

여러 테이블을 추가하기 위해 SQL 문을 사용하지 않고 Springboot+Mybatis-plus를 구현하는 방법 여러 테이블을 추가하기 위해 SQL 문을 사용하지 않고 Springboot+Mybatis-plus를 구현하는 방법 Jun 02, 2023 am 11:07 AM

Springboot+Mybatis-plus가 다중 테이블 추가 작업을 수행하기 위해 SQL 문을 사용하지 않을 때 내가 직면한 문제는 테스트 환경에서 생각을 시뮬레이션하여 분해됩니다. 매개 변수가 있는 BrandDTO 개체를 생성하여 배경으로 매개 변수 전달을 시뮬레이션합니다. Mybatis-plus에서 다중 테이블 작업을 수행하는 것은 매우 어렵다는 것을 Mybatis-plus-join과 같은 도구를 사용하지 않으면 해당 Mapper.xml 파일을 구성하고 냄새나고 긴 ResultMap만 구성하면 됩니다. 해당 SQL 문을 작성합니다. 이 방법은 번거로워 보이지만 매우 유연하며 다음을 수행할 수 있습니다.

springboot에서 application.yml의 값을 얻는 방법 springboot에서 application.yml의 값을 얻는 방법 Jun 03, 2023 pm 06:43 PM

프로젝트에서는 일부 구성 정보가 필요한 경우가 많습니다. 이 정보는 테스트 환경과 프로덕션 환경에서 구성이 다를 수 있으며 실제 비즈니스 상황에 따라 나중에 수정해야 할 수도 있습니다. 이러한 구성은 코드에 하드 코딩할 수 없습니다. 예를 들어 이 정보를 application.yml 파일에 작성할 수 있습니다. 그렇다면 코드에서 이 주소를 어떻게 얻거나 사용합니까? 2가지 방법이 있습니다. 방법 1: @Value 주석이 달린 ${key}를 통해 구성 파일(application.yml)의 키에 해당하는 값을 가져올 수 있습니다. 이 방법은 마이크로서비스가 상대적으로 적은 상황에 적합합니다. 프로젝트, 업무가 복잡할 때는 논리

See all articles