Micronaut 教程(二):分布式跟踪、JWT 安全和 AWS Lambda 部署

栏目: 后端 · 发布时间: 6年前

内容简介:在本系列的第一篇文章中,我们使用基于 JVM 的将系统分解为更小、更细粒度的微服务可以带来多种好处,但也会给生产环境的监控系统增加复杂性。你应该假设你的网络将会受到恶意实体的骚扰,它们时刻准备着随心所欲地释放它们的愤怒。

关键要点

  • Micronaut 提供了与 Zipkin 和 Jaeger 等多种分布式跟踪解决方案的无缝集成。
  • 框架提供了几种“开箱即用”的安全解决方案,例如基于 JWT 的认证。
  • Micronaut 提供了“令牌传播”之类的功能,用以简化微服务之间的安全通信。
  • 因为内存占用少,Micronaut 能够运行在功能即服务(FaaS)无服务器环境中。

在本系列的第一篇文章中,我们使用基于 JVM 的 Micronaut 框架开发并部署了三个微服务。在第二篇文章中,我们将为应用程序添加几个功能:分布式跟踪、JWT 安全性和无服务器功能。此外,我们也将介绍 Micronaut 提供的用户输入验证功能。

分布式跟踪

将系统分解为更小、更细粒度的微服务可以带来多种好处,但也会给生产环境的监控系统增加复杂性。

你应该假设你的网络将会受到恶意实体的骚扰,它们时刻准备着随心所欲地释放它们的愤怒。

——Sam Newman,《构建微服务》

Micronaut 与 Jaeger 和 Zipkin 原生集成——它们都是顶级的开源分布式跟踪解决方案。

Zipkin 是一种分布式跟踪系统,用于收集时序数据,这些数据可用于解决微服务架构中的延迟问题。它负责收集和查找这些数据。

启动 Zipkin 的简单方法是通过 Docker:

复制代码

$ docker run -d -p9411:9411openzipkin/zipkin

这个应用程序由三个微服务组成,也就是我们在第一篇文章中开发的三个微服务(gateway、inventory、books)。

我们需要对这三个微服务做出修改。

修改 build.gradle,加入跟踪依赖项:

复制代码

build.gradle

compile"io.micronaut:micronaut-tracing"

将以下依赖项添加到 build.gradle 中,这样就可以将跟踪数据发送到 Zipkin。

复制代码

build.gradle

runtime'io.zipkin.brave:brave-instrumentation-http'
runtime'io.zipkin.reporter2:zipkin-reporter'
compile'io.opentracing.brave:brave-opentracing'

配置跟踪选项:

复制代码

src/main/resources/application.yml

tracing:
   zipkin:
       http:
           url:http://localhost:9411
       enabled:true
       sampler:
           probability:1

设置 tracing.zipkin.sample.probability = 1,意思是我们要跟踪所有的请求。在生产环境中,你可能希望设置较低的百分比。

在测试时禁用跟踪:

复制代码

src/test/resources/application-test.yml

   tracing:
       zipkin:
           enabled:false

只需要很少的配置更改,就可以将分布式跟踪集成到 Micronaut 中。

运行应用程序

现在让我们运行应用程序,看看分布式跟踪集成是否能够正常运行。在第一篇文章中,我们集成了 Consul,用于实现服务发现。因此,在启动微服务之前需要先启动 Zipkin 和 Consul。在微服务启动好以后,它们将在 Consul 服务发现中进行注册。当我们发出请求时,它们会向 Zipkin 发送数据。

Gradle 提供了一个 flag(-parallel)用来启动微服务:

复制代码

./gradlew -parallelrun

你可以通过 cURL 命令向三个微服务发起请求:

复制代码

$ curl http://localhost:8080/api/books
[{"isbn":"1680502395","name":"Release It!","stock":3},
{"isbn":"1491950358","name":"Building Microservices","stock":2}]

然后,你可以通过 http://localhost:9411 来访问 Zipkin UI。

JWT 安全性

Micronaut 提供了多种开箱即用的安全选项,你可以使用基本的身份验证、基于会话的身份验证、JWT 身份验证、Ldap 身份验证,等等。JSON Web Token(JWT)是一种开放的行业标准(RFC 7519)用于在参与方之间声明安全。

Micronaut 提供了开箱即用的用于生成、签名、加密和验证 JWT 令牌的功能。

我们将把 JWT 身份验证集成到我们的应用程序中。

修改 gateway 微服务,让它支持 JWT

gateway 微服务将负责生成和传播 JWT 令牌。

