欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

SpringBoot集成gRPC微服務工程搭建實踐的方法

 更新時間:2019年01月20日 11:16:28   作者:驚天霸戈  
這篇文章主要介紹了SpringBoot集成gRPC微服務工程搭建實踐的方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

前言

本文將使用Maven、gRPC、Protocol buffers、Docker、Envoy等工具構建一個簡單微服務工程,筆者所使用的示例工程是以前寫的一個Java后端工程,因為最近都在 學習微服務相關的知識,所以利用起來慢慢的把這個工程做成微服務化應用。在實踐過程踩過很多坑,主要是經(jīng)驗不足對微服務還是停留在萌新階段,通過本文 記錄創(chuàng)建微服務工程碰到一些問題,此次實踐主要是解決以下問題:

  • 如何解決、統(tǒng)一服務工程依賴管理
  • SpringBoot集成gRPC
  • 管理Protocol buffers文件
  • 使用Envoy代理訪問gRPC
  • 部署到Docker

本文假設讀者已經(jīng)了解以下相關知識:

  • Maven
  • Envoy
  • gRPC
  • Protocol buffers
  • SpringBoot
  • Docker

由于是初步實現(xiàn)微服務,不會考慮過多的細節(jié),現(xiàn)階段只需要能夠使用gRPC正常通信,后續(xù)計劃會發(fā)布到k8s中,使用istio實現(xiàn)來服務網(wǎng)格。

使用Maven

現(xiàn)在比較流行的構建工具有Maven和Gradle,現(xiàn)階段后端開發(fā)大多數(shù)都是用的Maven所以本工程也使用Maven來構建項目,當然使用Gradle也可以兩者概念大都想通,不同的地方大多是實現(xiàn)和配置方式不一致。

使用項目繼承

根據(jù)Maven的POM文件繼承特性,將工程分不同的模塊,所有的模塊都繼承父pom.xml的依賴、插件等內(nèi)容,這樣就可以實現(xiàn)統(tǒng)一管理,并方便以后管理、維護。先看一下大概的項目結(jié)構:

AppBubbleBackend   (1)
├── AppBubbleCommon
├── AppBubbleSmsService  (2)
├── AppBubbleUserService
├── docker-compose.yaml  (3)
├── pom.xml
├── protos     (4)
│ ├── sms
│ └── user
└── scripts     (5)
 ├── docker
 ├── envoy
 ├── gateway
 └── sql

以下是各個目錄的用處簡述,詳細的用處文章后面都會提到,先在這里列出個大概:

  1. 工程主目錄
  2. 單個服務工程目錄(模塊)
  3. docker-compose發(fā)布文件
  4. 存放.proto文件
  5. 發(fā)布、編譯時用到的腳本文件

知道大概的項目工程結(jié)構后我們創(chuàng)建一個父pom.xml文件,放在AppBubbleBackend目錄下面:

<?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>
 <parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifactId>
  <version>2.1.2.RELEASE</version>
  <relativePath/> <!-- lookup parent from repository -->
 </parent>

 <groupId>com.bubble</groupId>
 <artifactId>bubble</artifactId>
 <version>0.0.1-SNAPSHOT</version>
 <packaging>pom</packaging>
 
 <modules>
  <module>AppBubbleSmsService</module>
  <module>AppBubbleCommon</module>
  <module>AppBubbleUserService</module>
 </modules>

 <!-- 省略其他部分 -->
</project>

因為使用SpringBoot構架,所以主pom.xml文件繼承自SpringBoot的POM文件。 有了主pom.xml后然后使每個模塊的pom.xml都繼承自 主pom.xml文件:

<?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>
 <parent>
 <groupId>com.bubble</groupId>
 <artifactId>bubble</artifactId>
 <version>0.0.1-SNAPSHOT</version>
 </parent>
 <artifactId>sms</artifactId>
 <version>0.0.1-SNAPSHOT</version>

 <!-- 省略其他部分 -->
</project>

經(jīng)過上面的配置后,所有的模塊都會繼承AppBubbleBackend中的pom.xml文件,這樣可以很方便的更改依賴、配置等信息。

