vdp-cloud readme

一 背景

我们希望针对"数据采集,处理,寄存,存储"的应用场景,设计一个数据灵活处理,存储和通信的框架。
我们将需求分解成了不同服务,使用者只要调用相应方法即可,服务和底层实现组件松散组合,可以根据需要进行调整和扩展。

二 简介

采用springboot+springcloud构筑的微服务分布式架构。可以方便的实现服务的注册和发现。使用者只需要通过简单的配置开启不同的服务即可(如何使用后面有介绍),设计的服务

  • 归档archive:
    将采集后的元素数据和解析后的数据备份到指定的服务器中,后续可以进行分析和计算.
  • 存储storage(未完成) :

  • 消息队列msgqueue:
    定义发生和接收的通用方法, 在配置文件中配置本服务节点需要的用到的队列, 在服务启动时初始化队列,在发生放和接收方指定相应的队列进行发生和接收操作.

  • 寄存memory:
    一个通用的寄存服务,对一些通用的缓存技术进行了封装,如redis和memcache. 封装了通用的存和取的方法.
  • 单点登陆sso(目前未支持)

可以灵活开启或关闭上述服务,不开启则不进行连接和bean的初始化。各个服务可以通过配置的方式灵活选择不同的组件来实现,服务和组件采用策略设计模式实现,各个服务可以根据需要灵活扩展和调整组件。
服务和支持的组件如下(包括计划支持的服务和组件)

  • 归档archive:mongodb,elasticsearch(计划支持)
  • 存储storage:mysql
  • 消息队列msgqueue:rabbitmq,kafka(计划支持),rocket(计划支持)
  • 寄存memory:redis
  • 单点登陆sso(计划支持):spring security集成auth2(计划支持)

    服务和支持的组件是一对一的关系,如归档archive服务,支持的基础组件为mongodb,elasticsearch,只能选择一种基础组件来实现. 即我们配置mongodb组件后,归档服务底层实现是由mongodb的api实现,且数据会归档到mongodb中.

系统架构图

输入图片说明
1441495-20180813165629503-1026562138.png
我们通过在vdp-cloud创建一个module 模块,依赖core包,就可以变成上图Business Node中的一server node,具有服务注册和发现功能,且可以调用归档(archive),消息队列(msgqueue),寄存(Memory)等服务。

三 涉及的技术

3.1 项目构建:

spring boot:通过spring boot快速项目构建

3.2 微服务架构:spring cloud:

注册中心:eureka1.x

eureka2.0被闭源,如果spring放弃eureka,那么可以选用zookeeper或者
console,到时候再支持。

配置中心:spring config

官方推荐git来管理配置,现在只支持本地文件系统,如果要修改成git,修改下配置即可。

如果需要更进一步扩展后期可能会支持携程的apollo。

负载均衡:ribbon

springcould之间服务调用的负载均衡

api网关:zuul

本项目节点外的第三方调用本项目服务节点暴露的api时, 通过zuul进行代理. 如web平台调用XXX项目查询归档的历史数据, 那么不是直接访问里面的XXX服务节点去请求数据,而是只访问zuul,由zuul代理访问XXX服务节点
配置示例:

