【AICon】探索八个行业创新案例,教你在教育、金融、医疗、法律等领域实践大模型技术! >>> 了解详情
写点什么

如何借助 Quarkus 和 MicroProfile 实现微服务

  • 2021-10-20
  • 本文字数:10655 字

    阅读完需:约 35 分钟

如何借助Quarkus和MicroProfile实现微服务

为何需要微服务特性?

在微服务架构中,应用程序是由多个相互连接的服务组成的,这些服务协同工作以实现所需的业务功能。


所以,一个典型的企业级微服务架构如下所示:



最初,我们可能认为使用微服务架构实现一个应用程序是很容易的事情。但是,要恰当地完成这一点并不容易,因为我们会面临一些新的挑战,而这些挑战是单体架构所未曾遇到的。举例来讲,这样的挑战包括容错、服务发现、扩展性、日志和跟踪等。


为了应对这些挑战,每个微服务都需要实现在 Red Hat 被称为“微服务特性(microservicility)”的内容。这个术语指的是除了业务逻辑之外,服务必须要实现的一个横切性关注点的列表,总结起来如下图所示:



业务逻辑可以使用任何语言(Java、Go 或 JavaScript)或任何框架(Spring Boot、Quarkus)来实现,但是围绕着业务逻辑,我们应该实现如下的关注点:


API:服务可以通过一组预先定义的 API 操作进行访问。例如,在采用 RESTful Web API 的情况下,会使用 HTTP 作为协议。此外,API 还可以使用像Swagger这样的工具实现文档化。


发现(Discovery):服务需要能够发现其他的服务。


调用(Invocation):在服务发现之后,需要使用一组参数来调用它,并且可能会返回一个响应。


弹性(Elasticity):微服务架构很重要的特性之一就是每个服务都是有弹性的,这意味着它可以根据一些参数(比如系统的重要程度或当前的工作负载)独立地进行扩展和伸缩。


回弹性(Resiliency):在微服务架构中,我们在开发时应该要考虑到故障,特别是与其他服务进行通信的时候。在单体架构中,应用会作为一个整体进行启动和关闭。但是,当我们把应用拆分成微服务架构之后,应用就变成由多个服务组成的,所有的服务会通过网络互相连接,这意味着应用的某些部分可能在正常运行,而其他部分可能已经出现了故障。在这种情况下,很重要的一点就是遏制故障,避免错误通过其他的服务进行传播。回弹性(或称为应用回弹性)是指一个应用/服务能够对面临的问题作出反应的能力,在出现问题的时候,依然能够提供尽可能最好的结果。


管道(Pipeline):服务应该能够独立部署,不需要任何形式的部署编排。基于这一点,每个服务应该有自己的部署管道。


认证(Authentication):在微服务架构中,涉及到安全性时,很重要的一个方面就是如何认证/授权内部服务之间的调用。Web token(以及通用的 token)是在内部服务之间声明安全性的首选方式。


日志(Logging):在单体应用中,日志是很简单的事情,因为应用的所有组件都在同一个节点中运行。现在,组件以服务的形式分布在多个节点上,因此,为了全面了解日志跟踪的情况,我们需要一个统一的日志系统/数据收集器。


监控(Monitoring):要保证基于微服务的应用正确运行,很重要的一个方面就是衡量系统的运行情况、理解应用的整体健康状况并在出现问题的时候发出告警。监控是控制应用程序的重要方面。


跟踪(Tracing):跟踪用来可视化一个程序的流程和数据进展。当我们需要检查用户在整个应用中的操作时,它对开发人员或运维人员尤其有用。


Kubernetes 正在成为部署微服务的事实标准工具。它是一个开源的系统,用来自动化、编排、扩展和管理容器。


但是在我们提到的十个微服务特性中,通过使用 Kubernetes 只能覆盖其中的三个。



发现(Discovery) 是通过_Kubernetes Service_理念实现的。它提供了一种将_Kubernetes Pod_(作为一个整体)进行分组的方式,使其具有稳定的虚拟 IP 和 DNS 名。要发现一个服务只需要在发送请求的时候使用 Kubernetes 的服务名作为主机名即可。


