最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java實現(xiàn)grpc框架的示例

 更新時間:2025年09月23日 09:59:01   作者:TanYYF  
本文主要介紹了gRPC框架及其與ProtocolBuffers的結(jié)合,用于構(gòu)建分布式系統(tǒng),文中通過示例代碼介紹的非常詳細,需要的朋友們下面隨著小編來一起學習學習吧

1.grpc簡介

官方地址:https://grpc.io/docs/what-is-grpc/introduction/

在gRPC中,客戶機應用程序可以直接調(diào)用不同機器上的服務器應用程序上的方法,就像它是本地對象一樣,使您更容易創(chuàng)建分布式應用程序和服務。與許多RPC系統(tǒng)一樣,gRPC基于定義服務的思想,指定可以遠程調(diào)用的方法及其參數(shù)和返回類型。在服務器端,服務器實現(xiàn)這個接口,并運行g(shù)RPC服務器來處理客戶端調(diào)用。在客戶端,客戶端有一個存根(在某些語言中稱為客戶端),它提供與服務器相同的方法

gRPC客戶端和服務器可以在各種環(huán)境中運行并相互通信——從Google內(nèi)部的服務器到您自己的桌面——并且可以用任何gRPC支持的語言編寫。因此,例如,您可以輕松地用Java創(chuàng)建gRPC服務器,用Go、Python或Ruby創(chuàng)建客戶端。

2.Protocol Buffers

官方地址:https://protobuf.dev/overview/

默認情況下,gRPC使用Protocol Buffers,這是Google用于序列化結(jié)構(gòu)化數(shù)據(jù)的成熟開源機制(盡管它可以與JSON等其他數(shù)據(jù)格式一起使用)
Protocol Buffers是一種語言無關(guān)、平臺無關(guān)的可擴展機制,用于序列化結(jié)構(gòu)化數(shù)據(jù)。
它類似于JSON,只是更小更快,并且生成本地語言綁定。您只需定義一次數(shù)據(jù)的結(jié)構(gòu)化方式,然后就可以使用特殊生成的源代碼輕松地將結(jié)構(gòu)化數(shù)據(jù)寫入和讀取到各種數(shù)據(jù)流,并使用各種語言。

協(xié)議緩沖區(qū)是定義語言(在.proto文件中創(chuàng)建)、proto編譯器為與數(shù)據(jù)交互而生成的代碼、特定于語言的運行時庫以及寫入文件(或通過網(wǎng)絡連接發(fā)送)的數(shù)據(jù)的序列化格式的組合

3.創(chuàng)建maven項目grpc-demo

3.1 編寫maven 配置文件

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>grpc-demo</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <!--grpc版本 -->
        <grpc.version>1.60.2</grpc.version>
    </properties>

    <dependencies>
        <!-- grpc 需要的依賴-->
        <dependency>
            <groupId>io.grpc</groupId>
            <artifactId>grpc-netty-shaded</artifactId>
            <version>${grpc.version}</version>
        </dependency>

        <dependency>
            <groupId>io.grpc</groupId>
            <artifactId>grpc-protobuf</artifactId>
            <version>${grpc.version}</version>
        </dependency>

        <dependency>
            <groupId>io.grpc</groupId>
            <artifactId>grpc-stub</artifactId>
            <version>${grpc.version}</version>
        </dependency>

    </dependencies>
    <build>
        <extensions>
            <extension>
                <groupId>kr.motd.maven</groupId>
                <artifactId>os-maven-plugin</artifactId>
                <version>1.5.0.Final</version>
            </extension>
        </extensions>
        <plugins>
            <plugin>
                <groupId>org.xolstice.maven.plugins</groupId>
                <artifactId>protobuf-maven-plugin</artifactId>
                <version>0.5.0</version>
                <configuration>
                    <protocArtifact>com.google.protobuf:protoc:3.3.0:exe:${os.detected.classifier}</protocArtifact>
                    <pluginId>grpc-java</pluginId>
                    <pluginArtifact>io.grpc:protoc-gen-grpc-java:${grpc.version}:exe:${os.detected.classifier}</pluginArtifact>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <!--它將{@code .proto}文件 生成java源代碼 -->
                            <goal>compile</goal>
                            <!--它將{@code .proto}文件 生成grpc java源代碼 -->
                            <goal>compile-custom</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <!-- 解決jar 包沖突、重復依賴、無效引用 -->
                <artifactId>maven-enforcer-plugin</artifactId>
                <version>1.4.1</version>
                <executions>
                    <execution>
                        <id>enforce</id>
                        <goals>
                            <goal>enforce</goal>
                        </goals>
                        <configuration>
                            <rules>
                                <requireUpperBoundDeps/>
                            </rules>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</project>

