2021-10-17 dubbogo 基础使用

一、dubbogo相关介绍链接

1、Dubbo基本使用与原理详解

2、dubbogo 3.0:牵手 gRPC 走向云原生时代

3、快速上手 dubbo-go

4、dubbogo github page

5、dubbo-go examples

6、dubbbo 3.0 快速开始

7、hesson协议序列化example

二、安装zookeeper

这里我们使用zookeeper作为注册中心

1、安装docker-compose

 apt install docker-compose
image.png

2、编写docker-compose.yaml

mkdir zookeeper
cd zookeeper
vim docker-compose.yaml

输入如下内容并保存

version: '3'
services:
  zookeeper:
    image: zookeeper
    ports:
      - 2181:2181
  admin:
    image: apache/dubbo-admin:latest
    depends_on:
      - zookeeper
    ports:
      - 8081:8080
    environment:
      - admin.registry.address=zookeeper://zookeeper:2181
      - admin.config-center=zookeeper://zookeeper:2181
      - admin.metadata-report.address=zookeeper://zookeeper:2181

运行

docker-compose -f /home/jun/docker/zookeeper/docker-compose.yaml up -d

查看容器是否启动

image.png

主机浏览器打开地址查看dubbo-admin:http://192.168.96.129:8081
image.png

登录用户名密码均为root
192.168.96.129换为自己虚拟机的ip

三、JAVA

此文介绍一个示例,使用spring boot dubbojava客户端调用dubbo-gogo语言服务

3.1、初始化springboot dubbo

3.1.1、spring.io

1.png

按照图示新建一个项目,文件夹如下图:


image.png

3.1.2、转换为多module项目

将当前目录所有文件移动到名为dubbo-consumer的子目录下,然后在当前目录新增pom文件



    4.0.0
    
        org.springframework.boot
        spring-boot-starter-parent
        2.5.5
         
    

    com.example
    demo
    0.0.1-SNAPSHOT
    demo
    Demo project for Spring Boot

    pom

    
        1.8
    

    
        dubbo-client
        dubbo-consumer
    

    
        
        
            org.projectlombok
            lombok
            true
        
    

修改dubbo-consumerpom文件内容为:



    4.0.0
    
        com.example
        demo
        0.0.1-SNAPSHOT
    

    dubbo-consumer
    0.0.1-SNAPSHOT
    dubbo-demo-consumer
    
    
        false
        2.7.14
        2.12.0
        3.4.14
    
    
        
            org.springframework.boot
            spring-boot-starter-web
        

        
            org.springframework.boot
            spring-boot-starter-test
            test
        
        
        
            org.apache.dubbo
            dubbo-spring-boot-starter
            ${dubbo.version}
        
        
        
            org.apache.dubbo
            dubbo-dependencies-zookeeper
            ${dubbo.version}
            pom
            
                
                    org.slf4j
                    slf4j-log4j12
                
            
        
        
            com.example
            dubbo-client
            0.0.1-SNAPSHOT
            compile
        
    

    
        
            
                org.springframework.boot
                spring-boot-maven-plugin
            
        
    


新建子项目dubbo-client,用于存放dubbogo适配的接口类,pom文件内容为



    4.0.0
    
        com.example
        demo
        0.0.1-SNAPSHOT
    
    
    dubbo-client

3.1.3、最后项目的目录情况:

image.png
  • --> 1: dubbogo互通协议的interface接口
  • --> 2: dubbogo互通协议的dto请求响应类型
  • --> 3: dubbogo消费端的请求接口类
  • --> 4: dubbogo消费端的配置文件

3.2、代码编写

3.2.1、dubbo-client

  • QueryUserParam
package com.demo.exp.dto;

import lombok.Data;

import java.io.Serializable;

@Data
public class QueryUserParam implements Serializable {
    private String userName;
    private String userId;
}
  • QueryUserResponse
package com.demo.exp.dto;

import lombok.Data;

import java.io.Serializable;

@Data
public class QueryUserResponse implements Serializable {
    private String userId;
    private String userName;
    private String birthDate;
    private long age;
    private boolean isDead;
}
  • UserService
package com.demo.exp.service;

import com.demo.exp.dto.QueryUserParam;
import com.demo.exp.dto.QueryUserResponse;

public interface UserService {
    QueryUserResponse QueryUser(QueryUserParam req);
}

3.2.2、dubbo-consumer

  • dto.Result
package com.example.demo.dto;

import lombok.Getter;
import lombok.Setter;

import java.io.Serializable;

@Getter
@Setter
public class Result implements Serializable {
    private static final long serialVersionUID = 1L;
    // 业务码code
    private int resultCode;
    // 返回信息
    private String message;
    // 返回的数据
    private T data;