zuul:
  routes:
  #### common routes, default support LoadBalancer
    vdp-cloud-sc: /sc/**
    vdp-cloud-vlr: /vlr/**
    vdp-cloud-dqs: /dqs/**

访问:
http://localhost:20001/vlr/vlr/device-authentication/a1234567890123456
返回:

{
    "msg": "OK",
    "data": "a1234567890123456",
    "debug": null,
    "status": 200,
    "ok": true
}
服务调用:feign

3.3 依赖管理

maven

3.4 nosql支持:

redis:寄存服务使用的组件,目前只支持集群模式(cluster)
mongodb:归档服务使用的组件,支持单机模式和复制集模式

3.5 队列技术:

生产者需要创建的队列, 和消费者需要监听的队列, 都通过在application.yaml配置文件中进行配置.
支持队列组件有:

  • rabbitmq:消息队列服务使用的组件,支持集单机模式,计划支持集群模式.
    需要在生产者和消费者中的application.yaml中相同的队列, 在加载的时候会自动进行初始化:
    queueNames:
      dataUpdateQ: topic.scdata.sc.vlr
      eventCalculateQ: topic.rtinfo.sc.event

格式为:"exchange类型.数据类型.生产者.消费者", "数据类型"作为exchange, "生产者.消费者"作为routeKey, 整个作为queue名称.
消费者通过指定queueNames下的key就能够实现监听指定的队列, 使用方式参考test项目下的MqController.java

3.6 日志处理:

log4j/logslf/logback: 日志收集, 采用lombok框架在类中简化创建log收集器:

@Slf4j
public class VdpExceptionHandler {
    //相当于
    //Logger log = LoggerFactory.getLogger(VdpExceptionHandler.class);
    …
    public void test(){
      log.error("发生异常!!!", e);
    }
}

@Slf4j相当于在类中创建了类成员Logger log = LoggerFactory.getLogger(VdpExceptionHandler.class);

3.7 持久层框架(orm):

mybaits:通过mybaits-plus简化curd操作。通过mybaits-generate将数据库表生成实体类

3.8 数据源:

druid:实现数据源监控功能
监控用户名和密码在application.yaml中进行配置

      monitor:
        urlSuffix: /druid/*    #访问的url地址后缀, 例如http://localhost:8080/druid/
        username: admin
        password: 123

3.9 项目调试:

swagger
swagger会管理所有包含@ApiOperation注解的控制器方法,同时,可利用@ApiImplicitParams注解标记接口中的参数,具体用法请参考UserController类中的用法。
通过application.yaml配置来实现swagger的开启和关闭

swagger:
  open: true            #开启/关闭swagger,开启--true,关闭--false
  protocol: http          #协议,http或https
  base-package: com.vdp.vlr.modules.controller  #一定要写对,会在这个路径下扫描controller定义
  title: 寄存服务(VLR)开发api
  version: 1.0
  description: vdp-cloud项目RESTful API

四 项目结构:

4.1 项目结构:

vdp-cloud: 父类, 用于springcloud和springboot的版本管控, maven插件, 仓库统一管控等.
|--vdp-cloud-common: 常用组件和工具类
|--vdp-cloud-core:依赖vdp-cloud-common项目
|--vdp-cloud-base-config-server: 微服务配置中心
|--vdp-cloud-base-discovery-eureka: 微服务注册中心
|--vdp-cloud-base-gateway-zuul: 微服务api网关
|--vdp-cloud-base-monitor-admin: 微服务节点监控项目
|--vdp-cloud-test:测试项目,用于测试框架的各个功能. 依赖vdp-cloud-core项目(也间接依赖了comon项目)

4.2 包结构:

  • vdp-common项目:
    com.vdp.common
    |--swagger: swagger的配置
    |--utils: 常用的工具类
    |--web: web开发需要的组件,如web异常处理,返回值的pojo等
  • vdp-cloud-core项目:
    com.vdp.core
    |--common: 通用工具类
    |--component: 用于实现服务的基本组件,如druid,mongo,rabbitmq,redis等
    |--container: 加载和容器的基本配置参数, 参考vdp-cloud-test项目application.yaml中的containerconfig配置
    |--data: 容器需要使用到的annotation,entity,const等
    |--service: 设计的服务, 有归档服务,消息队列服务等,请参考简介部分的设计的服务

新建一个项目时需要依赖core项目,具体参考test项目的pom.xml配置

五 Restful 接口设计

5.1 实体类设计

添加JSR注解实现参数检验, 通过JSR303进行校验
通过Lombok注解, 编译时自动添加Setter、Getter、toString()、equals()和hashCode()。

package com.vdp.sc.testCurd.testParamValid;

import lombok.Data;

import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.Size;


/**
* @ClassName Student
* @Description 实体类: 1.参数检验, 通过JSR303进行校验
*                    2.通过Lombok注解, 编译时自动添加Setter、Getter、toString()、equals()和hashCode()。
* @Author longxn
* @Date 2018/7/9 20:14
*/
@Data
public class Student {
    String id;

    @Size(min = 3, max = 5, message = "姓名长度为3到5之间")
    String name;

    @Min(value=0)
    @Max(value=150)
    Integer age;
}

5.2 请求

在Spring MVC 中,Restful API的定义对应为Controller层。根据Restful的接口定义规范:

GET(SELECT):从服务器取出资源(一项或多项)。
POST(CREATE):在服务器新建一个资源。
PUT(UPDATE):在服务器更新资源(客户端提供改变后的完整资源)。
PATCH(UPDATE):在服务器更新资源(客户端提供改变的属性)。
DELETE(DELETE):从服务器删除资源。

我们设计接口如下所示,详见():

//UserController.java
package com.vdp.sc.testCurd;

import com.mystudy.spring.domain.User;
import com.mystudy.spring.service.UserService;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/api/user")
public class UserController
{
    @Autowired
    private UserService userService;

    @ApiOperation(value="获取用户列表", notes="获取用户列表")
    @GetMapping(value = "/users")
    @ResponseStatus(HttpStatus.OK)
    public List<User> getUserList()
    {
        return userService.getUserList();
    }

    @ApiOperation(value="添加用户", notes="添加用户")
    @PostMapping(value = "/users")
    @ResponseStatus(HttpStatus.CREATED)
    public Object addUser(@RequestBody User user){
        return userService.addUser(user);
    }

    @ApiOperation(value="获取用户信息", notes="根据id获取用户信息")
    @GetMapping(value = "/users/{id}")
    @ResponseStatus(HttpStatus.OK)
    public Object getUser(@PathVariable("id") String id) throws NotFoundException
    {
        return userService.getUser(id);
    }

    @ApiOperation(value="删除用户", notes="根据id删除用户")
    @DeleteMapping(value = "/users/{id}")
    @ResponseStatus(HttpStatus.NO_CONTENT)
    public void deleteUser(@PathVariable("id") String id)
    {
        userService.deleteUser(id);
    }

    @ApiOperation(value="更新用户", notes="更新用户")
    @PatchMapping(value = "/users/{id}")
    @ResponseStatus(HttpStatus.CREATED)
    public User updateUser(@PathVariable("id") String id, @RequestBody User user)
    {
        return userService.update(id, user);
    }


    @ApiOperation(value="测试")
    @GetMapping(value = "/test")
    @ResponseStatus(HttpStatus.OK)
    public String test()
    {
        return "test ok!";
    }
}

在这些接口上,我们使用了如下注解:

  • @GetMapping 对应get请求
  • @PostMapping 对应post请求
  • @DeleteMapping 对应delete
  • @PutMapping 对应put和patch请求

    注意url和方法名的命名规则, url中不准出现get, update等

5.3 响应

5.3.1 正常响应

直接返回请求的数据
根据请求的类型需要设置相应的ResponseStatus进行相应,对应关系如下:

@GetMapping: @ResponseStatus(HttpStatus.OK)  //200
@PostMapping: @ResponseStatus(HttpStatus.CREATED)  //201
@DeleteMapping: @ResponseStatus(HttpStatus.NO_CONTENT) //204
@PatchMapping: @ResponseStatus(HttpStatus.CREATED)  //201
@PutMapping: @ResponseStatus(HttpStatus.CREATED)  //201
5.3.2 异常响应

发生异常会由VdpExceptionHandler.java进行拦截处理
异常产生和匹配规则如下:

  • 认证异常* :
    异常类: AuthenticationException.java
    HttpStatus: 401
    JSON中自定义status: 401
    备注: 在身份认证过程中判断token失效或者过期时手动抛出该异常
  • 参数校验异常* :
    异常类: IllegalArgumentException.java
    HttpStatus: 500
    JSON中自定义status: 501
    备注: 在校验参数失败时抛出该异常,如果是手动判断不满足条件,则需要手动抛出异常
  • JSR参数校验异常* :
    备注: MethodArgumentNotValidException.java
    HttpStatus: 500
    JSON中自定义status: 501
    备注: 在请求或者springboot中的配置文件开启JSR校验(参考5.4 参数校验)时, 若校验不通过则自动产生该异常
  • 业务异常* :
    备注: ServiceException.java
    HttpStatus: 500
    JSON中自定义status: 555
    备注: 如果业务逻辑或者数据异常, 则手动抛出该异常
  • 其他异常* :
    异常类: Exception.java
    HttpStatus: 500
    JSON中自定义status: 500
    备注: 如果上述异常都没匹配上匹配该异常