3.2 在/src/main/目錄下創(chuàng)建 helloworld.proto文件

官方地址: https://gitcode.com/grpc/grpc-java/blob/master/examples/src/main/proto/helloworld.proto

// Copyright 2015 The gRPC Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
syntax = "proto3";

option java_multiple_files = true;
option java_package = "io.grpc.examples.helloworld";
option java_outer_classname = "HelloWorldProto";
option objc_class_prefix = "HLW";

package helloworld;

// The greeting service definition.
service Greeter {
  // Sends a greeting
  rpc SayHello (HelloRequest) returns (HelloReply) {}
}

// The request message containing the user's name.
message HelloRequest {
  string name = 1;
}

// The response message containing the greetings
message HelloReply {
  string message = 1;
}

3.3 生成代碼

idea選中項目pom.xml-右鍵->run maven -> Plugins->protobuf-maven-plugin->protobuf:compile
或者進入到項目目錄直接執(zhí)行mvn命令:

#生成protobuf代碼
mvn protobuf:compile
#生成grpc代碼
mvn protobuf:compile-custom

生成成功的代碼如截圖,將代碼拷貝到項目對應的位置:

代碼拷貝到項目截圖:

4.代碼編寫

4.1 HelloWordServer服務端編寫

package io.grpc.examples.helloworld2;

import io.grpc.Grpc;
import io.grpc.InsecureServerCredentials;
import io.grpc.Server;
import io.grpc.examples.helloworld.GreeterGrpc;
import io.grpc.examples.helloworld.HelloReply;
import io.grpc.examples.helloworld.HelloRequest;
import io.grpc.stub.StreamObserver;

import java.io.IOException;
import java.util.Objects;
import java.util.Random;
import java.util.concurrent.TimeUnit;

/**
 * @Author tanyong
 * @Version HelloWordServer v1.0.0 2024/4/2 11:21 $$
 */
public class HelloWordServer {
    private static int port = 50052;

    /**
     * grpc服務實例
     */
    private Server server;

    /**
     * 啟動 grpc服務
     *
     * @throws IOException
     */
    public void start() throws IOException {

        server = Grpc.newServerBuilderForPort(port, InsecureServerCredentials.create())
                // 添加業(yè)務處理類
                .addService(new GreeterImpl(port))
                .build()
                .start();
        // 注冊了一個JVM關(guān)閉鉤子(Shutdown Hook),當Java虛擬機(JVM)即將關(guān)閉時(無論是正常退出還是非正常退出,如接收到操作系統(tǒng)中斷信號)當JVM關(guān)閉時,所有已注冊的關(guān)閉鉤子都將被依次調(diào)用
        Runtime.getRuntime().addShutdownHook(new Thread() {
            @Override
            public void run() {
                // Use stderr here since the logger may have been reset by its JVM shutdown hook.
                System.err.println("*** shutting down gRPC server since JVM is shutting down");
                try {
                    // 優(yōu)雅地停止gRPC服務器實例
                    HelloWordServer.this.stop();
                } catch (InterruptedException e) {
                    e.printStackTrace(System.err);
                }
                System.err.println("*** server shut down");
            }
        });
    }

    /**
     * 停止grpc 實例
     *
     * @throws InterruptedException
     */
    public void stop() throws InterruptedException {
        if (Objects.nonNull(server)) {
            // 發(fā)起服務器的關(guān)閉流程,不再接受新的連接和請求,但允許現(xiàn)有連接繼續(xù)完成請求處理
            server.shutdown()
                    // 給予服務器最長30秒的時間去完成所有待處理的工作,超過這個時間限制,程序?qū)⒗^續(xù)執(zhí)行后續(xù)邏輯,即使服務器還有任務未完成
                    // 這樣設(shè)計有助于在應用退出時確保資源得到釋放,同時也能防止因某些原因?qū)е碌拈L時間無法關(guān)閉的問題。
                    .awaitTermination(30, TimeUnit.SECONDS);
        }

    }