修改 build.gradle,为每个微服务(gateway、inventory 和 books)添加 micronaut-security-jwt 依赖项:

复制代码

gateway/build.gradle

      compile"io.micronaut:micronaut-security-jwt" 
      annotationProcessor"io.micronaut:micronaut-security"

修改 application.yml:

复制代码

gateway/src/main/resources/application.yml
micronaut:
   application:
       name:gateway
   server:
       port:8080
   security:
       enabled:true
       endpoints:
           login:
               enabled:true
           oauth:
               enabled:true
       token:
           jwt:
               enabled:true
               signatures:
                   secret:
                       generator:
                           secret:pleaseChangeThisSecretForANewOne
           writer:
               header:
                   enabled:true
           propagation:
               enabled:true
               service-id-regex:"books|inventory"

我们做了几个重要的配置变更:

  • micronaut.security.enable = true 启用了安全,并默认为每个端点提供安全保护。
  • micronaut.security.endpoints.login.enable = true 启用了 /login 端点,我们将用它进行身份验证。
  • micronaut.security.endpoints.oauth.enable = true 启用了 /oauth/access_tokenendpoint 端点,在令牌过期时,我们可以使用它来获取新的 JWT 访问令牌。
  • micronaut.security.jwt.enable = true 启用了 JWT 功能。
  • 我们让应用程序启用签名的 JWT。更多的签名和加密选项,请参阅 JWT 令牌生成文档。
  • micronaut.security.token.propagation.enabled = true 表示启用了令牌传播。这是一种在微服务架构中简化 JWT 或其他令牌安全机制的功能。
  • micronaut.security.writer.header.enabled = ture 启用了一个令牌写入器,它将为开发人员在 HTTP 标头中写入 JWT 令牌。
  • micronaut.security.token.propagation.service-id-regex 设置了一个正则表达式,用于匹配需要进行令牌传播的服务。我们匹配了应用程序中的其他两个服务。

你可以使用 @Secured 注解来配置 Controller 或 Controller Action 级别的访问。

使用 @Secured(“isAuthenticated()”) 注解 BookController.java,只允许经过身份验证的用户访问。同时记得使用 @Secured(“isAuthenticated()”) 注解 inventory 和 books 微服务的 BookController 类。

/login 端点被调用时,会尝试通过任何可用的 AuthenticationProvider 对用户进行身份验证。为了简单起见,我们将允许两个用户访问,他们是福尔摩斯和华生。创建 SampleAuthenticationProvider:

复制代码

gateway/src/main/java/example/micronaut/SampleAuthenticationProvider.java

packageexample.micronaut;

importio.micronaut.context.annotation.Requires; 
importio.micronaut.context.env.Environment; 
importio.micronaut.security.authentication.AuthenticationFailed; 
importio.micronaut.security.authentication.AuthenticationProvider; 
importio.micronaut.security.authentication.AuthenticationRequest; 
importio.micronaut.security.authentication.AuthenticationResponse; 
importio.micronaut.security.authentication.UserDetails; 
importio.reactivex.Flowable; 
importorg.reactivestreams.Publisher;

importjavax.inject.Singleton; 
importjava.util.ArrayList; 
importjava.util.Arrays;

@Requires(notEnv = Environment.TEST) 
@Singleton 
publicclassSampleAuthenticationProviderimplementsAuthenticationProvider{

   @Override
   publicPublisher<AuthenticationResponse> authenticate(AuthenticationRequest authenticationRequest) { 
       if(authenticationRequest.getIdentity() ==null) { 
           returnFlowable.just(newAuthenticationFailed()); 
        } 
       if(authenticationRequest.getSecret() ==null) { 
           returnFlowable.just(newAuthenticationFailed()); 
        } 
       if(Arrays.asList("sherlock","watson").contains(authenticationRequest.getIdentity().toString()) && authenticationRequest.getSecret().equals("elementary"))     { 
           returnFlowable.just(newUserDetails(authenticationRequest.getIdentity().toString(),newArrayList<>())); 
        } 
       returnFlowable.just(newAuthenticationFailed()); 
    } 
}

修改 inventory 和 books,让它们支持 JWT

对于 inventory 和 books,除了添加 micronaut-security-jwt 依赖项并使用 @Secured 注解控制器之外,我们还需要修改 application.yml,以便能够验证在 gateway 中生成和签名的 JWT 令牌。

修改 application.yml:

复制代码

inventory/src/main/resources/application.yml

