暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

一个基于Dapr框架开发的演示项目

编程阁楼 2021-04-24
699
前文我们讲过Dapr及其核心特性《Dapr:一种全新思路的分布式应用开发框架》,今天我们来写个真实的项目,来实地体验下其对编写代码的带来的巨大改变。由于小编是Java出身,今天的项目我们就是用java语言进行开发。另外,本文仅关注后端服务,并不打算提供前端页面,读者仅需领会到其思想即可。

项目整体架构


代码片段

Dapr bindings-http.yaml 部署文件:

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
name: zcy-test1
namespace: default
spec:
type: bindings.http
version: v1
metadata:
- name: url
value: http://zcy-middleware-efficiency-agent:18099
Microservice A deploy.yaml配置文件:
apiVersion: apps/v1
kind: Deployment
metadata:
name: zcy-middleware-efficiency-console
labels:
app: java
spec:
replicas: 1
selector:
matchLabels:
app: java
template:
metadata:
labels:
app: java
k8s-app: middleware-efficiency-console
annotations:
dapr.io/enabled: "true"
dapr.io/app-id: "zcy-middleware-efficiency-console"
spec:
containers:
- name: java
image: zhangjb/zcy-middleware-efficiency-console:latest
env:
- name: "spring.datasource.url"
value: "jdbc:mysql://localhost:3306/db_middleware?useUnicode=true&characterEncoding=UTF-8&useSSL=false"
- name: "spring.datasource.username"
value: "zcy_middleware"
- name: "spring.datasource.password"
value: "123456"


---
apiVersion: v1
kind: Service
metadata:
name: zcy-middleware-efficiency-console
namespace: default
spec:
ports:
- name: default
port: 18090
protocol: TCP
selector:
k8s-app: middleware-efficiency-console
type: NodePort
Microservice B deploy.yaml配置文件:
apiVersion: apps/v1
kind: Deployment
metadata:
name: zcy-middleware-efficiency-agent
labels:
app: java
spec:
replicas: 1
selector:
matchLabels:
app: java
template:
metadata:
labels:
app: java
k8s-app: middleware-efficiency-agent
annotations:
dapr.io/enabled: "true"
dapr.io/app-id: "zcy-middleware-efficiency-agent"
spec:
containers:
- name: java
image: zhangjb/zcy-middleware-efficiency-agent:latest
env:
- name: "spring.datasource.url"
value: "jdbc:mysql://localhost:3306/db_middleware?useUnicode=true&characterEncoding=UTF-8&useSSL=false"
- name: "spring.datasource.username"
value: "zcy_middleware"
- name: "spring.datasource.password"
value: "123456"
---
apiVersion: v1
kind: Service
metadata:
name: zcy-middleware-efficiency-agent
namespace: default
spec:
clusterIP: None
ports:
- port: 8080
protocol: TCP
targetPort: 18099
selector:
workloadID_zcy-middleware-efficiency-agent: "true"
sessionAffinity: None
type: ClusterIP
status:
loadBalancer: {}

java代码调用片段:
@Value("${dapr.enabled:false}")
private boolean daprEnabled;
@Value("${dapr.port:3500}")
private int daprPort;


private static final String BINDINGS_HTTP_URL = "http://localhost:%d/v1.0/bindings/%s";
private static final String CONTENT_TYPE_JSON = "application/json; charset=utf-8";
private static final String CONTENT_TYPE_FORM = "application/x-www-form-urlencoded; charset=utf-8";


/**
* 查询redis db概要信息
*
* @param productId 中间件产品Id
* @param dbIndex 查询所有db信息
* @return
*/
@GetMapping(value = "/productId/{productId}/dbIndex/{dbIndex}", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
public Mono<Response<List<DbMsg>>> getDbMsgList(
@PathVariable Long productId,
@PathVariable Integer dbIndex) {


MiddlewareConnectionMessage connectionMessage = connectionMessageService.getConnectMessageByProductId(productId);
if (connectionMessage == null) {
log.warn("Can not get connection message with productId: {}", productId);
return Mono.just(Response.failOfMessage("Can not get connection message"));
}


String originPath = "/redis/operate/metaName/%s/dbIndex/%d";
String result;
try {
if (!daprEnabled) {
// 调用对应环境的agent接口
String originAgentUrl = connectionMessage.getLocalAgentUrl() + String.format(originPath, connectionMessage.getMetaName(), dbIndex);
log.info("originAgentUrl: {}", originAgentUrl);
result = HttpClientUtil.get(originAgentUrl);
} else {
MiddlewareProductInfo productInfo = middlewareProductInfoService.getMiddlewareProductInfoById(productId);
String metaName = productInfo.getRegion() + "-" + productInfo.getEnv();


log.info("begin call dapr bindings.http, metadata.name: {}", metaName);
String daprBindingsUrl = String.format(BINDINGS_HTTP_URL, daprPort, metaName);
BindingsData bindingsData = new BindingsData();
bindingsData.setOperation("get");
bindingsData.setMetadata(ImmutableMap.<String, String>builder().put("path",
String.format(originPath, connectionMessage.getMetaName(), dbIndex)).put("Content-Type", CONTENT_TYPE_JSON).build());


result = HttpClientUtil.postJsonBody(daprBindingsUrl, mapper.writeValueAsString(bindingsData), "utf-8");
log.info("call dapr bindings.http finished, metadata.name: {}", metaName);
}
return Mono.just(mapper.readValue(result, Response.class));
} catch (IOException e) {
log.error("getDbMsgList fail: {}", Throwables.getStackTraceAsString(e));
}
return Mono.just(Response.failOfMessage("getDbMsgList fail"));
}

重点是这段代码HttpClientUtil.postJsonBody(daprBindingsUrl, mapper.writeValueAsString(bindingsData), "utf-8")
,这里实际调用的是dapr bindings.http的地址http://localhost:%d/v1.0/bindings/%s
,如本文中这个地址为:http://localhost:3500/v1.0/bindings/zcy-test1
,其中3500
是dapr sidecar端口,zcy-test1
是dapr bindings定义的building block。

BindingsData是一个标准入参格式:
public class BindingsData {


private String operation;
private Object data;
private Map<String, String> metadata;


public String getOperation() {
return operation;
}


public void setOperation(String operation) {
this.operation = operation;
}


public Object getData() {
return data;
}


public void setData(Object data) {
this.data = data;
}


public Map<String, String> getMetadata() {
return metadata;
}


public void setMetadata(Map<String, String> metadata) {
this.metadata = metadata;
}


@Override
public String toString() {
return "BindingsData{" +
"operation='" + operation + '\'' +
", data=" + data +
", metadata=" + metadata +
'}';
}
}

转化为json格式如下:
{
"operation": "get", # request method
"data": null, # 请求参数,可以是字符串,也可以是request json body
"metadata": {
"path": "/redis/operate/metaName/redis/dbIndex/0",
"Content-Type": "application/json; charset=utf-8"
}
}
就这么简单,我们就轻松的通过daprEnabled
配置,实现了在普通http调用和dapr bindings.http模式进行切换。

源码地址

因为涉及一些私有信息,暂时不方便公开,读者如有兴趣演示测试,可以私信小编获取。
文章转载自编程阁楼,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论