Dubbo 微服务入门(一)

API网关 Gateway

  • 类似于设计模式中的Facade模式
  • 微服务系统中的正门
  • 微服务的重要组成部分

常见作用

  • 身份验证和安全 JSON Web Token(JWT)
  • 审查和检测
  • 动态路由
  • 压力测试
  • 负载均衡
  • 静态相应处理

业务总结

必须先启动服务提供者,否则会报错
启动检查:服务启动过程中验证服务提供者的可用性,如果验证出现问题,则阻止整个spring容器的初始化,还有个好处就是服务启动检查可以尽可能早的发现服务问题

check = false

如果我们将用户模块部署多台,消费者会如何访问
Dubbo负载均衡
在这里插入图片描述

Protocol
Dubbo支持多协议
最常见dubbo
RMI、Hessian、Http、Redis、Memerycached

在这里插入图片描述
网关gateway逻辑处理

外部服务请求的入口
1、使用ThreadLocal进行用户的id存储,配合jwt进行用户校验

public class CurrentUser {

    // 线程绑定的存储空间
    private static final ThreadLocal<String> threadlocal = new ThreadLocal<>();
    // 将用户信息放入存储空间
    public static void saveUserId(String userId) {
        threadlocal.set(userId);
    }

    // 将用户信息取出
    public static String getCurrentUserId() {
        return threadlocal.get();
    }

    /*   考虑到jvm内存大小 存储对象过多 使用存储id   */
//    public static void saveUserInfo(UserInfoModel userInfoModel) {
//        threadlocal.set(userInfoModel);
//    }
    // 将用户信息取出
//    public static UserInfoModel getCurrentUser() {
//        return threadlocal.get();
//    }
}

@RequestMapping(value = "${jwt.auth-path}")
    public ResponseVO createAuthenticationToken(AuthRequest authRequest) {

        boolean validate = true;
        // 去掉guns自带用户名密码验证,使用自己的
        int userId = userAPI.login(authRequest.getUserName(), authRequest.getPassword());
        if (userId == 0) {
            validate = false;
        }

        if (validate) {
            // randomKey  token 生成完毕
            final String randomKey = jwtTokenUtil.getRandomKey();
            final String token = jwtTokenUtil.generateToken(""+userId, randomKey);
            //
            return ResponseVO.success(new AuthResponse(token, randomKey));
        } else {
            return ResponseVO.serviceFail("用户名或密码错误");
        }
    }

// JWT 处理
final String requestHeader = request.getHeader(jwtProperties.getHeader());
        String authToken = null;
        if (requestHeader != null && requestHeader.startsWith("Bearer ")) {
            authToken = requestHeader.substring(7);

            // 通过token获取userId 并且存入threadlocal 以便后续业务使用
            String userId = jwtTokenUtil.getUsernameFromToken(authToken);
            if (userId == null) {
                return;
            } else {
                CurrentUser.saveUserId(userId);
            }

2、忽略路径的配置

rest:
  auth-open: true #jwt鉴权机制是否开启(true或者false)
  sign-open: true #签名机制是否开启(true或false)

jwt:
  header: Authorization   #http请求头所需要的字段
  secret: mySecret        #jwt秘钥
  expiration: 604800      #7天 单位:秒
  auth-path: auth         #认证请求的路径
  md5-key: randomKey      #md5加密混淆key
  ignore-url: /user/register,/user/check # 忽略列表

private String ignoreUrl = "";

    public String getIgnoreUrl() {
        return ignoreUrl;
    }

    public void setIgnoreUrl(String ignoreUrl) {
        this.ignoreUrl = ignoreUrl;
    }

// 配置忽略列表
        String ignoreUrl = jwtProperties.getIgnoreUrl();
        String[] ignoreUrls = ignoreUrl.split(",");
        for (int i = 0; i < ignoreUrls.length; i++) {
            if (request.getServletPath().equals(ignoreUrls[i])) {
                chain.doFilter(request, response);
                return;
            }
        }

3、dubbo配置

spring:
  application:
    name: meeting-gateway
  dubbo:
    server: true
    registry: zookeeper://localhost:2181
    protocol:
      name: dubbo # 协议名称
      port: 20880 # 端口号
  datasource:
      url: jdbc:mysql://127.0.0.1:3306/guns_rest?autoReconnect=true&useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&useSSL=false
      username: root
      password: root
      filters: log4j,wall,mergeStat

4、pom文件

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>com.alibaba.spring.boot</groupId>
            <artifactId>dubbo-spring-boot-starter</artifactId>
            <version>2.0.0</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
        </dependency>
        <dependency>
            <groupId>com.stylefeng</groupId>
            <artifactId>guns-core</artifactId>
        </dependency>
        <dependency>
            <groupId>com.stylefeng</groupId>
            <artifactId>guns-api</artifactId>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>

        <dependency>
            <groupId>com.101tec</groupId>
            <artifactId>zkclient</artifactId>
            <version>0.10</version>
        </dependency>

注:期间遇到引入dubbo-spring-boot-starter提示某个包找不到,解决办法是找到maven仓库中的包删掉,然后project中maven clean 重新install

5、公用接口请求返回类 封装

package com.stylefeng.guns.rest.modular.vo;

public class ResponseVO<M> {

    // 状态 【0-成功 1-失败 999-系统异常】
    private int status;
    // 返回信息
    private String msg;
    // 实体
    private M data;

    // 不允许外部创建实体 单例
    private ResponseVO() {}

    public static<M> ResponseVO success(M m) {
        ResponseVO responseVO = new ResponseVO();
        responseVO.setStatus(0);
        responseVO.setData(m);

        return responseVO;
    }

    public static<M> ResponseVO success(String msg) {
        ResponseVO responseVO = new ResponseVO();
        responseVO.setStatus(0);
        responseVO.setMsg(msg);

        return responseVO;
    }

    public static<M> ResponseVO serviceFail(String msg) {
        ResponseVO responseVO = new ResponseVO();
        responseVO.setStatus(1);
        responseVO.setMsg(msg);

        return responseVO;
    }

    public static<M> ResponseVO appFail(String msg) {
        ResponseVO responseVO = new ResponseVO();
        responseVO.setStatus(999);
        responseVO.setMsg(msg);

        return responseVO;
    }

    public int getStatus() {
        return status;
    }

    public void setStatus(int status) {
        this.status = status;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public M getData() {
        return data;
    }

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

6、API模块抽离
7、User模块实现
copy guns-rest 服务模块 修改pom文件,修改project structure 删除多余引用,修改pom配置,application.properties,api对应的UserAPi实现类处理
8、理解 gateway api user 模块的调用原理,其实就是api作为公用模块,修改之前做的直接提供者,采用zookeeper注册中心,user模块实现api接口,gateway通过调用api模块接口,注册中心监测到user中有对应的实现,直接执行userApiImpl中的实现方法

坑:
1、遇到java.util.Date 数据库写入问题,替换java.sql.Date后得到解决,倒是数据库时分秒全为0,后续排查
2、mysql链接不起 jdbc:mysql://127.0.0.1:3306/guns_rest?autoReconnect=true&useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&useSSL=false,使用serverTimezone=GMT%2B8 确定时区
3、接口名 使用 value = “register”
4、服务检查:@Reference(interfaceClass = UserAPI.class, check = false)
5、service负载均衡 @Service(interfaceClass = UserAPI.class, loadbalance = “roundrobin”)

项目地址

发布了83 篇原创文章 · 获赞 12 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_38885024/article/details/94839266