micronaut:
   application:
       name:inventory
   server:
       port:8081
   security:
       enabled:true 
       token:
           jwt:
                 enabled:true
                 signatures:
                     secret: 
                         validation: 
                             secret:pleaseChangeThisSecretForANewOne

请注意,我们使用与 gateway 配置中相同的秘钥,这样就可以验证由 gateway 微服务签名的 JWT 令牌。

运行安全的应用程序

在启动了 Zipkin 和 Consul 之后,你就可以同时启动这三个微服务。Gradle 提供了一个方便的 flag(-parallel):

复制代码

./gradlew -parallelrun

你可以运行 cURL 命令,然后会收到 401 错误,表示未授权!

复制代码

$ curl -I http://localhost:8080/api/books HTTP/1.1 401 Unauthorized
Date: Mon,1Oct201818:44:54GMT transfer-encoding: chunked connection: close

我们需要先登录,并获得一个有效的 JWT 访问令牌:

复制代码

$ curl -X"POST""http://localhost:8080/login"\
-H 'Content-Type: application/json; charset=utf-8' \
-d $'{"username":"sherlock","password":"password"}' 
{"username":"sherlock","access_token":"eyJhbGciOiJIUzI1NiJ9.eyJzdWI iOiJzaGVybG9jayIsIm5iZiI6MTUzODQxMjQwOSwicm9sZXMiOltdLCJpc3MiOiJnYX Rld2F5IiwiZXhwIjoxNTM4NDE2MDA5LCJpYXQiOjE1Mzg0MTI0MDl9.1W4CXbN1bJgM CQlCDKJtm7zHWzyZeIr1rHpTuDy6h0","refresh_token":"eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ zaGVybG9jayIsIm5iZiI6MTUzODQxMjQwOSwicm9sZXMiOltdLCJpc3MiOiJnYXRld2 F5IiwiaWF0IjoxNTM4NDEyNDA5fQ.l72msZKwHmYeLs7T0vKtRxu7_DZr62rPCILNmC 7UEZ4","expires_in":3600,"token_type":"Bearer"}

Micronaut 提供了开箱即用的 RFC 6750 Bearer Token 规范支持。我们可以使用从 /login 响应标头中获得的 JWT 来调用 /api/books 端点。

复制代码

curl"http://localhost:8080/api/books"\ -H'Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJzaGVybG9jayIsIm5iZiI6MTUzODQxMjQwOS wicm9sZXMiOltdLCJpc3MiOiJnYXRld2F5IiwiZXhwIjoxNTM4NDE2MDA5LCJpYXQiO jE1Mzg0MTI0MDl9.1W4CXbN1bJgMCQlCDKJtm7zHWz-yZeIr1rHpTuDy6h0'
[{"isbn":"1680502395","name":"Release It!","stock":3}, {"isbn":"1491950358","name":"Building Microservices","stock":2}]

Serverless

我们将添加一个部署到 AWS Lambda 的功能来验证 books 的 ISBN。

复制代码

mncreate-functionexample.micronaut.isbn-validator

注意:我们使用了 Micronaut CLI 提供的 create-function 命令。

验证

我们将创建一个单例来处理 ISBN 10 验证。

创建一个封装操作的接口:

复制代码

packageexample.micronaut;

importjavax.validation.constraints.Pattern;

publicinterfaceIsbnValidator{
   booleanisValid(@Pattern(regexp ="\\d{10}") String isbn);
}

Micronaut 的验证基于标准框架 JSR 380 ,也称为 Bean Validation 2.0。

Hibernate Validator 是这个标准的参考实现。

将以下代码段添加到 build.gradle 中:

复制代码

isbn-validator/build.gradle

     compile"io.micronaut.configuration:micronaut-hibernatevalidator"

创建一个实现了 IsbnValidator 的单例。

复制代码

isbn-validator/src/main/java/example/micronaut/DefaultIsbnValidator.java

packageexample.micronaut;

importio.micronaut.validation.Validated; 
importjavax.inject.Singleton; 
importjavax.validation.constraints.Pattern;

@Singleton 
@Validated 
publicclassDefaultIsbnValidatorimplementsIsbnValidator{

   /** 
     * must range from 0 to 10 (the symbol X is used for 10), and must be such that the sum of all the ten digits, each multiplied by its (integer) weight, descending from 10 to 1, is a multiple of 11.
   *@paramisbn 10 Digit ISBN
   *@returnwhether the ISBN is valid or not.
   */
   @Override
   publicbooleanisValid(@Pattern(regexp ="\\d{10}") String isbn) { 
       char[] digits = isbn.toCharArray(); 
       intaccumulator =0; 
       intmultiplier =10; 
       for(inti =0; i < digits.length; i++) { 
           charc = digits[i]; 
           accumulator += Character.getNumericValue(c) * multiplier; 
           multiplier--; 
       } 
       return(accumulator %11==0);
   }
}