    public Result(){}

    public Result(int code, String message){
        this.resultCode = code;
        this.message = message;
    }

    @Override
    public String toString(){
        return "Result{" +
                "resultCode=" + resultCode +
                ", message='" + message + "'" +
                ", data=" + data +
                "}";
    }

}
  • dto.ResultGenerator
package com.example.demo.dto;

import org.springframework.util.StringUtils;

public class ResultGenerator {
    private static final String DEFAULT_SUCCESS_MESSAGE = "success";
    private static final String DEFAULT_FAIL_MESSAGE = "fail";
    private static final int RESULT_CODE_SUCCESS = 200;
    private static final  int RESULT_CODE_SERVER_ERROR = 500;

    public static Result genSuccessResult(){
        Result res = new Result();
        res.setResultCode(RESULT_CODE_SUCCESS);
        res.setMessage(DEFAULT_SUCCESS_MESSAGE);
        return res;
    }

    public static Result genSuccessResult(String msg){
        Result res = new Result();
        res.setResultCode(RESULT_CODE_SUCCESS);
        res.setMessage(msg);
        return res;
    }

    public static Result genSuccessResult(Object data){
        Result res = new Result();
        res.setResultCode(RESULT_CODE_SUCCESS);
        res.setMessage(DEFAULT_SUCCESS_MESSAGE);
        res.setData(data);
        return res;
    }

    public static Result genFailResult(String msg){
        Result res = new Result();
        res.setResultCode(RESULT_CODE_SERVER_ERROR);
        if(!StringUtils.hasLength(msg)){
            res.setMessage(DEFAULT_FAIL_MESSAGE);
        }else{
            res.setMessage(msg);
        }
        return res;
    }

    public static Result genErrorResult(int code, String msg){
        Result res = new Result();
        res.setResultCode(code);
        res.setMessage(msg);
        return res;
    }
}
  • UserController
package com.example.demo.controllers;

import com.demo.exp.dto.QueryUserParam;
import com.demo.exp.dto.QueryUserResponse;
import com.demo.exp.service.UserService;
import com.example.demo.dto.Result;
import com.example.demo.dto.ResultGenerator;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.rpc.RpcContext;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api/user")
@Slf4j
public class UserController {
    @DubboReference(retries = 0, timeout = 1000 * 60, application = "dubbogo-demo", group = "dubbo-service", version = "1.0.0")
    UserService userService;

    @GetMapping("/query")
    @ResponseBody
    public Result QueryUser(){
        QueryUserParam req = new QueryUserParam();
        req.setUserName("test");
        RpcContext rpcContext = RpcContext.getContext();
        rpcContext.setAttachment("app", "dubbo-consumer");
        QueryUserResponse resp = null;
        try{
            resp = userService.QueryUser(req);
        }catch (Throwable e){
            log.error("QueryUser error", e);
            return ResultGenerator.genFailResult(e.getMessage());
        }
        return ResultGenerator.genSuccessResult(resp);
    }
}
  • application.yml配置文件
server:
  port: 7000

spring:
  application:
    name: dubbo-consumer
logging:
  level:
    root: info

#dubbo
dubbo:
  application:
    name: dubbo-consumer
  registry:
    address: zookeeper://192.168.96.129:2181
    timeout: 60000
  protocal:
    name: dubbo
  consumer:
    retries: 1
    check: false

四、go

4.1、初始化go项目

mkdir dubbogodemo
cd dubbogodemo
go mod init dubbo-demo
go get github.com/pkg/errors
go get dubbo.apache.org/dubbo-go/[email protected]
image.png

4.2、 编写go代码

4.2.1、项目结构

image.png
  • --> 1: dubbogo互通协议的dto请求响应类型
  • --> 2: dubbogo互通协议的interface实现
  • --> 3: 工具类
  • --> 4: dubbogo服务提供方的配置文件
  • --> 5: dubbogo服务启动工具

4.2.2、dto

  • UserRequest
package dto

type UserRequest struct {
    UserName string // 用户名
    UserId string // 用户id
}

func(req UserRequest) JavaClassName() string{
    return "com.demo.exp.dto.QueryUserParam"
}
  • UserResponse
package dto

type UserResponse struct {
    UserName string // 用户名
    UserId string // 用户id
    BirthDate string // 出生日期
    Age int64 // 年龄
    IsDead bool // 是否已去世
}

func(req UserResponse) JavaClassName() string{
    return "com.demo.exp.dto.QueryUserResponse"
}

4.2.3、service

  • UserService
package service