    /**
     * 確保主線程或者其他調(diào)用者線程會在服務器完全關(guān)閉之前保持等待狀態(tài)。
     * 在主線程上等待終止,因為grpc庫使用守護線程
     *
     * @throws InterruptedException
     */
    public void blockUntilShutdown() throws InterruptedException {
        if (Objects.nonNull(server)) {
            server.awaitTermination();
        }
    }

    /**
     * 業(yè)務處理類
     */
    public static class GreeterImpl extends GreeterGrpc
            .GreeterImplBase {

        private final int port;

        public GreeterImpl(int port) {
            this.port = port;
        }

        /**
         * @param request
         * @param responseObserver 這是gRPC提供的響應觀察者對象,用于向客戶端發(fā)送響應。服務端通過調(diào)用其方法將響應數(shù)據(jù)發(fā)送給客戶端。
         */
        @Override
        public void sayHello(HelloRequest request, StreamObserver<HelloReply> responseObserver) {
            HelloReply reply = HelloReply.newBuilder().setMessage("Hello " + request.getName() + this.port).build();
            try {
                Thread.sleep(500 + new Random().nextInt(1000));
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            // 向客戶端發(fā)送響應數(shù)據(jù),即將創(chuàng)建好的 reply 對象推送給客戶端。
            responseObserver.onNext(reply);
            // 表示響應已經(jīng)結(jié)束,沒有更多的數(shù)據(jù)要發(fā)送給客戶端。
            responseObserver.onCompleted();
        }
    }

    public static void main(String[] args) throws IOException, InterruptedException {
        final HelloWordServer helloWordServer = new HelloWordServer();
        helloWordServer.start();
        helloWordServer.blockUntilShutdown();
    }
}

4.2 自定負載均衡解析器編寫

HelloWordConstants.java常量:

public interface HelloWordConstants {
    String SCHEME = "example";
    String SERVICE_NAME = "lb.example.grpc.io";
}

負載均衡解析器LoadBalanceNameResolver.java

package io.grpc.examples.helloworld2;

import io.grpc.EquivalentAddressGroup;
import io.grpc.NameResolver;

import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Author tanyong
 * @Version LoadBalanceNameResolver v1.0.0 2024/4/2 16:59 $$
 */
public class LoadBalanceNameResolver extends NameResolver {

    private Listener2 listener;

    private List<InetSocketAddress> socketAddressList;
    private String serviceName;

    private final Map<String, List<InetSocketAddress>> addrStore = new HashMap<>();

    public LoadBalanceNameResolver(List<InetSocketAddress> socketAddressList, String serviceName) {
        this.socketAddressList = socketAddressList;
        this.serviceName = serviceName;
        addrStore.put(serviceName, socketAddressList);

    }

    @Override
    public void start(Listener2 listener) {

        this.listener = listener;
        this.resolve();
    }

    @Override
    public void refresh() {
        this.resolve();
    }

    /**
     * 返回用于對服務器連接進行身份驗證的權(quán)限。它必須來自受信任的來源,因為如果權(quán)限被篡改,rpc可能會被發(fā)送給攻擊者,這可能會泄露敏感的用戶數(shù)據(jù)。
     * 實現(xiàn)必須在不阻塞的情況下生成它,通常是在線生成,并且必須保持它不變。從同一工廠使用相同參數(shù)創(chuàng)建的namesolvers必須返回相同的權(quán)限。
     * 自:
     *
     * @return
     */
    @Override
    public String getServiceAuthority() {
        return "ok";
    }

    @Override
    public void shutdown() {

    }

    /**
     * 解析服務器地址
     */
    private void resolve() {
        List<InetSocketAddress> addresses = addrStore.get(serviceName);
        List<EquivalentAddressGroup> equivalentAddressGroup = addresses.stream().map(this::toSocketAddress)
                .map(Arrays::asList)
                .map(this::addrToEquivalentAddressGroup)
                .collect(Collectors.toList());
        ResolutionResult resolutionResult = ResolutionResult.newBuilder()
                .setAddresses(equivalentAddressGroup)
                .build();

        // 處理已解析地址和屬性的更新
        this.listener.onResult(resolutionResult);

    }

