1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        Spring Boot+gRPC構(gòu)建微服務(wù)并部署到Istio(詳細(xì)教程)

        共 35231字,需瀏覽 71分鐘

         ·

        2022-06-25 12:40

        點(diǎn)擊關(guān)注公眾號(hào),實(shí)用技術(shù)文章及時(shí)了解

        作為Service Mesh和云原生技術(shù)的忠實(shí)擁護(hù)者,我卻一直沒(méi)有開(kāi)發(fā)過(guò)Service Mesh的應(yīng)用。正好最近受夠了Spring Cloud的“折磨”,對(duì)Kubernetes也可以熟練使用了,而且網(wǎng)上幾乎沒(méi)有Spring Boot微服務(wù)部署到Istio的案例,我就開(kāi)始考慮用Spring Boot寫(xiě)個(gè)微服務(wù)的Demo并且部署到Istio。項(xiàng)目本身不復(fù)雜,就是發(fā)送一個(gè)字符串并且返回一個(gè)字符串的最簡(jiǎn)單的Demo。

        題外話(huà):我本來(lái)是想用Spring MVC寫(xiě)的——因?yàn)橹車(chē)械耐瑢W(xué)不相信Spring MVC也可以開(kāi)發(fā)微服務(wù),但是Spring MVC的各種配置和依賴(lài)問(wèn)題把我整的想吐,為了少掉幾根頭發(fā),還是用了方便好用的Spring Boot。

        為什么要用Istio?

        目前,對(duì)于Java技術(shù)棧來(lái)說(shuō),構(gòu)建微服務(wù)的最佳選擇是Spring Boot而Spring Boot一般搭配目前落地案例很多的微服務(wù)框架Spring Cloud來(lái)使用。

        Spring Cloud看似很完美,但是在實(shí)際上手開(kāi)發(fā)后,很容易就會(huì)發(fā)現(xiàn)Spring Cloud存在以下比較嚴(yán)重的問(wèn)題:

        • 服務(wù)治理相關(guān)的邏輯存在于Spring Cloud Netflix等SDK中,與業(yè)務(wù)代碼緊密耦合。
        • SDK對(duì)業(yè)務(wù)代碼侵入太大,SDK發(fā)生升級(jí)且無(wú)法向下兼容時(shí),業(yè)務(wù)代碼必須做出改變以適配SDK的升級(jí)——即使業(yè)務(wù)邏輯并沒(méi)有發(fā)生任何變化。
        • 各種組件令人眼花繚亂,質(zhì)量也參差不齊,學(xué)習(xí)成本太高,且組件之間代碼很難完全復(fù)用,僅僅為了實(shí)現(xiàn)治理邏輯而學(xué)習(xí)SDK也并不是很好的選擇。
        • 綁定于Java技術(shù)棧,雖然可以接入其他語(yǔ)言但要手動(dòng)實(shí)現(xiàn)服務(wù)治理相關(guān)的邏輯,不符合微服務(wù)“可以用多種語(yǔ)言進(jìn)行開(kāi)發(fā)”的原則。
        • Spring Cloud僅僅是一個(gè)開(kāi)發(fā)框架,沒(méi)有實(shí)現(xiàn)微服務(wù)所必須的服務(wù)調(diào)度、資源分配等功能,這些需求要借助Kubernetes等平臺(tái)來(lái)完成。但Spring Cloud與Kubernetes功能上有重合,且部分功能也存在沖突,二者很難完美配合。

        替代Spring Cloud的選擇有沒(méi)有呢?有!它就是Istio。

        Istio徹底把治理邏輯從業(yè)務(wù)代碼中剝離出來(lái),成為了獨(dú)立的進(jìn)程(Sidecar)。部署時(shí)兩者部署在一起,在一個(gè)Pod里共同運(yùn)行,業(yè)務(wù)代碼完全感知不到Sidecar的存在。這就實(shí)現(xiàn)了治理邏輯對(duì)業(yè)務(wù)代碼的零侵入——實(shí)際上不僅是代碼沒(méi)有侵入,在運(yùn)行時(shí)兩者也沒(méi)有任何的耦合。這使得不同的微服務(wù)完全可以使用不同語(yǔ)言、不同技術(shù)棧來(lái)開(kāi)發(fā),也不用擔(dān)心服務(wù)治理問(wèn)題,可以說(shuō)這是一種很優(yōu)雅的解決方案了。

        所以,“為什么要使用Istio”這個(gè)問(wèn)題也就迎刃而解了——因?yàn)镮stio解決了傳統(tǒng)微服務(wù)諸如業(yè)務(wù)邏輯與服務(wù)治理邏輯耦合、不能很好地實(shí)現(xiàn)跨語(yǔ)言等痛點(diǎn),而且非常容易使用。只要會(huì)用Kubernetes,學(xué)習(xí)Istio的使用一點(diǎn)都不困難。

        為什么要使用gRPC作為通信框架?

        在微服務(wù)架構(gòu)中,服務(wù)之間的通信是一個(gè)比較大的問(wèn)題,一般采用RPC或者RESTful API來(lái)實(shí)現(xiàn)。

        Spring Boot可以使用RestTemplate調(diào)用遠(yuǎn)程服務(wù),但這種方式不直觀(guān),代碼也比較復(fù)雜,進(jìn)行跨語(yǔ)言通信也是個(gè)比較大的問(wèn)題;而gRPC相比Dubbo等常見(jiàn)的Java RPC框架更加輕量,使用起來(lái)也很方便,代碼可讀性高,并且與Istio和Kubernetes可以很好地進(jìn)行整合,在Protobuf和HTTP2的加持下性能也還不錯(cuò),所以這次選擇了gRPC來(lái)解決Spring Boot微服務(wù)間通信的問(wèn)題。并且,雖然gRPC沒(méi)有服務(wù)發(fā)現(xiàn)、負(fù)載均衡等能力,但是Istio在這方面就非常強(qiáng)大,兩者形成了完美的互補(bǔ)關(guān)系。


        微信搜索公眾號(hào):Java項(xiàng)目精選,回復(fù):java 領(lǐng)取資料 。

        由于考慮到各種grpc-spring-boot-starter可能會(huì)對(duì)Spring Boot與Istio的整合產(chǎn)生不可知的副作用,所以這一次我沒(méi)有用任何的grpc-spring-boot-starter,而是直接手寫(xiě)了gRPC與Spring Boot的整合。不想借助第三方框架整合gRPC和Spring Boot的可以簡(jiǎn)單參考一下我的實(shí)現(xiàn)。

        編寫(xiě)業(yè)務(wù)代碼

        首先使用Spring Initializr建立父級(jí)項(xiàng)目spring-boot-istio,并引入gRPC的依賴(lài)。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/> <!-- lookup parent from repository -->
            </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>

        然后建立公共依賴(lài)模塊spring-boot-istio-api,pom文件如下,主要就是gRPC的一些依賴(lài):

        <?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文件夾,在此文件夾下建立hello.proto,定義服務(wù)間的接口如下:

        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;
        }

        很簡(jiǎn)單,就是發(fā)送一個(gè)name返回一個(gè)帶name的message。

        然后生成服務(wù)端和客戶(hù)端的代碼,并且放到j(luò)ava文件夾下。這部分內(nèi)容可以參考gRPC的官方文檔。

        有了API模塊之后,就可以編寫(xiě)服務(wù)提供者(服務(wù)端)和服務(wù)消費(fèi)者(客戶(hù)端)了。這里我們重點(diǎn)看一下如何整合gRPC和Spring Boot。

        服務(wù)端

        業(yè)務(wù)代碼非常簡(jiǎn)單:

        /**
         * 服務(wù)端業(yè)務(wù)邏輯實(shí)現(xiàn)
         *
         * @author 江文
         */

        @Slf4j
        @Component
        public class HelloServiceImpl extends HelloWorldGrpc.HelloWorldImplBase {
            @Override
            public void sayHello(HelloWorldService.HelloRequest request,
                                 StreamObserver<HelloWorldService.HelloResponse> responseObserver)
         
        {
                // 根據(jù)請(qǐng)求對(duì)象建立響應(yīng)對(duì)象,返回響應(yīng)信息
                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());
            }
        }

        光有業(yè)務(wù)代碼還不行,我們還需要在應(yīng)用啟動(dòng)時(shí)把gRPC Server也給一起啟動(dòng)起來(lái)。首先寫(xiě)一下Server端的啟動(dòng)、關(guān)閉等邏輯:

        /**
         * gRPC Server的配置——啟動(dòng)、關(guān)閉等
         * 需要使用<code>@Component</code>注解注冊(cè)為一個(gè)Spring Bean
         *
         * @author 江文
         */

        @Slf4j
        @Component
        public class GrpcServerConfiguration {
            @Autowired
            HelloServiceImpl service;

            /** 注入配置文件中的端口信息 */
            @Value("${grpc.server-port}")
            private int port;
            private Server server;

            public void start() throws IOException {
                // 構(gòu)建服務(wù)端
                log.info("Starting gRPC on port {}.", port);
                server = ServerBuilder.forPort(port).addService(service).build().start();
                log.info("gRPC server started, listening on {}.", port);

                // 添加服務(wù)端關(guān)閉的邏輯
                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) {
                    // 關(guān)閉服務(wù)端
                    server.shutdown();
                }
            }

            public void block() throws InterruptedException {
                if (server != null) {
                    // 服務(wù)端啟動(dòng)后直到應(yīng)用關(guān)閉都處于阻塞狀態(tài),方便接收請(qǐng)求
                    server.awaitTermination();
                }
            }
        }

        定義好gRPC的啟動(dòng)、停止等邏輯后,就可以使用CommandLineRunner把它加入到Spring Boot的啟動(dòng)中去了:

        /**
         * 加入gRPC Server的啟動(dòng)、停止等邏輯到Spring Boot的生命周期中
         *
         * @author 江文
         */

        @Component
        public class GrpcCommandLineRunner implements CommandLineRunner {
            @Autowired
            GrpcServerConfiguration configuration;

            @Override
            public void run(String... args) throws Exception {
                configuration.start();
                configuration.block();
            }
        }

        之所以要把gRPC的邏輯注冊(cè)成Spring Bean,就是因?yàn)樵谶@里要獲取到它的實(shí)例并進(jìn)行相應(yīng)的操作。

        這樣,在啟動(dòng)Spring Boot時(shí),由于CommandLineRunner的存在,gRPC服務(wù)端也就可以一同啟動(dòng)了。

        客戶(hù)端

        業(yè)務(wù)代碼同樣非常簡(jiǎn)單:

        /**
         * 客戶(hù)端業(yè)務(wù)邏輯實(shí)現(xiàn)
         *
         * @author 江文
         */

        @RestController
        @Slf4j
        public class HelloController {
            @Autowired
            GrpcClientConfiguration configuration;

            @GetMapping("/hello")
            public String hello(@RequestParam(name = "name", defaultValue = "JiangWen", required = false) String name) {
                // 構(gòu)建一個(gè)請(qǐng)求
                HelloWorldService.HelloRequest request = HelloWorldService.HelloRequest
                        .newBuilder()
                        .setName(name)
                        .build();

                // 使用stub發(fā)送請(qǐng)求至服務(wù)端
                HelloWorldService.HelloResponse response = configuration.getStub().sayHello(request);
                log.info("Server response received: [{}]", response.getMessage());
                return response.getMessage();
            }
        }

        在啟動(dòng)客戶(hù)端時(shí),我們需要打開(kāi)gRPC的客戶(hù)端,并獲取到channel和stub以進(jìn)行RPC通信,來(lái)看看gRPC客戶(hù)端的實(shí)現(xiàn)邏輯:

        /**
         * gRPC Client的配置——啟動(dòng)、建立channel、獲取stub、關(guān)閉等
         * 需要注冊(cè)為Spring Bean
         *
         * @author 江文
         */

        @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() {
                // 開(kāi)啟channel
                channel = ManagedChannelBuilder.forAddress(host, port).usePlaintext().build();

                // 通過(guò)channel獲取到服務(wù)端的stub
                stub = HelloWorldGrpc.newBlockingStub(channel);
                log.info("gRPC client started, server address: {}:{}", host, port);
            }

            public void shutdown() throws InterruptedException {
                // 調(diào)用shutdown方法后等待1秒關(guān)閉channel
                channel.shutdown().awaitTermination(1, TimeUnit.SECONDS);
                log.info("gRPC client shut down successfully.");
            }

            public HelloWorldGrpc.HelloWorldBlockingStub getStub() {
                return this.stub;
            }
        }

        比服務(wù)端要簡(jiǎn)單一些。

        最后,仍然需要一個(gè)CommandLineRunner把這些啟動(dòng)邏輯加入到Spring Boot的啟動(dòng)過(guò)程中:

        /**
         * 加入gRPC Client的啟動(dòng)、停止等邏輯到Spring Boot生命周期中
         *
         * @author 江文
         */

        @Component
        @Slf4j
        public class GrpcClientCommandLineRunner implements CommandLineRunner {
            @Autowired
            GrpcClientConfiguration configuration;

            @Override
            public void run(String... args) {
                // 開(kāi)啟gRPC客戶(hù)端
                configuration.start();
                
                // 添加客戶(hù)端關(guān)閉的邏輯
                Runtime.getRuntime().addShutdownHook(new Thread(() -> {
                    try {
                        configuration.shutdown();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }));
            }
        }

        編寫(xiě)Dockerfile

        業(yè)務(wù)代碼跑通之后,就可以制作Docker鏡像,準(zhǔn)備部署到Istio中去了。

        在開(kāi)始編寫(xiě)Dockerfile之前,先改動(dòng)一下客戶(hù)端的配置文件:

        server:
          port: 19090
        spring:
          application:
            name: spring-boot-istio-client
        server-host: ${server-host}
        server-port: ${server-port}

        接下來(lái)編寫(xiě)Dockerfile:

        服務(wù)端:

        FROM openjdk:8u121-jdk
        RUN /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
          && echo 'Asia/Shanghai' >/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

        可以看到這里添加了啟動(dòng)參數(shù),配合前面的配置,當(dāng)這個(gè)鏡像部署到Kubernetes集群時(shí),就可以在Kubernetes的配合之下通過(guò)服務(wù)名找到服務(wù)端了。

        同時(shí),服務(wù)端和客戶(hù)端的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>

        這樣執(zhí)行mvn clean package時(shí)就可以同時(shí)把docker鏡像構(gòu)建出來(lái)了。

        編寫(xiě)部署文件

        有了鏡像之后,就可以寫(xiě)部署文件了:

        服務(wù)端:

        apiVersion: v1
        kind: Service
        metadata:
          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: Deployment
        metadata:
          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

        主要是暴露服務(wù)端的端口:18080和gRPC Server的端口18888,以便可以從Pod外部訪(fǎng)問(wèn)服務(wù)端。

        客戶(hù)端:

        apiVersion: v1
        kind: Service
        metadata:
          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: Deployment
        metadata:
          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

        主要是暴露客戶(hù)端的端口19090,以便訪(fǎng)問(wèn)客戶(hù)端并調(diào)用服務(wù)端。

        如果想先試試把它們部署到k8s可不可以正常訪(fǎng)問(wèn),可以這樣配置Ingress:

        apiVersion: networking.k8s.io/v1beta1
        kind: Ingress
        metadata:
          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的網(wǎng)關(guān)配置文件與k8s不大一樣:

        apiVersion: networking.istio.io/v1alpha3
        kind: Gateway
        metadata:
          name: spring-boot-istio-gateway
        spec:
          selector:
            istio: ingressgateway
          servers:
            - port:
                number: 80
                name: http
                protocol: HTTP
              hosts:
                - "*"
        ---
        apiVersion: networking.istio.io/v1alpha3
        kind: VirtualService
        metadata:
          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這個(gè)路徑,并且指定對(duì)應(yīng)的服務(wù)和端口。

        部署應(yīng)用到Istio

        首先搭建k8s集群并且安裝istio。我使用的k8s版本是1.16.0,Istio版本是最新的1.6.0-alpha.1,使用istioctl命令安裝Istio。建議跑通官方的bookinfo示例之后再來(lái)部署本項(xiàng)目。

        注:以下命令都是在開(kāi)啟了自動(dòng)注入Sidecar的前提下運(yùn)行的

        我是在虛擬機(jī)中運(yùn)行的k8s,所以istio-ingressgateway沒(méi)有外部ip:

        $ kubectl get svc istio-ingressgateway -n istio-system
        NAME                   TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)                                                                                                                                      AGE
        istio-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

        所以,需要設(shè)置IP和端口,以NodePort的方式訪(fǎng)問(wèn)gateway:

        export INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http2")].nodePort}')
        export SECURE_INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="https")].nodePort}')
        export INGRESS_HOST=127.0.0.1
        export GATEWAY_URL=$INGRESS_HOST:$INGRESS_PORT

        必須要等到兩個(gè)pod全部變?yōu)镽unning而且Ready變?yōu)?/2才算部署完成。

        接下來(lái)就可以通過(guò)

        curl -s http://${GATEWAY_URL}/hello

        訪(fǎng)問(wèn)到服務(wù)了。如果成功返回了Hello, JiangWen. This message comes from gRPC.的結(jié)果,沒(méi)有出錯(cuò)則說(shuō)明部署完成。

        來(lái)源:blog.csdn.net/weixin_43887447/article/

        details/109605564

        推薦

        基于 SpringBoot + Echarts 實(shí)現(xiàn)的動(dòng)態(tài)實(shí)時(shí)大屏

        清華學(xué)姐自學(xué)的Linux筆記,天花板級(jí)別!

        PS:因?yàn)楣娞?hào)平臺(tái)更改了推送規(guī)則,如果不想錯(cuò)過(guò)內(nèi)容,記得讀完點(diǎn)一下“在看”,加個(gè)“星標(biāo)”,這樣每次新文章推送才會(huì)第一時(shí)間出現(xiàn)在你的訂閱列表里。點(diǎn)“在看”支持我們吧!

        瀏覽 21
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            欧美大波大乳人奶 | 久久国产精品99久久久久久丝袜 | 日本一区不卡视频 | 蘑菇视频logo | 鲁丝一区二区三区免费观看 | 在线激情网址 | 国产精品久久欠久久al换脸综合 | 成人免费a片无遮挡 | 国产无码乱伦视频 | 少妇口述被4p高潮 |