与之前的代码清单一样,你要为需要验证的类添加 @Validated 注解。

创建单元测试:

复制代码

isbn-validator/src/test/java/example/micronaut/IsbnValidatorTest.java

packageexample.micronaut;

importio.micronaut.context.ApplicationContext; 
importio.micronaut.context.DefaultApplicationContext; 
importio.micronaut.context.env.Environment; 
importorg.junit.AfterClass; 
importorg.junit.BeforeClass; 
importorg.junit.Rule; 
importorg.junit.Test; 
importorg.junit.rules.ExpectedException;
importjavax.validation.ConstraintViolationException;
importstaticorg.junit.Assert.assertFalse; 
importstaticorg.junit.Assert.assertTrue;

publicclassIsbnValidatorTest{

   privatestaticApplicationContext applicationContext;

   @BeforeClass 
   publicstaticvoidsetupContext() { 
        applicationContext =newDefaultApplicationContext(Environment.TEST).start(); 
    }
    
   @AfterClass 
   publicstaticvoidstopContext() {
       if(applicationContext!=null) {     
            applicationContext.stop();
        }
    }

   @RulepublicExpectedException thrown = ExpectedException.none();

   @TestpublicvoidtestTenDigitValidation() {
       thrown.expect(ConstraintViolationException.class);
       IsbnValidator isbnValidator = applicationContext.getBean(IsbnValidator.class);
       isbnValidator.isValid("01234567891"); 
    }

   @Test 
   publicvoidtestControlDigitValidationWorks() {  
        IsbnValidator isbnValidator = applicationContext.getBean(IsbnValidator.class);
        assertTrue(isbnValidator.isValid("1491950358"));
        assertTrue(isbnValidator.isValid("1680502395"));
        assertFalse(isbnValidator.isValid("0000502395"));
    }
}

如果我们尝试使用十一位数字字符串调用该方法,就会抛出 javax.validation.ConstraintViolationException。

函数的输入和输出

这个函数将接受单个参数(ValidationRequest,它是一个封装了 ISBN 的 POJO)。

复制代码

isbn-validator/src/main/java/example/micronaut/IsbnValidationRequest.java

packageexample.micronaut;

publicclassIsbnValidationRequest{ 
   privateString isbn;
   publicIsbnValidationRequest(){
    }
   publicIsbnValidationRequest(String isbn){ 
       this.isbn = isbn; 
    }
   publicStringgetIsbn(){returnisbn; }

   publicvoidsetIsbn(String isbn){this.isbn = isbn; }
}

并返回单个结果(ValidationResponse,一个封装了 ISBN 和一个指示 ISBN 是否有效的布尔值的 POJO)。

复制代码

isbn-validator/src/main/java/example/micronaut/IsbnValidationResponse.java

packageexample.micronaut;

publicclassIsbnValidationResponse{ 
   privateString isbn; 
   privateBoolean valid;
    
   publicIsbnValidationResponse(){
    }

   publicIsbnValidationResponse(String isbn,booleanvalid){
       this.isbn = isbn; 
       this.valid = valid; 
    }
   publicStringgetIsbn(){ 
       returnisbn; 
    }
   publicvoidsetIsbn(String isbn){ 
       this.isbn = isbn; 
    }
   publicBooleangetValid(){ 
       returnvalid; 
    }
   publicvoidsetValid(Boolean valid){ 
       this.valid = valid; 
    }
}

函数测试

当我们运行 create-function 命令时,Micronaut 会在 src/main/java/example/micronaut 目录创建一个 IsbnValidatorFunction 类。修改它,让它实现 java.util.Function 接口。

复制代码

isbn-validator/src/main/java/example/micronaut/IsbnValidatorFunction.java

packageexample.micronaut;

importio.micronaut.function.FunctionBean;
importjava.util.function.Function; 
importjavax.validation.ConstraintViolationException;