    private SocketAddress toSocketAddress(InetSocketAddress address) {
        return new InetSocketAddress(address.getHostName(), address.getPort());
    }

    private EquivalentAddressGroup addrToEquivalentAddressGroup(List<SocketAddress> addrList) {
        return new EquivalentAddressGroup(addrList);
    }
}

負載均衡解析器提供者LoadBalanceNameResolverProvider.java

package io.grpc.examples.helloworld2;

import io.grpc.NameResolver;
import io.grpc.NameResolverProvider;

import java.net.InetSocketAddress;
import java.net.URI;
import java.util.List;

/**
 * @Author tanyong
 * @Version LoadBalanceNameResolverProvider v1.0.0 2024/4/3 9:56 $$
 */
public class LoadBalanceNameResolverProvider extends NameResolverProvider {

    private final List<InetSocketAddress> socketAddressList;

    public LoadBalanceNameResolverProvider(List<InetSocketAddress> socketAddressList) {
        this.socketAddressList = socketAddressList;
    }


    @Override
    protected boolean isAvailable() {
        return true;
    }

    @Override
    protected int priority() {
        return 5;
    }

    @Override
    public NameResolver newNameResolver(URI targetUri, NameResolver.Args args) {
        return new LoadBalanceNameResolver(socketAddressList, HelloWordConstants.SERVICE_NAME);
    }

    @Override
    public String getDefaultScheme() {
        return HelloWordConstants.SCHEME;
    }
}

4.3 客戶端HelloWordClient.java

package io.grpc.examples.helloworld2;

import io.grpc.*;
import io.grpc.examples.helloworld.GreeterGrpc;
import io.grpc.examples.helloworld.HelloReply;
import io.grpc.examples.helloworld.HelloRequest;

import java.net.InetSocketAddress;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @Author tanyong
 * @Version HellowordClient v1.0.0 2024/4/2 16:33 $$
 */
public class HelloWordClient {

    /**
     * 客戶端對服務Greeter進行同步rpc調(diào)用 blockingStub
     */
    private final GreeterGrpc.GreeterBlockingStub blockingStub;


    public HelloWordClient(Channel channel) {
        // 創(chuàng)建一個新的阻塞式Stub,支持對服務的一元和流輸出調(diào)用
        blockingStub = GreeterGrpc.newBlockingStub(channel);
    }

    public void greet(String name) {
        HelloRequest request = HelloRequest.newBuilder().setName(name).build();

        HelloReply response;
        try {
            // 設(shè)置此次RPC調(diào)用的響應超時時間為1秒
            response = blockingStub.withDeadlineAfter(1, TimeUnit.SECONDS).sayHello(request);
            System.out.println(response.getMessage());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        // 服務段連接地址
        List<InetSocketAddress> addressList = Arrays.asList(new InetSocketAddress("127.0.0.1", 50052),
                new InetSocketAddress("127.0.0.1", 50053));

        // 注冊 NameResolverProvider
        NameResolverRegistry.getDefaultRegistry().register(new LoadBalanceNameResolverProvider(addressList));
        // 符合namesolver的有效URI
        String target = String.format("%s:///%s", HelloWordConstants.SCHEME, HelloWordConstants.SERVICE_NAME);


        // 創(chuàng)建channel
        ManagedChannel channel = ManagedChannelBuilder.forTarget(target)
                .defaultLoadBalancingPolicy("round_robin")
                // 使用明文連接到服務器。默認情況下,將使用安全連接機制,如TLS。
                // 應僅用于測試或API的使用或交換的數(shù)據(jù)不敏感的API。
                .usePlaintext()
                .disableRetry()
                .build();

        try {
            HelloWordClient client = new HelloWordClient(channel);
            long current = System.currentTimeMillis();
            for (int i = 0; i < 10; i++) {
                Thread.sleep(5000);
                client.greet("測試");
            }
            System.out.println(System.currentTimeMillis() - current);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 關(guān)閉channel
            channel.shutdownNow().awaitTermination(5, TimeUnit.SECONDS);
        }

    }
}

到此這篇關(guān)于Java實現(xiàn)grpc框架的示例的文章就介紹到這了,更多相關(guān)Java grpc內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • mybatis-plus3.0.1枚舉返回為null解決辦法