import (
    "context"
    "dubbo-demo/pkg/dto"
    "dubbo-demo/pkg/util"
    "github.com/pkg/errors"
    "time"
)

type UserService struct {

}

func (u *UserService) Reference() string {
    return "UserService"
}

func (u *UserService) QueryUser(ctx context.Context, in *dto.UserRequest)(*dto.UserResponse, error){
    appName := util.GetDubboContextAppName(ctx)
    if appName == ""{
        return nil, errors.Errorf("auth error, no appname")
    }
    if appName != "dubbo-consumer"{
        return nil, errors.Errorf("auth error, not allowed")
    }
    if in.UserId != ""{
        if in.UserId != "123456789"{
            return nil, errors.Errorf("no user found with id[%s]", in.UserId)
        }
        return &dto.UserResponse{
            UserName:  "dubbo-user1",
            UserId:    "123456789",
            BirthDate: util.GetCommonTimeStr(time.Now().Add(-56 * 360 * 24 * time.Hour)),
            Age:       56,
            IsDead:    true,
        }, nil
    }
    if in.UserName == ""{
        return nil, errors.Errorf("please input query condition")
    }
    return &dto.UserResponse{
        UserName:  in.UserName,
        UserId:    "666666666",
        BirthDate: util.GetCommonTimeStr(time.Now().Add(-30 * 360 * 24 * time.Hour)),
        Age:       30,
        IsDead:    false,
    }, nil
}

4.2.2、util


func GetDubboContextAppName(ctx context.Context)(appName string){
    ctxMap, ok := ctx.Value(constant.DubboCtxKey("attachment")).(map[string]interface{})
    if !ok{
        return
    }
    if str, ok := ctxMap["app"]; ok{
        appName, _ = str.(string)
    }
    return
}

func GetCommonTimeStr(t time.Time) string{
    return t.Format("2006-01-02 15:04:05")
}

4.2.4、dubbo.yml

# dubbo server yaml configure file

dubbo:
  application:
    name: dubbogo-demo
    module: dubbogo
    version: 1.0.0
    owner: demo
  registries:
    demoZK:
      protocol: zookeeper
      timeout: 3s
      address: 192.168.96.129:2181
  protocols:
    dubbo:
      name: dubbo
      port: 20000
  provider:
    register: true
    registryIDs:
      - demoZK
    services:
      UserService:
        protocol: dubbo
        interface: com.demo.exp.service.UserService
        group: dubbo-service
        version: 1.0.0
        loadbalance: random
        warmup: 100
        cluster: failover
        methods:
          - name: QueryUser
            retries: 1
            loadbalance: random
  logger:
    zap-config:
      level: info

4.2.5、cmd

  • cmd.go
package cmd

import (
    "dubbo-demo/pkg/dto"
    "dubbo-demo/pkg/service"
    "dubbo.apache.org/dubbo-go/v3/config"
    _ "dubbo.apache.org/dubbo-go/v3/imports"

    hessian "github.com/apache/dubbo-go-hessian2"
)

func StartDubboServer(){
    config.SetProviderService(&service.UserService{})
    hessian.RegisterPOJO(&dto.UserRequest{})
    hessian.RegisterPOJO(&dto.UserResponse{})

    err := config.Load(config.WithPath("./conf/dubbo.yml"))
    if err != nil{
        panic(err)
    }
    select {
    }
}
  • main.go
package main

import (
    "dubbo-demo/cmd"
)

func main(){
    cmd.StartDubboServer()
}

4.3、go mod

如果import包有问题或者报错,按照如下操作试试

go mod tidy
go get dubbo.apache.org/dubbo-go/[email protected]
go mod tidy

五、运行测试

5.1、启动go项目

goland按照如下配置运行:

image.png

启动后,在dubbo admin可以看到服务已经注册:
image.png

详情页服务提供者可以看到运行种服务的ip和端口:


image.png

此时,消费者没有信息。

5.2、启动java项目

idea按照如下配置运行:

image.png

启动后,在dubbo admin服务详情页可以看到消费者信息:
image.png

5.3、调用测试

调用java项目的api接口,api会通过dubbo协议调用到go项目的服务。
浏览器打开地址: 127.0.0.1:7000/api/user/query
得到如下返回:

{
    "resultCode": 200,
    "message": "success",
    "data":
    {
        "userId": "666666666",
        "userName": "test",
        "birthDate": "1992-03-23 20:50:05",
        "age": 30,
        "dead": false
    }
}

修改代码,当有错误error时,返回如下:

{
    "resultCode": 500,
    "message": "no user found with id[666]"
}

六、项目代码

dubbogo example in github

你可能感兴趣的:(2021-10-17 dubbogo 基础使用)