使用 Kubernetes 调用(Invocation) 服务是非常容易的,因为平台本身提供了所需的网络来调用任意的服务。


弹性(Elasticity) (或者说扩展性)是 Kubernetes 从一开始就考虑到的问题,例如,如果运行kubectl scale deployment myservice --replicas=5命令的话,myservice deployment 就会扩展至五个副本或实例。Kubernetes 平台会负责寻找合适的节点、部署服务并维持所需数量的副本一直处于运行状态。


但是,剩余的微服务特性该怎么处理呢?Kubernetes 只涵盖了其中的三个,那么我们该如何实现剩余的哪些呢?


根据所使用的语言或框架,我们有很多可遵循的策略,但是在本文中,我们会看到如何使用Quarkus来实现其中某些微服务特性。

什么是 Quarkus?

Quarkus是一个全栈、Kubernetes 原生的 Java 框架,适用于 Java 虚拟机(JVM)和原生编译环境,针对容器环境对 Java 的进行了专门的优化,使其成为一个可用于无服务器、云和 Kubernetes 环境的高效平台。


Quarkus 没有重复发明轮子,而是使用了由标准/规范支撑的知名企业级框架,并使它们可以借助GraalVM编译成二进制文件。

什么是 MicroProfile?

Quarkus 集成了MicroProfile规范,将企业级 Java 生态系统转移到了微服务架构中。


在下图中,我们可以看到构成 MicroProfile 规范的所有 API。其中有些 API 是基于Jakarta EE(也就是以前的 Java EE)规范的,比如 CDI、JSON-P 和 JAX-RS,其他的则是由 Java 社区开发的。



接下来,我们就使用 Quarkus 来实现 API、调用、回弹性、认证、日志、监控和跟踪等微服务特性。


如何使用 Quarkus 实现微服务特性

起步

开始使用 Quarkus 的最快捷方式就是通过起始页面,在这里我们可以添加所需的依赖。就本例来讲,我们要注册如下的依赖以满足微服务特性的需求:


  • API:RESTEasy JAX-RS、RESTEasy JSON-B 和 OpenAPI

  • 调用:REST Client JSON-B

  • 回弹性:Fault Tolerance

  • 认证:JWT

  • 日志:GELF

  • 监控:Micrometer metrics

  • 跟踪:OpenTracing



我们可以手动选择这些依赖,也可以导航至如下的链接Microservicilities Quarkus Generator,在这里所有的依赖都已经选择好了。然后点击“Generate your application”按钮以下载包含脚手架应用的压缩文件。

服务

在本例中,我们会创建一个非常简单的应用,它只包含两个服务。其中一个服务名为_Rating service_,它会返回给定一本书的评分,另外一个服务名为_Book service_,它会返回某本书的信息及其评分。服务之间的所有调用必须要进行认证。


在下图中,我们可以看到完整系统的概览:



_Rating service_已经开发完成并且能够以 Linux 容器的形式供我们使用。我们可以使用如下的命令在 9090 端口启动该服务:


docker run --rm -ti -p 9090:8080 quay.io/lordofthejars/rating-service:1.0.0
复制代码


为了校验该服务,我们可以发送请求到http://localhost:9090/rate/1


