分享
  1. 首页
  2. 文章

dapr实战(2):使用go和java来实现dapr 官方的Hello world和对其过程的研究

narry · · 1693 次点击 · · 开始浏览
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

引言

在前面上一次的实战中,我们搭建了dapr的本地开发环境,并且部署了dapr官方的Hello World示例代码,为了加深对Dapr的理解,在本文中使用go 和 java语言重写Dapr的官方示例代码

Dapr的官方示例代码Hello World的分析

dapr示例

在服务端中提供了三个对Order的处理逻辑:增加订单,查询订单和删除订单,这三个业务处理都是以REST的方式对外提供服务,而这三个业务处理都会通过Dapr Runtime与Redis交互来完成数据的存放,读取和删除;而python所开发的客户端,周期的通过Dapr Runtime去调用服务端的增加订单的接口

官方示例代码重新实现

服务端的代码分为两个部分:提供的REST服务 和 访问Redis,后面将对这两个部分进行分析

使用golang实现服务端

提供REST服务

REST服务这部分的开发与一般的rest服务的开发并没有什么不同之处,所以在这里我选择自己比较熟悉的echo框架作为了开发框架,分别开发了order的增查删的接口,代码如下:
路由注册部分,完整代码参考

 e := echo.New()
 e.POST("/neworder", orderResource.Neworder)
 e.GET("/order", orderResource.Queryorders)
 e.DELETE("/order/:id", orderResource.DeleteOrder)

REST请求处理部分,完整代码参考

func (o *OrderResource) Neworder(c echo.Context) error {
 data := &Data{}
 err := c.Bind(data)
 if err != nil {
 return err
 }
 err = o.cache.Add(data)
 if err != nil {
 return c.String(500, err.Error())
 }
 return c.String(200, "add success")
}
func (o *OrderResource) Queryorders(c echo.Context) error {
 data, err := o.cache.Query()
 if err != nil {
 return c.String(500, err.Error())
 }
 return c.JSON(200, data)
}
func (o *OrderResource) DeleteOrder(c echo.Context) error {
 id := c.Param("id")
 err := o.cache.delete(id)
 if err != nil {
 return c.String(500, err.Error())
 }
 return c.String(200, "delete success")
}

在这里需要关注的一点就是在这里注册的path和访问这个rest接口的path还是有所不同,通过Dapr来访问时,还需要增加http://xxxx:<DAPR_HTTP_PORT>/v1.0/invoke/<APP_ID>/method/<Method> 来访问才行,如下:

http://localhost:3500/v1.0/invoke/nodeapp/method/neworder

访问redis

要通过Dapr runtime去访问redis服务,必须按照Dapr的state规范来实现(注:Dapr中所涉及到的规范,将在以后的文章中来进行介绍)
相关代码如下,完整代码请参考

func (cache *CacheService) Add(data *Data) error {
 request := cache.httpclient.Post()
 request.Path(cache.stateUrl)
 state := &State{
 Key: "order",
 Value: data,
 }
 states := []*State{state}
 response, err := request.JSON(&states).Send()
 if err != nil {
 return err
 }
 if !response.Ok {
 return fmt.Errorf("add state error,statuCode:%d,messag:%s", response.StatusCode, response.String())
 }
 log.Info("Successfully persisted state.")
 return nil
}
func (cache *CacheService) Query() (*Data, error) {
 request := cache.httpclient.Get()
 request.Path(cache.stateUrl + "/order")
 response, err := request.Send()
 if err != nil {
 return nil, err
 }
 if !response.Ok {
 return nil, fmt.Errorf("query state error,statuCode:%d,messag:%s", response.StatusCode, response.String())
 }
 data := &Data{}
 err = response.JSON(&data)
 return data, err
}
func (cache *CacheService) delete(id string) error {
 request := cache.httpclient.Delete()
 request.Path(cache.stateUrl + "/" + id)
 request.AddHeader("Content-Type", "application/json")
 response, err := request.Send()
 if err != nil {
 return err
 }
 if !response.Ok {
 return fmt.Errorf("delete state error,id:%s,statuCode:%d,messag:%s", id, response.StatusCode, response.String())
 }
 return nil
}

使用java实现客户端

相关代码如下,完整代码参考