@FunctionBean("isbn-validator") 
publicclassIsbnValidatorFunctionimplementsFunction<IsbnValidationRequest,IsbnValidationResponse> {

   privatefinalIsbnValidator isbnValidator;

   publicIsbnValidatorFunction(IsbnValidator isbnValidator) {
       this.isbnValidator = isbnValidator; 
    }

   @Override 
   publicIsbnValidationResponse apply(IsbnValidationRequest req) {
       try{ 
           returnnewIsbnValidationResponse(req.getIsbn(), isbnValidator.isValid(req.getIsbn()));
        }catch(ConstraintViolationException e) { 
           returnnewIsbnValidationResponse(req.getIsbn(),false);
        }
    }
}

上面的代码做了几件事:

  • 使用 @FunctionBean 注解了一个返回函数的方法。
  • 你可以在函数中使用 Micronaut 的编译时依赖注入。我们通过构造函数注入了 IsbnValidator。

函数也可以作为 Micronaut 应用程序上下文的一部分运行,这样方便进行测试。应用程序已经在类路径中包含了用于测试的 function-web 和 HTTP 服务器依赖项:

复制代码

isbn-validator/build.gradle

     testRuntime"io.micronaut:micronaut-http-server-netty" 
     testRuntime"io.micronaut:micronaut-function-web"

要在测试中调用函数,需要修改 IsbnValidatorClient.java

复制代码

isbn-validator/src/test/java/example/micronaut/IsbnValidatorClient.java

packageexample.micronaut;

importio.micronaut.function.client.FunctionClient; 
importio.micronaut.http.annotation.Body; 
importio.reactivex.Single;
importjavax.inject.Named;

@FunctionClient 
publicinterfaceIsbnValidatorClient{
   @Named("isbn-validator") 
    Single<IsbnValidationResponse> isValid(@BodyIsbnValidationRequest isbn);
}

同时修改 IsbnValidatorFunctionTest.java。我们需要测试不同的场景(有效的 ISBN、无效的 ISBN、超过 10 位的 ISBN 和少于 10 位的 ISBN)。

复制代码

isbn-validator/src/test/java/example/micronaut/IsbnValidatorFunctionTest.java

package example.micronaut;

import io.micronaut.context.ApplicationContext; 
import io.micronaut.runtime.server.EmbeddedServer; 
import org.junit.Test; 
import static org.junit.Assert.assertFalse; 
import static org.junit.Assert.assertTrue;

publicclassIsbnValidatorFunctionTest {

    @Test public void testFunction(){ 
        EmbeddedServer server =ApplicationContext.run(EmbeddedServer.class);

        IsbnValidatorClient client = server.getApplicationContext().getBean(IsbnValidatorClient.class);

       assertTrue(client.isValid(newIsbnValidationRequest("1491950358")).blockingGet().getValid());
       assertTrue(client.isValid(new    IsbnValidationRequest("1680502395")).blockingGet().getValid());
       assertFalse(client.isValid(newIsbnValidationRequest("0000502395")).blockingGet().getValid());
       assertFalse(client.isValid(newIsbnValidationRequest("01234567891")).blockingGet().getValid());
       assertFalse(client.isValid(newIsbnValidationRequest("012345678")).blockingGet().getValid());
        server.close();
}

}

部署到 AWS Lambda

假设你拥有 Amazon Web Services(AWS)帐户,那么就可以转到 AWS Lambda 并创建一个新功能。

选择 Java 8 运行时。名称为 isbn-validator,并创建一个新的角色表单模板。角色名称为 lambda_basic_execution。

Micronaut 教程(二):分布式跟踪、JWT 安全和 AWS Lambda 部署

运行./gradlew shadowJar 生成一个 Jar 包。

shadowJar 是 Gradle ShadowJar 插件提供的一个任务。

复制代码

$ du -h isbn-validator/build/libs/isbn-validator-0.1-all.jar11M isbn-validator/build/libs/isbn-validator-0.1-all.jar

上传 JAR,并指定 Handler。

复制代码

io.micronaut.function.aws.MicronautRequestStreamHandler 

我只分配了 256Mb 内存,超时时间为 25 秒。

Micronaut 教程(二):分布式跟踪、JWT 安全和 AWS Lambda 部署

从另一个微服务中调用函数

我们将在 gateway 微服务中使用这个 lambda。修改 gateway 微服务中的 build.gradle,添加 micronaut-function-client:

复制代码

com.amazonaws:aws-java-sdk-lambda dependencies:

build.gradle

     compile"io.micronaut:micronaut-function-client" 
     runtime'com.amazonaws:aws-java-sdk-lambda:1.11.285'

修改 src/main/resources/application.yml:

复制代码

src/main/resources/application.yml

aws:
    lambda:
        functions:
            vat:
                functionName:isbn-validator 
                qualifer:isbn 
        region:eu-west-3# Paris Region