    mybatis-plus3.0.1枚舉返回為null解決辦法

    這篇文章主要介紹了mybatis-plus3.0.1枚舉返回為null解決辦法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-12-12
  • SpringAI?Agent開發(fā)秘籍如何讓javaer也可以用上Agent?Skills

    SpringAI?Agent開發(fā)秘籍如何讓javaer也可以用上Agent?Skills

    文章介紹了如何使用SpringA和Skills構(gòu)建一個代碼評審應用,通過實戰(zhàn)示例展示如何利用SpringAI和大模型實現(xiàn)零配置的代碼評審功能,感興趣的朋友跟隨小編一起看看吧
    2026-04-04
  • java項目新建遇到的兩個問題解決

    java項目新建遇到的兩個問題解決

    創(chuàng)建一個新的Java項目可以通過多種方式進行,包括使用集成開發(fā)環(huán)境(IDE)或手動創(chuàng)建,下面這篇文章主要給大家介紹了關(guān)于java項目新建遇到的兩個問題,需要的朋友可以參考下
    2024-06-06
  • Spring依賴注入DI之三種依賴注入類型詳解

    Spring依賴注入DI之三種依賴注入類型詳解

    這篇文章主要介紹了Spring依賴注入DI之三種依賴注入類型詳解,通過 @Autowired 注解,字段注入的實現(xiàn)方式非常簡單而直接,代碼的可讀性也很強,事實上,字段注入是三種注入方式中最常用、也是最容易使用的一種,需要的朋友可以參考下
    2023-09-09
  • Spring Data分頁與排序的實現(xiàn)方法

    Spring Data分頁與排序的實現(xiàn)方法

    這篇文章主要給大家介紹了關(guān)于Spring Data分頁與排序的實現(xiàn)方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2018-12-12
  • Java中如何執(zhí)行多條shell/bat命令

    Java中如何執(zhí)行多條shell/bat命令

    這篇文章主要介紹了Java中如何執(zhí)行多條shell/bat命令的方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • Eclipse 出現(xiàn)A configuration with this name already exists問題解決方法

    Eclipse 出現(xiàn)A configuration with this name already exists問題解決方

    這篇文章主要介紹了Eclipse 出現(xiàn)A configuration with this name already exists問題解決方法的相關(guān)資料,需要的朋友可以參考下
    2016-11-11
  • Java線程創(chuàng)建的5種寫法詳解

    Java線程創(chuàng)建的5種寫法詳解

    這段文章詳細解釋了線程與進程的關(guān)系、線程狀態(tài)、線線程創(chuàng)建的幾種寫法、常見面試題以及高耦合與低耦合的概念,通過這些內(nèi)容,讀者可以全面了解線程的基礎(chǔ)知識及其在編程中的應用,需要的朋友可以參考下
    2026-05-05
  • java中的數(shù)學計算函數(shù)的總結(jié)

    java中的數(shù)學計算函數(shù)的總結(jié)

    這篇文章主要介紹了java中的數(shù)學計算函數(shù)的總結(jié)的相關(guān)資料,需要的朋友可以參考下
    2017-07-07
  • 使用Java?Executors創(chuàng)建線程池的9種方法

    使用Java?Executors創(chuàng)建線程池的9種方法

    文章主要介紹了?Java?中Executors類創(chuàng)建線程池的?9?種方法,每種方法都詳細闡述了實現(xiàn)原理、源代碼分析、參數(shù)解釋、實現(xiàn)過程、特性和使用場景,感興趣的小伙伴跟著小編一起來看看吧
    2024-11-11

最新評論

富源县| 墨脱县| 教育| 屏南县| 江陵县| 台安县| 塘沽区| 叙永县| 兴山县| 漯河市| 乌鲁木齐县| 资源县| 霍城县| 云安县| 灵武市| 海兴县| 利津县| 开化县| 边坝县| 托克托县| 普定县| 邮箱| 宜春市| 佛冈县| 汽车| 无棣县| 五常市| 铜山县| 淳安县| 章丘市| 隆林| 上饶市| 泗阳县| 怀远县| 化德县| 酒泉市| 视频| 潢川县| 呼图壁县| 绍兴县| 舟曲县|