5.4 参数校验

5.4.1 controller的请求参数进行JSR303校验
//CheckParamController
package com.vdp.sc.testCurd.testParamValid;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.validation.constraints.Min;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

/**
* @ClassName CheckParamController
* @Description 对@RequestParam和@PathVariable的校验需要添加@Validated到类上
* @Author longxn
* @Date 2018/7/9 20:25
*/
@RestController
@Validated
public class CheckParamController {

    // http://localhost:8080/checkParamTest?name=1&age=-1
    // 提示: msg": "checkParamTest.age: age必须大于0"
    @GetMapping("checkParamTest")
    public void checkParamTest(@RequestParam @Min(value = 2,message = "age必须大于0") Integer age){
        System.out.println(age + ",.,.");
    }

    //加@Validated对具体实体类检验,需要在实体类加相应的注解,如@Size等
    // http://localhost:8080/checkParamTestPost
    // 提示: msg": "姓名长度为3到5之间"
    // 参数:
    // {
    //  "name":"1",
    //  "age":1
    // }
    @PostMapping("checkParamTestPost")
    public void checkParamTestPost(@RequestBody @Validated Student student){
        System.out.println(student);
    }


    // http://localhost:8080/checkParamTestPath/aa
    // msg": "checkParamTestPath.name: 名字长度在3到5之间"
    @GetMapping("checkParamTestPath/{name}")
    public void checkParamTestPath(@NotNull @NotBlank @Size(min=3,max=5, message = "名字长度在3到5之间")@PathVariable String name){
        System.out.println(name);
    }
}
5.4.2 手动参数校验

采用Spring的Assert进行校验

//第一个参数为false则抛出IllegalArgumentException异常
Assert.isTrue(concurrentConsumers > 0, "'concurrentConsumers' value must be at least 1 (one)");
Assert.isTrue(!this.exclusive || concurrentConsumers == 1,"When the consumer is exclusive, the concurrency must be 1");

复杂校验通过Optional

ZOrder order = this.getOrderByOrderNum(orderNum);
Optional.ofNullable(order).filter(o -> {
    return null != o && (0 == o.getStatus() || 3 == o.getStatus() || 9 == o.getStatus());
}).orElseThrow(() -> new ParamException("获取数据异常,订单号有误或者订单状态异常!"));

简单的一些条件判断可以使用Objects, 和common3的StringUtils

日期处理
文件上传处理

5.5 service设计(待完成)

5.6 dao设计(待完成)

  • mybatis-plus(mybaits-generate)
  • spring data,hibernate, ORM,实现JPA规范

6 开发步骤

6.1 新建一个maven项目,作为vdp-cloud父项目中的子项目,添加vdp-cloud-core依赖进pom, 添加spring-boot-starter-web依赖, 否则在启动项目报错时在console无法打印错误信息

        <parent>
        <groupId>com.vdp-cloud</groupId>
        <artifactId>vdp-cloud</artifactId>
        <version>1.0.0-SNAPSHOT</version>
    </parent>
    <dependencies>
        <dependency>
            <groupId>com.vdp-cloud</groupId>
            <artifactId>vdp-cloud-core</artifactId>
            <version>${vdp.cloud.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

6.2 在application.yaml配置服务

###### 容器功能相关配置 #################
# 第一级key不要用驼峰格式, 会导致一直无法读取到配置!!!!!
#    enabled: 根据需要配置成true还是false. 配置成false时,不会创建bean, 也不会去连接对应的mysql,mongodb等服务器
#    component: 选择一种在support中已经被支持的组件, 采用的enum类,在enum类中可以查询到支持的component
containerconfig:
  msgqueue:
    enabled: false
    component: rabbitmq
  memory:
    enabled: false #
    component: redis
  storage:
    enabled: true
    component: mysql
  archive:
    enabled: true
    component: mongodb
    ThreadNum: 2
    QueueCap: 200000

6.3 修改bootstrap.yml里面的配置

  • 注册服务,实例名等

6.4 修改其他一些服务的ip地址

如修改mongodb, mysql, redis, rabbitmq等对应的ip地址, 端口和密码

6.5 如果要用lombok,需要在IDE中安装lombok插件

转载于:https://www.cnblogs.com/lognxn/p/9469330.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值