创建一个接口:

复制代码

src/main/java/example/micronaut/IsbnValidator.java

package example.micronaut;

import io.micronaut.http.annotation.Body;
import io.reactivex.Single;

publicinterfaceIsbnValidator { 
    Single<IsbnValidationResponse> validateIsbn(@Body IsbnValidationRequest req); 
}

创建一个 @FunctionClient:

复制代码

src/main/java/example/micronaut/FunctionIsbnValidator.java

packageexample.micronaut;

importio.micronaut.context.annotation.Requires; 
importio.micronaut.context.env.Environment; 
importio.micronaut.function.client.FunctionClient; 
importio.micronaut.http.annotation.Body; 
importio.reactivex.Single;
importjavax.inject.Named;

@FunctionClient 
@Requires(notEnv = Environment.TEST) 
publicinterfaceFunctionIsbnValidatorextendsIsbnValidator{
   @Override 
   @Named("isbn-validator") 
    Single<IsbnValidationResponse> validateIsbn(@BodyIsbnValidationRequest req);
}

关于上面这些代码有几点值得注意:

  • FunctionClient 注解可以在接口上应用引入通知(introduction advice),这样接口定义的方法就会成为远程函数的调用者。
  • 使用函数名 isbn-validator,与 application.yml 定义的一样。

最后一步是修改 gateway 的 BookController,让它调用函数。

复制代码

src/main/java/example/micronaut/BooksController.java

packageexample.micronaut;

importio.micronaut.http.annotation.Controller; 
importio.micronaut.http.annotation.Get; 
importio.micronaut.security.annotation.Secured; 
importio.reactivex.Flowable;

importjava.util.List;

@Secured("isAuthenticated()")
@Controller("/api") 
publicclassBooksController{
   privatefinalBooksFetcher booksFetcher; 
   privatefinalInventoryFetcher inventoryFetcher; 
   privatefinalIsbnValidator isbnValidator;
   publicBooksController(BooksFetcher booksFetcher, InventoryFetcher inventoryFetcher, IsbnValidator isbnValidator) {
       this.booksFetcher = booksFetcher; 
       this.inventoryFetcher = inventoryFetcher; 
       this.isbnValidator = isbnValidator;
    }

   @Get("/books") 
    Flowable<Book> findAll() { 
       returnbooksFetcher.fetchBooks()
             .flatMapMaybe(b -> isbnValidator.validateIsbn(new IsbnValidationRequest(b.getIsbn()))
                 .filter(IsbnValidationResponse::getValid)
                 .map(isbnValidationResponse -> b) 
              )
              .flatMapMaybe(b -> inventoryFetcher.inventory(b.getIsbn())
                  .filter(stock -> stock >0)
                  .map(stock -> { 
                      b.setStock(stock); 
                     returnb; 
                  })
              );
   }
}

我们通过构造函数注入了 IsbnValidator。调用远程函数对 程序员 来说是透明的。

结论

下面的图片说明了我们在这一系列文章中开发的应用程序:

  • 我们有三个微服务(一个 Java 服务、一个 Groovy 服务和一个 Kotlin 服务)。
  • 这些微服务使用 Consul 进行服务发现。
  • 这些微服务使用 Zipkin 作为分布式跟踪服务。
  • 我们添加了第四个微服务,一个部署到 AWS Lambda 的功能。
  • 微服务之间的通信是安全的。每个请求在 Authorization Http 标头中包含一个 JWT 令牌就可以通过网络。JWT 令牌通过内部请求自动传播。

关于 Micronaut 的更多内容,请访问 官方网站

关于作者

Micronaut 教程(二):分布式跟踪、JWT 安全和 AWS Lambda 部署

Sergio del AmoCaballero是一名手机应用程序(iOS、Android,后端由 Grails/Micronaut 驱动)开发者。自 2015 年起,Sergio del Amo 为 Groovy 生态系统和微服务维护着一个新闻源 Groovy Calamari

查看英文原文: Micronaut Tutorial: Part 2: Easy Distributed Tracing, JWT Security and AWS Lambda Deployment


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

The Web Application Hacker's Handbook

The Web Application Hacker's Handbook

Dafydd Stuttard、Marcus Pinto / Wiley / 2011-9-27 / USD 50.00

The highly successful security book returns with a new edition, completely updated Web applications are the front door to most organizations, exposing them to attacks that may disclose personal infor......一起来看看 《The Web Application Hacker's Handbook》 这本书的介绍吧!

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具