curl localhost:8080/rate/1 -vv
> GET /rate/1 HTTP/1.1> Host: localhost:8080> User-Agent: curl/7.64.1> Accept: */*>< HTTP/1.1 401 Unauthorized< www-authenticate: Bearer {token}< Content-Length: 0
复制代码


这里的状态码是401 Unauthorized,这是因为我们没有在请求中以 bearer token(JWT)的形式提供认证信息。带有_group_ Echoer的合法 token 才能访问_rating service_。

API

Quarkus 使用大家熟知的 JAX-RS 规范来定义 RESTful web API。在底层,Quarkus 使用了 RESTEasy 实现,直接与 Vert.X 框架协作,而不是使用 Servlet 相关的技术。


现在我们为 book service 定义 API,实现最常见的操作:


import javax.ws.rs.Consumes;import javax.ws.rs.DELETE;import javax.ws.rs.GET;import javax.ws.rs.POST;import javax.ws.rs.Path;import javax.ws.rs.PathParam;import javax.ws.rs.Produces;import javax.ws.rs.QueryParam;import javax.ws.rs.core.MediaType;import javax.ws.rs.core.Response;import javax.ws.rs.core.UriBuilder;
@Path("/book")public class BookResource {
@GET @Path("/{bookId}") @Produces(MediaType.APPLICATION_JSON) public Book book(@PathParam("bookId") Long bookId) { // logic }
@POST @Consumes(MediaType.APPLICATION_JSON) public Response getBook(Book book) { // logic
return Response.created( UriBuilder.fromResource(BookResource.class) .path(Long.toString(book.bookId)) .build()) .build(); }
@DELETE @Path("/{bookId}") public Response delete(@PathParam("bookId") Long bookId) { // logic
return Response.noContent().build(); }
@GET @Produces(MediaType.APPLICATION_JSON) @Path("search") public Response searchBook(@QueryParam("description") String description) { // logic
return Response.ok(books).build(); }}
复制代码


我们要注意的第一件事情就是这里定义了四个不同的端点:


  • GET /book/{bookId}使用 GET HTTP 方法来返回图书的信息,其中包括它的评分。返回元素会自动反编组(unmarshal)为 JSON。

  • POST /book使用 POST HTTP 方法插入来自请求体内容的一本图书。请求体的内容会自动从 JSON 编组(marshal)为 Java 对象。

  • DELETE /book/{bookId}使用 DELETE HTTP 方法以根据 ID 删除某本图书。

  • GET /book/search?description={description}根据描述搜索图书。


要注意的第二件事就是返回的类型,有时候我们返回的是一个 Java 对象,有时候返回的是javax.ws.rs.core.Response的实例。当使用 Java 对象的时候,我们会将 Java 编组为@Produces注解所设置的媒体类型。具体到本服务中,输出是 JSON 文档。如果使用Response对象的话,对于返回什么内容给调用者,我们会有更细粒度的控制,例如,我们可以设置返回给调用者的 HTTP 状态码、头信息或内容。至于该优选选择哪种方式,这取决于具体的使用场景。

调用

定义完访问_book service_的 API 之后,我们就该开发调用_rating service_服务以获取图书评分信息的代码了。


Quarkus 使用MicroProfile Rest Client规范来访问外部的(HTTP)服务。它提供了一种类型安全的方式借助 HTTP 协议访问 RESTful 服务,在这个过程中,它会使用 JAX-RS 2.0 的一些 API 以实现一致性和更简单的重用。


我们要创建的第一个元素是代表远程服务的接口,它会用到 JAX-RS 的注解。


import javax.ws.rs.GET;import javax.ws.rs.Path;import javax.ws.rs.PathParam;import javax.ws.rs.Produces;import javax.ws.rs.core.MediaType;
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
@Path("/rate")@RegisterRestClientpublic interface RatingService {
@GET @Path("/{bookId}") @Produces(MediaType.APPLICATION_JSON) Rate getRate(@PathParam("bookId") Long bookId);
}
复制代码


getRate()方法被调用的时候,会触发一个对/rate/{bookId}的远程 HTTP 调用,在这个过程中bookId会被替换为方法参数中的值。很重要的一点就是,要为接口添加@RegisterRestClient注解。


然后,RatingService接口需要注入到BookResource中以执行远程调用。


import org.eclipse.microprofile.rest.client.inject.RestClient;
@RestClientRatingService ratingService;
@GET@Path("/{bookId}")@Produces(MediaType.APPLICATION_JSON)public Book book(@PathParam("bookId") Long bookId) { final Rate rate = ratingService.getRate(bookId);
Book book = findBook(bookId); return book;}
复制代码


@RestClient注解会注入对应接口的一个代理实例,从而提供了客户端的实现。


最后需要配置的就是服务的位置(_hostname_部分)。在 Quarkus 中,配置属性是在src/main/resources/application.properties文件中设置的。要配置服务的位置,我们需要使用 Rest Client 接口的全限定名并结合 URL 作为键,然后使用实际的位置作为值:


org.acme.RatingService/mp-rest/url=http://localhost:9090
复制代码


要想正确访问_rating_服务并摆脱401 Unauthorized的问题,我们还需要解决相互认证的问题。

认证

基于 token 的认证机制允许系统基于一个安全 token 进行认证、授权和身份验证。Quarkus 集成了MicroProfile JWT RBAC Security规范,以使用 JWT Bearer Token 来保护服务。


要使用 MicroProfile JWT RBAC Security 来保护一个端点,我们只需要为方法添加@RolesAllowed注解即可。


@GET@Path("/{bookId}")@RolesAllowed("Echoer")@Produces(MediaType.APPLICATION_JSON)public Book book(@PathParam("bookId") Long bookId)
复制代码


随后,我们还需要在application.properties文件中配置 token 的 issuer 以及公钥文件的位置,以便于校验 token 的签名:


mp.jwt.verify.publickey.location=https://raw.githubusercontent.com/redhat-developer-demos/quarkus-tutorial/master/jwt-token/quarkus.jwt.pubmp.jwt.verify.issuer=https://quarkus.io/using-jwt-rbac
复制代码


该扩展会执行如下的校验:token 是合法的;issuer 是正确的;token 没有被修改过;签名是合法的;它还没有过期。


现在,_book service_和_rating service_都使用相同的 JWT issuer 和秘钥进行保护,所以服务之间的通信需要用户进行认证,这是通过在Authentication头信息中提供一个合法的 bearer token 实现的。


rating service_运行起来之后,我们就可以使用如下的命令启动_book service


./mvnw compile quarkus:dev
复制代码


最后,我们可以发送请求来获取图书信息并提供一个合法的 JSON Web Token 作为 bearer token。


至于 token 如何生成超出了本文的范围,我们假设 token 已经能够生成:



curl -H "Authorization: Bearer eyJraWQiOiJcL3ByaXZhdGVLZXkucGVtIiwidHlwIjoiSldUIiwiYWxnIjoiUlMyNTYifQ.eyJzdWIiOiJqZG9lLXVzaW5nLWp3dC1yYmFjIiwiYXVkIjoidXNpbmctand0LXJiYWMiLCJ1cG4iOiJqZG9lQHF1YXJrdXMuaW8iLCJiaXJ0aGRhdGUiOiIyMDAxLTA3LTEzIiwiYXV0aF90aW1lIjoxNTcwMDk0MTcxLCJpc3MiOiJodHRwczpcL1wvcXVhcmt1cy5pb1wvdXNpbmctand0LXJiYWMiLCJyb2xlTWFwcGluZ3MiOnsiZ3JvdXAyIjoiR3JvdXAyTWFwcGVkUm9sZSIsImdyb3VwMSI6Ikdyb3VwMU1hcHBlZFJvbGUifSwiZ3JvdXBzIjpbIkVjaG9lciIsIlRlc3RlciIsIlN1YnNjcmliZXIiLCJncm91cDIiXSwicHJlZmVycmVkX3VzZXJuYW1lIjoiamRvZSIsImV4cCI6MjIwMDgxNDE3MSwiaWF0IjoxNTcwMDk0MTcxLCJqdGkiOiJhLTEyMyJ9.Hzr41h3_uewy-g2B-sonOiBObtcpkgzqmF4bT3cO58v45AIOiegl7HIx7QgEZHRO4PdUtR34x9W23VJY7NJ545ucpCuKnEV1uRlspJyQevfI-mSRg1bHlMmdDt661-V3KmQES8WX2B2uqirykO5fCeCp3womboilzCq4VtxbmM2qgf6ag8rUNnTCLuCgEoulGwTn0F5lCrom-7dJOTryW1KI0qUWHMMwl4TX5cLmqJLgBzJapzc5_yEfgQZ9qXzvsT8zeOWSKKPLm7LFVt2YihkXa80lWcjewwt61rfQkpmqSzAHL0QIs7CsM9GfnoYc0j9po83-P3GJiBMMFmn-vg" localhost:8080/book/1 -v
复制代码


响应再次提示禁止访问的错误:


<  HTTP/1.1 401 Unauthorized<  Content-Length: 0
复制代码


你可能会想在提供了合法的 token 之后,为何还会遇到这个错误。如果我们探查一下 book service 的控制台,就会看到如下的异常:


org.jboss.resteasy.client.exception.ResteasyWebApplicationException: Unknown error, status code 401    at org.jboss.resteasy.client.exception.WebApplicationExceptionWrapper.wrap(WebApplicationExceptionWrapper.java:107)    at org.jboss.resteasy.microprofile.client.DefaultResponseExceptionMapper.toThrowable(DefaultResponseExceptionMapper.java:21)
复制代码


出现这个异常的原因在于我们已经认证并授权访问_book service_,但是这个 bearer token 并没有传递到_rating service_中。



为了让Authorization头信息能够从传入的请求自动传播至 rest-client 请求,我们需要进行两项修改。


第一项修改是更新 Rest Client 接口并为其添加org.eclipse.microprofile.rest.client.inject.RegisterClientHeaders注解。


@Path("/rate")@RegisterRestClient@RegisterClientHeaderspublic interface RatingService {}
复制代码


第二项修改是配置哪些头信息要在请求之间进行传递,这是在application.properties文件中进行配置:


org.eclipse.microprofile.rest.client.propagateHeaders=Authorization
复制代码


我们再次使用相同的 curl,就会得到正确的输出了:


< HTTP/1.1 200 OK< Content-Length: 39< Content-Type: application/json<* Connection #0 to host localhost left intact{"bookId":2,"name":"Book 2","rating":1}* Closing connection 0
复制代码

回弹性

在微服务架构中,服务具备容错性是非常重要的,这样可以避免一个故障从某个服务传播至它的所有直接和间接的调用者。Quarkus 将MicroProfile Fault Tolerance规范与如下的注解集成到了一起,以便于处理故障相关的问题:


●    @Timeout:定义在抛出异常之前,某个服务最长的持续时间。


●    @Retry:如果调用失败的话,会再次进行尝试执行。


●    @Bulkhead:并发执行的限制,这样的话,该区域出现的故障不会导致整个系统超载。


●    @CircuitBreaker:当执行反复失败时,该服务会自动地快速失败。


●    @Fallback:当执行失败的时候,提供一个替代方案/默认值。


在访问_rating service_的时候,如果出现错误,我们会进行三次重试并在每次重试之间添加一秒钟的睡眠计时器。


@Retry(maxRetries = 3, delay = 1000)Rate getRate(@PathParam("bookId") Long bookId);
复制代码


现在,我们关掉_rating service_并执行请求,将会抛出如下的异常:


org.jboss.resteasy.spi.UnhandledException: javax.ws.rs.ProcessingException: RESTEASY004655: Unable to invoke request: org.apache.http.conn.HttpHostConnectException: Connect to localhost:9090 [localhost/127.0.0.1, localhost/0:0:0:0:0:0:0:1] failed: Connection refused
复制代码


显然,这里会有错误,但是需要注意在抛出异常之前,我们经历了三秒钟的时间,这是因为执行了三次重试,并且每次重试间有一秒钟的延迟。


在这种情况下,_rating service_已经被我们停掉了,所以不可能恢复,但是在现实世界的例子中,_rating service_可能只会停机很短的时间,或者服务部署了多个副本,这样的话,简单的重试操作可能就足以恢复并提供一个合法的响应。


但是,当重试不足以解决问题并且抛出异常的时候,我们可以将错误传播至调用者,也可以为调用提供一个替代值。这个替代值可以来自对其他系统的调用(如分布式缓存),也可以是一个静态值。


就本例来讲,当连接_rating service_失败的时候,我们会返回一个值为 0 的评分值。


为了实现这个回退(fallback)逻辑,我们首先要做的就是实现org.eclipse.microprofile.faulttolerance.FallbackHandler接口,并将返回值设置为相同的类型,因为回退策略方法的作用是返回一个替代值。在本例中,会返回一个默认的Rate对象。


import org.eclipse.microprofile.faulttolerance.ExecutionContext;import org.eclipse.microprofile.faulttolerance.FallbackHandler;
public class RatingServiceFallback implements FallbackHandler&lt;Rate&gt; {
@Override public Rate handle(ExecutionContext context) { Rate rate = new Rate(); rate.rate = 0; return rate; }
}
复制代码


最后要做的就是为getRating()方法添加@org.eclipse.microprofile.faulttolerance.Fallback注解,配置在无法进行恢复的时候要执行的回退类。


@Retry(maxRetries = 3, delay = 1000)@Fallback(RatingServiceFallback.class)Rate getRate(@PathParam("bookId") Long bookId);
复制代码


如果我们重复前面的请求,此时不会抛出异常,而是会返回一个合法的输出,其中评分字段的值被设置成了 0。


* Connection #0 to host localhost left intact{"bookId":2,"name":"Book 2","rating":0}* Closing connection 0
复制代码


相同的方式也可以用于该规范提供的其他模式。比如,如果使用断路器模式的话::


@CircuitBreaker(requestVolumeThreshold = 4,               failureRatio=0.75,               delay = 1000)
复制代码


如果在滚动时间窗口中,四个连续的请求中有_三个(即 4 x 0.75)_出现了故障,那么断路器就会打开 1000 毫秒的时间,然后会回到半开状态。当断路器处于半开状态时,如果调用成功了,那么会再次关闭。否则的话,它会继续保持打开的状态。

日志

在微服务架构中,推荐将所有服务的日志收集到一起,以便于高效使用和理解。


其中有个解决方案就是使用Fluentd,这是一个开源的数据收集器,能够用来实现 Kubernetes 中统一的日志层。Quarkus 使用 Graylog 扩展日志格式(Graylog Extended Log Format,GELF)与 Fluentd 进行了集成。


具体的集成是非常简单的。首先,像其他的 Quarkus 应用那样使用日志逻辑:


import org.jboss.logging.Logger;
private static final Logger LOG = Logger.getLogger(BookResource.class);
@GET@Path("/{bookId}")@RolesAllowed("Echoer")@Produces(MediaType.APPLICATION_JSON)public Book book(@PathParam("bookId") Long bookId) { LOG.info("Get Book");
复制代码


接下来,启用 GELF 格式并设置 Fluentd 服务器的地址:


quarkus.log.handler.gelf.enabled=truequarkus.log.handler.gelf.host=localhostquarkus.log.handler.gelf.port=12201
复制代码


最后,我们可以发送请求给实现日志功能的端点:


curl -H "Authorization: Bearer ..." localhost:8080/book/1
{"bookId":1,"name":"Book 1","rating":3}
复制代码


在输出方面并没有任何变化,但是日志已经被传输到了 Fluentd 上。如果我们使用Kibana来可视化数据的话,就会看到如下所示的日志行:


监控

监控是另外一个我们需要在微服务架构中实现的微服务特性。Quarkus 集成了Micrometer实现应用监控。Micrometer 为几乎所有流行的监控系统提供了一个简单的入口,从而能够让我们在避免供应商锁定的前提下 instrument 基于 JVM 的应用。


对于本例来讲,我们使用Prometheus格式作为监控输出,但是 Micrometer(和 Quarkus)也支持其他的格式,比如 Azure Monitor、Stackdriver、SignalFx、StatsD 和 DataDog。


我们可以注册如下的 Maven 依赖以提供 Prometheus 输出:


<dependency>  <groupId>io.quarkus</groupId>;  <artifactId>quarkus-micrometer-registry-prometheus</artifactId></dependency>
复制代码


Micrometer 扩展默认会注册一些与系统、JVM 或 HTTP 相关的指标。所收集到的指标的一个子集可以通过/q/metrics端点进行访问,如下所示:


curl localhost:8080/q/metrics
jvm_threads_states_threads{state="runnable",} 22.0jvm_threads_states_threads{state="blocked",} 0.0jvm_threads_states_threads{state="waiting",} 10.0http_server_bytes_read_count 1.0http_server_bytes_read_sum 0.0
复制代码


但是,我们还可以使用 Micrometer API 实现应用特定的指标。


在这里,我们实现一个自定义的指标来衡量评分最高的图书。


要注册一个指标,也就是本例中的一个 gauge,是通过使用io.micrometer.core.instrument.MeterRegistry类来完成的。


private final MeterRegistry registry;private final LongAccumulator highestRating = new LongAccumulator(Long::max, 0);
public BookResource(MeterRegistry registry) { this.registry = registry; registry.gauge("book.rating.max", this, BookResource::highestRatingBook);}
复制代码


我们发送一些请求并校验 gauge 是否被正确地更新了。


curl -H "Authorization: Bearer ..." localhost:8080/book/1
{"bookId":1,"name":"Book 1","rating":3}
curl localhost:8080/q/metrics
# HELP book_rating_max# TYPE book_rating_max gaugebook_rating_max 3.0
复制代码


我们还可以设置一个计时器,记录从 rating service 获取评分信息所耗费的时间。


Supplier<Rate> rateSupplier = () -> {      return ratingService.getRate(bookId);};
final Rate rate = registry.timer("book.rating.test").wrap(rateSupplier).get();
复制代码


我们发送一些请求并校验是否收集了评分服务的耗时。


# HELP book_rating_test_seconds# TYPE book_rating_test_seconds summarybook_rating_test_seconds_count 4.0book_rating_test_seconds_sum 1.05489108# HELP book_rating_test_seconds_max# TYPE book_rating_test_seconds_max gaugebook_rating_test_seconds_max 1.018622001
复制代码


Micrometer 使用MeterFilter实例来自定义由MeterRegistry实例所发出的指标。Micrometer 扩展将会探测到MeterFilter CDI bean 并使用它们来初始化MeterRegistry实例。


例如,我们可以定义一个通用的标签来设置应用运行的环境(prod、testing、staging 等)。


@Singletonpublic class MicrometerCustomConfiguration {
@Produces @Singleton public MeterFilter configureAllRegistries() { return MeterFilter.commonTags(Arrays.asList( Tag.of("env", "prod"))); }
}
复制代码


发送一个新的请求并校验指标是否添加了标签。


http_client_requests_seconds_max{clientName="localhost",env="prod",method="GET",outcome="SUCCESS",status="200",uri="/rate/2",} 0.0
复制代码


请注意,标签env包含的值为prod

跟踪

Quarkus 应用使用OpenTracing规范来为互相交互的 Web 应用提供分布式跟踪能力。


接下来,我们配置 OpenTracing 连接一个 Jaeger 服务器,并将服务的名字设置为 book-service 以标识跟踪信息:


quarkus.jaeger.enabled=truequarkus.jaeger.endpoint=http://localhost:14268/api/tracesquarkus.jaeger.service-name=book-servicequarkus.jaeger.sampler-type=constquarkus.jaeger.sampler-param=1
复制代码


现在,我们发送一个请求:


curl -H "Authorization: Bearer ..." localhost:8080/book/1
{"bookId":1,"name":"Book 1","rating":3}
复制代码


访问 Jaeger UI 来校验调用过程被进行了跟踪:


结论

开发和实现微服务架构要比开发单体应用更具挑战性。我们相信,微服务特性能够促使你在应用基础设施方面正确地开发服务。


我们在这里所阐述的微服务特性(除 API 和管道之外)都是新的理念,或者说在单体应用中会以不同的方式来实现。其中的原因在于,现在应用被拆分成了多个组成部分,所有的这些组成部分需要在网络中进行相互连接。


如果你打算开发微服务并将它们部署到 Kubernetes 的话,那么 Quarkus 是一个很好的解决方案,因为它可以很平滑地与 Kubernetes 进行集成,实现大多数的微服务特性都非常简单,只需要几行代码就能实现。


用来阐述本文的源码都可以在github上找到。


作者简介:


Alex Soto 是红帽公司的开发者体验总监。他对 Java 领域、软件自动化充满热情,他相信开源软件模式。Soto 是Manning的《Testing Java Microservices》O’Reilly的《Quarkus Cookbook》两本书的共同作者,他还是多个开源项目的贡献者。自 2017 年以来,他一直是 Java Champion,是国际演讲者和 Salle URL 大学的教师。


英文原文:


Implementing Microservicilities with Quarkus and MicroProfile

2021-10-20 14:112446

评论

发布
暂无评论
发现更多内容

算云融合促发展,天翼云以领先云网算力助推数字中国建设!

天翼云开发者社区

SketchUp Pro(草图大师2023)中文版 Mac/win

魔仙苹果mac堡

SketchUp Pro 2023 SketchUp Pro中文版 草图大师2023下载

MobTech MobLink|无码邀请是怎么处理的

MobTech袤博科技

为何说低代码平台会提升软件开发效率?

这我可不懂

软件开发 低代码 JNPF

软件测试/测试开发丨通用 api 封装实战,带你深入理解 PO

测试人

软件测试 自动化测试 测试开发

JetBrains CLion 2023中文版安装教程CLion 2023新功能

魔仙苹果mac堡

C/C++ CLion 2023 JetBrains CLion破解版

架构训练营模块二作业

请叫我馒头哥丶

架构实战营

社区分享 | Orillusion 引擎入门系列 —— 如何创建一个简单的 3D 示例

Orillusion

WebGL 元宇宙 web3d #WebGPU #开源

大咖说丨云计算:数字世界的“中枢神经”

天翼云开发者社区

喜讯!天翼云荣获国际AI顶会ABAW季军

天翼云开发者社区

基于 Nginx&Lua 实现自建服务端埋点系统

亚马逊云科技 (Amazon Web Services)

Amazon

不动产行业国产化加速,明源云上榜《中国信创500强》

科技热闻

最新版本 Stable Diffusion 开源 AI 绘画工具之使用篇

极客飞兔

人工智能 图文生成 AI绘画 Stable Diffusion

Springfox与SpringDoc——swagger如何选择(SpringDoc入门)

天翼云开发者社区

5月上海线下 · CSM认证周末班【提前报名特惠】“全球金牌课程”CST导师亲授

ShineScrum捷行

关于验证码,你不知道的一些问题!

宙哈哈

php html 记录 验证码

Autodesk AutoCAD 2024 Mac(cad2024) v2024.3 支持M1 兼容Mac13系统

魔仙苹果mac堡

mac软件下载 M1芯片 cad2024激活版 Autodesk AutoCAD

AntDB数据库携超融合流式实时数仓亮相第25届中国高速公路信息技术化大会

亚信AntDB数据库

AntDB AntDB数据库 企业号 4 月 PK 榜

GaussDB(DWS)云原生数仓技术解析

华为云开发者联盟

数据库 后端 华为云 华为云开发者联盟 企业号 4 月 PK 榜

联合解决方案|亚信科技AntDB携手蓝凌软件,助推企业数字化办公转型升级

亚信AntDB数据库

AntDB AntDB数据库 企业号 4 月 PK 榜

建木在 Rainbond 上使用实践

北京好雨科技有限公司

云原生 CI/CD #Kubernetes# rainbond 企业号 4 月 PK 榜

长安信托:拥抱数字信托,探索多项目管理新路径

万事ONES

Higress GitHub star 突破 1k,来自社区开发者和用户的寄语

阿里巴巴云原生

阿里云 云原生 Higress

Excelize 入选 2022 中国开源创新大赛优秀项目

xuri

golang 开源 Go 语言 Excelize OOXML

解决Parallels Desktop 18.2.0提示“由于临界误差,不能启动虚拟机”的问题

魔仙苹果mac堡

Parallels Desktop 18 pd18虚拟机 PD虚拟机不能联网

安全可信| 天翼云算力调度平台通过信通院首批可信算力云服务评估!

天翼云开发者社区

5月在线 · A-CSM认证周末班【提前报名特惠】“敏捷教练必修课程”CST导师亲授

ShineScrum捷行

AI开发实践:关于停车场中车辆识别与跟踪

华为云开发者联盟

人工智能 华为云 华为云开发者联盟 企业号 4 月 PK 榜 车辆检测

autodesk maya 2023最新中文版 Maya动画和建模软件

魔仙苹果mac堡

Autodesk Maya maya破解版 玛雅2023下载

Ample Sound Ample Bass Upright III Mac(虚拟立式低音乐器)

魔仙苹果mac堡

软件测试/测试开发丨两个步骤轻松搞定测试环境问题

测试人

软件测试 自动化测试 测试开发

如何借助Quarkus和MicroProfile实现微服务_云原生_Alex Soto_InfoQ精选文章