public class DaprHelloworldClientApplication {
 private final static String bodyTmpl="{\"data\": {\"orderId\": \"%s\"}}";
 public static void main(String[] args) throws IOException, InterruptedException {
 Thread sendThread = new Thread(new Runnable() {
 public void run() {
 int i=0;
 while(!Thread.interrupted()){
 try {
 Thread.sleep(5000);
 i++;
 String body=String.format(bodyTmpl,String.valueOf(i));
 sendRequest(body);
 } catch (Exception e) {
 e.printStackTrace();
 }
 }
 }
 });
 sendThread.start();
 Thread.sleep(5*60*60*1000);
 }
 public static void sendRequest(String body) throws IOException {
 String httpPort = System.getenv("DAPR_HTTP_PORT");
 if (httpPort == null) {
 httpPort = "3500";
 }
 String resultUrl = "http://localhost:" + httpPort + "/v1.0/invoke/goapp/method/neworder";
 URL url = new URL(resultUrl);
 HttpURLConnection connection = (HttpURLConnection) url.openConnection();
 connection.setRequestMethod("POST");
 connection.setRequestProperty("Content-Type", "application/json;charset=UTF-8");
 connection.setRequestProperty("Connection", "Keep-Alive");
 connection.setUseCaches(false);
 connection.setDoOutput(true);
 connection.setDoInput(true);
 System.out.println("request body:"+body);
 DataOutputStream out = new DataOutputStream(connection.getOutputStream());
 out.write(body.getBytes("UTF-8"));
 out.flush();
 out.close();
 connection.connect();
 BufferedReader bReader = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8"));
 String line, resultStr = "";
 while (null != (line = bReader.readLine())) {
 resultStr += line;
 }
 System.out.println(resultStr);
 bReader.close();
}
}

在上面的代码中,比较特殊的情况是其访问服务端REST的URL是:"http://localhost:" + httpPort + "/v1.0/invoke/goapp/method/neworder"

小结

从上面的代码看来使用Drap后,REST的开发并没有变的麻烦,并且访问Redis的代码还更加的简洁,不在需要使用特定的redis客户端,这样降低了业务开发人员的学习成本,向着云原生又迈进的一步

部署程序

用于使用java开发,所以整个系统都使用maven来进行编译,当然在

启动服务端

dapr run --app-id goapp --app-port 3000 --port 3500 ./helloworld-server
i️ Starting Dapr with id goapp. HTTP Port: 3500. gRPC Port: 39669
== APP ==
== APP == ____ __
== APP == / __/___/ / ___
== APP == / _// __/ _ \/ _ \
== APP == /___/\__/_//_/\___/ v4.1.16
== APP == High performance, minimalist Go web framework
== APP == https://echo.labstack.com
== APP == ____________________________________O/_______
== APP == O\
== APP == ⇨ http server started on [::]:3000

启动客户端

 dapr run --app-id javaapp `java -jar dapr-helloworld-client-0.0.1-SNAPSHOT-jar-with-dependencies.jar`

在启动客户端后,可以在服务端的终端上看到如下的代码输出:

== APP == {"time":"2020年06月01日T07:25:37.690025853-04:00","level":"INFO","prefix":"-","file":"cache_service.go","line":"48","message":"Successfully persisted state."}
== APP == {"time":"2020年06月01日T07:25:42.712922528-04:00","level":"INFO","prefix":"-","file":"cache_service.go","line":"48","message":"Successfully persisted state."}
== APP == {"time":"2020年06月01日T07:25:47.725423292-04:00","level":"INFO","prefix":"-","file":"cache_service.go","line":"48","message":"Successfully persisted state."}

总结

通过用java和golang开发了官方的实例代码,个人感觉dapr对代码的限制比较少,开发难度不大,在后面的实战中,将试试在Kubernetes来部署Dapr


微信公众号

有疑问加站长微信联系(非本文作者)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

关注微信
1693 次点击
暂无回复
添加一条新回复 (您需要 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传

用户登录

没有账号?注册
(追記) (追記ここまで)

今日阅读排行

    加载中
(追記) (追記ここまで)

一周阅读排行

    加载中

关注我

  • 扫码关注领全套学习资料 关注微信公众号
  • 加入 QQ 群:
    • 192706294(已满)
    • 731990104(已满)
    • 798786647(已满)
    • 729884609(已满)
    • 977810755(已满)
    • 815126783(已满)
    • 812540095(已满)
    • 1006366459(已满)
    • 692541889

  • 关注微信公众号
  • 加入微信群:liuxiaoyan-s,备注入群
  • 也欢迎加入知识星球 Go粉丝们(免费)

给该专栏投稿 写篇新文章

每篇文章有总共有 5 次投稿机会

收入到我管理的专栏 新建专栏