本篇主要介绍了 Quarkus 中的远程调用,项目的结构采用了传统的微服务模式。演示了如何编写符合 istio 的 Quarkus java 程序。
项目准备
创建一个项目 xyzshop,包括三个模块(按照 dubbo,spring cloud 示例的方式来组织):
- xyzshop-api: facade 模块,包含接口,方法的声明
- xyzshop-provider: 服务的具体实现
- xyzshop-consumer: 服务调用方
本示例源码参见:https://github.com/cloudbeer/quarkus-demo-xyzdemo
facade 模块
facade 模块会被不同的模块引用,服务提供者来实现它,服务消费者通过引用它提供简化调用,这个包应该减小体积,去除非必要外部依赖。
本示例的facade 模块是 xyzshop-api, 里包含了实体类以及 OrderService 接口。
接口中可以约定接口的 restful 地址和配置。
代码语言:txt复制package com.tencent.xyzshop;
import com.tencent.xyzshop.model.Goods;
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
@Path("/order")
@RegisterRestClient(configKey = "xyzshop-provider")
public interface OrderService {
@POST
@Produces("application/json")
Goods save(Goods goods);
@GET
@Path("/id/{goodsId}")
@Produces("application/json")
Goods get(@PathParam long goodsId);
@GET
@Path("/hello")
@Produces("text/plain")
String sayHello();
}
为了能让 facade 模块能被注入,需要在编译的时候加入 CDI 索引。
在 pom.xml 中加入如下配置:
代码语言:txt复制<build>
<plugins>
<plugin>
<groupId>org.jboss.jandex</groupId>
<artifactId>jandex-maven-plugin</artifactId>
<version>1.0.7</version>
<executions>
<execution>
<id>make-index</id>
<goals>
<goal>jandex</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
provider 模块
xyzshop-provider 比较简单,直接引用xyzshop-api,实现接口就可以了。
但为了让 Quarkus 能找到资源,需要在实现类中加入 @Path 标记。
代码语言:txt复制@Path("/order")
public class OrderServiceImpl implements OrderService {
@Override
public Goods save(Goods goods) {
goods.setId(100L);
return goods;
}
@Override
public Goods get(long goodsId) {
Goods goods = new Goods();
goods.setId(goodsId);
goods.setPrice(12111);
goods.setStock(20);
goods.setTitle("腾讯黑鲨手机 M100");
return goods;
}
@Override
public String sayHello() {
return "世界,你好。 Hello world";
}
}
使用 mvn compile quarkus:dev
启动项目即可。
consumer 模块
需要在配置里指定服务的远程调用地址:
代码语言:txt复制# 远程调用配置
xyzshop-provider/mp-rest/url=http://localhost:8080
#xyzshop-provider/mp-rest/url=http://xyzshop-provider:8080
#xyzshop-provider/mp-rest/scope=javax.inject.Singleton
# 如果没有指定configKey 可以写下面的配置
# com.tencent.xyzshop.OrderService/mp-rest/url=http://xyzshop-provider:8080
# com.tencent.xyzshop.OrderService/mp-rest/scope=javax.inject.Singleton
部署的时候,我会把 k8s 的服务提供者部署成 xyzshop-provider,端口 8080。
但在本地开发的时候,用 http://localhost:8080
就好。
消费端的代码示例如下:
代码语言:txt复制@Path("/open/order")
public class OrderController {
@Inject
@RestClient
OrderService orderService;
@GET
@Path("/id/{goodsId}")
@Produces(MediaType.APPLICATION_JSON)
public Goods getGoods(@PathParam long goodsId){
Goods goods = orderService.get(goodsId);
goods.setTitle("consumer 给你打8折:" goods.getTitle() ": " goods.getPrice() * 0.8);
return goods;
}
}
同时启动,需要重新配置一下启动端口,在 application.properties 文件中:
代码语言:txt复制quarkus.http.port=9080
启动的时候有个警告 debug 端口被占用,可以重新指定一下,请使用下面的命令启动:
代码语言:txt复制mvn compile quarkus:dev -Ddebug=5006
rest-client 扩展已经在 rpc 中内置了 opentracing 的 header。istio 的调用链追踪可以完美支持。