依賴管理

Maven提供依賴中心化的管理機制,通過項目繼承特性所有對AppBubbleBackend/pom.xml所做的更改都會對其他模塊產(chǎn)生影響,詳細的依賴管理 內(nèi)容可查看官方文檔。

 <dependencyManagement>
  <dependencies>
   <!-- gRPC -->
   <dependency>
    <groupId>io.grpc</groupId>
    <artifactId>grpc-netty-shaded</artifactId>
    <version>${grpc.version}</version>
   </dependency>
  </dependencies>
</dependencyManagement>

通過dependencyManagement標簽來配置依賴,這樣可以就可以實現(xiàn)統(tǒng)一依賴的管理,并且還可以添加公共依賴。

插件管理

使用pluginManagement可以非常方便的配置插件,因為項目中使用了Protocol buffers需要集成相應的插件來生成Java源文件:

<pluginManagement>
   <plugins>
    <plugin>
     <groupId>org.xolstice.maven.plugins</groupId>
     <artifactId>protobuf-maven-plugin</artifactId>
     <version>0.5.1</version>
     <executions>
      <execution>
       <goals>
        <goal>compile</goal>
        <goal>compile-custom</goal>
       </goals>
      </execution>
     </executions>
    </plugin>
   </plugins>
</pluginManagement>

Protocol buffers插件的完整配置參數(shù),可以這這里找到。

Profile

使用Profile的目的是為了區(qū)分生成Docker鏡像時的一些特殊配置,示例工程只配置了一個docker-build的profile:

 <profiles>
  <profile>
   <id>docker-build</id>
   <properties>
    <jarName>app</jarName>
   </properties>
  </profile>
 </profiles>

  <properties>
  <jarName>${project.artifactId}-${project.version}</jarName>
 </properties>
 
 <build>
  <finalName>${jarName}</finalName>
 </build>

如果使用mvn package -P docker-build命令生成jar包時,相應的輸出文件名是app.jar這樣可以方便在Dockerfile中引用文件,而不需要使用${project.artifactId}-${project.version}的形式來查找輸出的jar這樣可以省去了解析pom.xml文件。如果還需要特殊的參數(shù)可以或者不同的行為,可以添加多個Profile,這樣配置起來非常靈活。

Protocol buffers文件管理

因為是使用微服務開發(fā),而且RPC通信框架是使用的gRPC,所以每個服務工程都會使用.proto文件。服務工程之間又會有使用同一份.proto文件的需求,比如在進行RPC通信時服務提供方返回的消息Test定義在a.proto文件中,那么在使用方在解析消息時也同樣需要a.proto文件來將接收到的消息轉(zhuǎn)換成Test消息,因此管理.proto文件也有一些小麻煩。關于Protocol buffers的使用可參考 官方文檔。

Protocol buffers文件管理規(guī)約

在我們的示例項目中使用集中管理的方式,即將所有的.proto文件放置在同一個目錄(AppBubbleBackend/protos)下并按服務名稱來劃分:

├── sms
│ ├── SmsMessage.proto
│ └── SmsService.proto
└── user
 └── UserMessage.proto

還可以將整個目錄放置在一個單獨的git倉庫中,然后在項目中使用git subtree來管理文件。

Protocol buffers 插件配置

有了上面的目錄結(jié)構后,就需要配置一下Protocol buffers的編譯插件來支持這種.proto文件的組織結(jié)構。在講解如何配置插件解決.proto文件的編譯問題之前,推薦讀者了解一下插件的配置文檔:Xolstice Maven Plugins。在我們的工程中使用如下配置:

<plugin>
  <groupId>org.xolstice.maven.plugins</groupId>
  <artifactId>protobuf-maven-plugin</artifactId>
  <version>0.5.1</version>
  <configuration >
   <protocArtifact>com.google.protobuf:protoc:3.5.1-1:exe:${os.detected.classifier}</protocArtifact>
   <pluginId>grpc-java</pluginId>
   <pluginArtifact>io.grpc:protoc-gen-grpc-java:1.17.1:exe:${os.detected.classifier}</pluginArtifact>
   <additionalProtoPathElements combine.children="append" combine.self="append">
    <additionalProtoPathElement>${GOPATH}/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis</additionalProtoPathElement>
    <additionalProtoPathElement>${GOPATH}/src</additionalProtoPathElement>
   </additionalProtoPathElements>
   <protoSourceRoot>${protos.basedir}</protoSourceRoot>
   <writeDescriptorSet>true</writeDescriptorSet>
   <includeDependenciesInDescriptorSet>true</includeDependenciesInDescriptorSet>
  </configuration>
  <!-- ... -->
 </plugin>

首先上面的插件配置使用protoSourceRoot標簽將Protocol buffers的源文件目錄更改成AppBubbleBackend/protos目錄,因為工程中使用了googleapis來定義服務接口,所以需要使用添加additionalProtoPathElement標簽添加額外的依賴文件。注意這個插件的配置是在AppBubbleBackend/pom.xml文件中的,服務工程都是繼承此文件的。在父POM文件配置好以后,再看一下服務工程的插件配置:

<plugins>
 <plugin>
 <groupId>org.xolstice.maven.plugins</groupId>
 <artifactId>protobuf-maven-plugin</artifactId>
 <configuration>
  <includes>
  <include>${project.artifactId}/*.proto</include>
  <include>user/*.proto</include>
  </includes>
 </configuration>
 </plugin>
 </plugins>

服務工程主要使用includes標簽,將需要的.proto文件包含在編譯腳本中,includes標簽中的include只是一個指定匹配.proto文件的匹配模式,<include>${project.artifactId}/*.proto</include>意思是AppBubbleBackend/protos/${project.artifactId}目錄下的所有以.proto文件結(jié)尾的文件,如果服務工程有多個依賴可以將需要依賴的文件也添加到編譯服務中,如上面的<include>user/*.proto</include>就將AppBubbleBackend/protos/user中的.proto文件添加進來,然后進行整體的編譯。

gRPC

gRPC是由Google開源的RPC通信框架,gRPC使用Protocol buffers定義服務接口并自動生成gRPC相關代碼,有了這些代碼后就可以非常方便的實現(xiàn)gRPC服務端和gPRC客戶端,過多的細節(jié)就不細說了先看一下如何使用在SpringBoot中使用gRPC。

運行gRPC服務

利用ApplicationRunner接口,在SprintBoot中運行gRPC服非常方便,只需要像下面代碼一樣就可以運行一個簡單的gRPC服務。

package com.bubble.sms.grpc;

@Component
public class GrpcServerInitializer implements ApplicationRunner {


 @Autowired
 private List<BindableService> services;

 @Value("${grpc.server.port:8090}")
 private int port;

 @Override
 public void run(ApplicationArguments args) throws Exception {

  ServerBuilder serverBuilder = ServerBuilder
    .forPort(port);

  if (services != null && !services.isEmpty()) {
   for (BindableService bindableService : services) {
    serverBuilder.addService(bindableService);
   }
  }
  Server server = serverBuilder.build();
  serverBuilder.intercept(TransmitStatusRuntimeExceptionInterceptor.instance());
  server.start();
  startDaemonAwaitThread(server);
 }


 private void startDaemonAwaitThread(Server server) {
  Thread awaitThread = new Thread(() -> {
   try {
    server.awaitTermination();
   } catch (InterruptedException ignore) {
    
   }
  });
  awaitThread.setDaemon(false);
  awaitThread.start();
 }
}

Envoy代理

gRPC服務運行起來后就需要進行調(diào)試了,比如使用curl、chrome等工具向gRPC服務發(fā)起Restful請求,實際上gRPC的調(diào)試并沒有那么簡單。一開始的方案是使用了gRPC-gateway,為每個服務都啟動一個網(wǎng)關將Http 1.x請求轉(zhuǎn)換并發(fā)送到gRPC服務。然而gRPC-gateway只有go語言的版本,并沒有Java語言的版本,所有在編譯和使用中比較困難,后來發(fā)現(xiàn)了Envoy提供了envoy.grpc_json_transcoder這個http過濾器,可以很方便的將RESTful JSON API轉(zhuǎn)換成gRPC請求并發(fā)送給gRPC服務器。

envoy的相關配置都放置在AppBubbleBackend/scripts/envoy目錄中,里面的envoy.yaml是一份簡單的配置文件:

static_resources:
 listeners:
 - name: grpc-8090
 address:
  socket_address: { address: 0.0.0.0, port_value: 8090 }
 filter_chains:
 - filters:
  - name: envoy.http_connection_manager
  config:
   stat_prefix: sms_http
   codec_type: AUTO
   # 省略部分配置
   http_filters:
   - name: envoy.grpc_json_transcoder
   config:
    proto_descriptor: "/app/app.protobin"
    services: ["sms.SmsService"]
    match_incoming_request_route: true
    print_options:
    add_whitespace: true
    always_print_primitive_fields: true
    always_print_enums_as_ints: false
    preserve_proto_field_names: false
# 省略部分配置    

使用envoy.grpc_json_transcoder過濾器的主要配置是proto_descriptor選項,該選項指向一個proto descriptor set文件。AppBubbleBackend/scripts/envoy/compile-descriptor.sh是編譯proto descriptor set的腳本文件, 運行腳本文件會在腳本目錄下生成一個app.protobin的文件,將此文件設置到envoy.grpc_json_transcoder就可大致完成了envoy的代理配置。

使用Docker發(fā)布

經(jīng)過上面的一系統(tǒng)準備工作之后,我們就可以將服務發(fā)布到docker中了,Docker相關的文件都放置中AppBubbleBackend/scripts/docker和一個AppBubbleBackend/docker-compose.yaml文件。在發(fā)布時使用單個Dockerfile文件來制作服務鏡像:

FROM rcntech/ubuntu-grpc:v0.0.5
EXPOSE 8080
EXPOSE 8090

#將當前目錄添加文件到/bubble
ARG APP_PROJECT_NAME
#復制父pom.xml
ADD /pom.xml /app/pom.xml
ADD /protos /app/protos
ADD $APP_PROJECT_NAME /app/$APP_PROJECT_NAME
ADD scripts/gateway /app/gateway
ADD scripts/docker/entrypoint.sh /app/entrypoint.sh
RUN chmod u+x /app/entrypoint.sh

ENTRYPOINT ["/app/entrypoint.sh"]

有了Dockerfile文件后,在docker-compose.yaml里面做一些配置就能將服務打包成鏡像:

 sms:
 build:
 context: ./
 dockerfile: scripts/docker/Dockerfile
 args:
  APP_PROJECT_NAME: "AppBubbleSmsService"
 environment:
 APOLLO_META: "http://apollo-configservice-dev:8080"
 APP_PROJECT_NAME: "AppBubbleSmsService"
 ENV: dev

同時編寫了一個通用的entrypoint.sh腳本文件來啟動服務器:

#!/bin/bash

export GOPATH=${HOME}/go
export PATH=$PATH:/usr/local/go/bin:$GOPATH/bin

rootProjectDir="/app"
projectDir="${rootProjectDir}/${APP_PROJECT_NAME}"

cd ${rootProjectDir}/AppBubbleCommon
./mvnw install

cd $projectDir
#打包app.jar
./mvnw package -DskipTests -P docker-build
#編譯proto文件
./mvnw protobuf:compile protobuf:compile-custom -P docker-build


# Run service
java -jar ${projectDir}/target/app.jar

entrypoint.sh腳本中將服務工程編譯成app.jar包再運行服務。還有envoy代理也要啟動起來這樣我們就可以使用curl或其他工具直接進行測試了。

總結(jié)

搭建這個工程大概摸索了一周的時間,主要的時間是花在了Protocol buffers文件的管理與使用Envoy作為代理調(diào)試gRPC服務上。文章中的示例工程已經(jīng)傳到了GitHub: AppBubbleBackend 后面會打算慢慢的完善這個應用,這是個簡單的短視屏應用除了服務器還包含了Android和iOS端,等到將后端微服務化為開源出來供學習交流使用。

參考引用

gRPC官方文檔
Protocol buffers Maven 插件文檔
Protocol buffers官方文檔
gRPC 官方文檔中文版
gRPC-JSON transcoder

以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

相關文章

  • Windows環(huán)境使用bat腳本啟動Java服務的過程

    Windows環(huán)境使用bat腳本啟動Java服務的過程

    Java項目一般會被打包成jar后啟動,在windows系統(tǒng)中可以通過終端窗口cmd啟動jar包,即在jar包所在的目錄中打開cmd,或在cmd中進入到jar包目錄,這篇文章主要介紹了Windows環(huán)境使用bat腳本啟動Java服務,需要的朋友可以參考下
    2023-08-08
  • JNDI簡介_動力節(jié)點Java學院整理

    JNDI簡介_動力節(jié)點Java學院整理

    這篇文章主要介紹了JNDI簡介,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-08-08
  • 帶你了解Java數(shù)據(jù)結(jié)構和算法之無權無向圖

    帶你了解Java數(shù)據(jù)結(jié)構和算法之無權無向圖

    這篇文章主要為大家介紹了Java數(shù)據(jù)結(jié)構和算法之無權無向圖?,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-01-01
  • SpringCloud集成MybatisPlus實現(xiàn)MySQL多數(shù)據(jù)源配置方法

    SpringCloud集成MybatisPlus實現(xiàn)MySQL多數(shù)據(jù)源配置方法

    本文詳細介紹了SpringCloud集成MybatisPlus實現(xiàn)MySQL多數(shù)據(jù)源配置的方法,包括在application.properties中配置多數(shù)據(jù)源,配置MybatisPlus,創(chuàng)建Mapper接口和使用多數(shù)據(jù)源等步驟,此外,還解釋了每一個配置項目的含義,以便讀者更好地理解和應用
    2024-10-10
  • 學習spring事務與消息隊列

    學習spring事務與消息隊列

    這篇文章主要為大家詳細介紹了spring事務與消息隊列,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-10-10
  • Java中HashMap和HashTable區(qū)別

    Java中HashMap和HashTable區(qū)別

    HashMap和Hashtable都是Java常見的基于哈希表實現(xiàn)的Map接口的實現(xiàn)類,本文主要介紹了Java中HashMap和HashTable區(qū)別,具有一定的參考價值,感興趣的可以了解一下
    2023-11-11
  • SpringBoot對靜態(tài)資源的映射規(guī)則詳解

    SpringBoot對靜態(tài)資源的映射規(guī)則詳解

    在Web應用中會涉及到大量的靜態(tài)資源,例如 JS、CSS和HTML等,我們知道,Spring MVC 導入靜態(tài)資源文件時,需要配置靜態(tài)資源的映射,但在 SpringBoot 中則不再需要進行此項配置,因為SpringBoot已經(jīng)默認完成了這一工作,本文給大家介紹了SpringBoot對靜態(tài)資源的映射規(guī)則詳
    2024-12-12
  • Java中的LinkedBlockingQueue源碼解析

    Java中的LinkedBlockingQueue源碼解析

    這篇文章主要介紹了Java中的LinkedBlockingQueue源碼解析,LinkedBlockingQueue底層是一個鏈表(可以指定容量,默認是Integer.MAX_VALUE),維持了兩把鎖,一把鎖用于入隊,一把鎖用于出隊,并且使用一個AtomicInterger類型的變量保證線程安全,需要的朋友可以參考下
    2023-12-12
  • Spring session 獲取當前賬戶登錄數(shù)的實例代碼

    Spring session 獲取當前賬戶登錄數(shù)的實例代碼

    這篇文章主要介紹了Spring session 獲取當前賬戶登錄數(shù),本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-04-04
  • 利用java反射機制調(diào)用類的私有方法(推薦)

    利用java反射機制調(diào)用類的私有方法(推薦)

    下面小編就為大家?guī)硪黄胘ava反射機制調(diào)用類的私有方法(推薦)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-08-08

最新評論