1. 前言

1.1 说明

前面已经将三个服务注册到了Nacos服务端了。接下来就要继续改造三个服务的相互调用:验证码服务调用邮箱服务提供的发送邮件,用户服务调用验证码服务提供的校验服务。

原先是直接通过HTTP请求进行调用。而针对于分布式服务来说,HTTP调用相比而言就单薄了些。更多的是使用RPC来调用。因为良好的rpc调用是面向服务的封装,针对服务的可用性和效率等都做了优化。单纯使用http调用则缺少了这些特性。

本文就介绍下如何使用Dubbo来实现服务的远程调用。

1.2 什么是Dubbo

Dubbo是Alibaba开源的一个分布式服务框架,提供高性能和透明化的RPC远程服务调用方案,可以和Spring进行无缝集成。

在Dubbo中所有的的服务调用都是基于接口去进行双方交互的。提供者和消费者双方协定好Dubbo调用中的接口,提供者来提供实现类并且注册到注册中心上。

消费者则只需要引入该接口,并且注册到相同的注册中心上,即可利用注册中心来实现集群感知功能,之后消费者即可对提供者进行调用。

2. 改造邮箱服务

2.1 定义邮箱服务的dubbo服务接口

2.1.1 创建api接口模块

这个模块是用于规范双方接口协定。创建一个maven项目lagou-service-email-api

  • 不需要引入其他的依赖
  • 创建邮箱业务接口EmailService,提供一个发送邮件的接口方法
public interface EmailService {
    //发送邮件,发送成功返回true,失败返回false
    Boolean send(String email, String code);
}



2.2 改造邮箱服务模块

项目是 lagou-service-email

2.2.1 在pom.xml中引入依赖

包括了dubbo依赖和前面定义的api接口依赖



<dependency>
    <groupId>com.yyh</groupId>
    <artifactId>lagou-service-email-api</artifactId>
    <version>0.0.1</version>
</dependency>

<!--spring cloud+dubbo 依赖-->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-dubbo</artifactId>
</dependency>



2.2.2 新建邮箱业务实现类EmailServiceImpl

  • 实现EmailService接口
  • 实现EmailService接口的send方法
    (1)将EmailController中的发送邮件的逻辑拷贝到方法中。因为发送邮件的过程会比较慢,这里简单的另起了一个线程进行异步的调用
public class EmailServiceImpl implements EmailService {
    @Autowired
    private EmailConfig emailConfig;
    @Override
    public Boolean send(String email, String code) {
        return sendEmail(email, code);
    }
    private boolean sendEmail(String email, String code) {
        MailAccount account = new MailAccount();
        account.setHost(emailConfig.getHost());
        account.setPort(emailConfig.getPort());
        account.setFrom(emailConfig.getFrom());
        account.setUser(emailConfig.getUser());
        account.setPass(emailConfig.getPass());

        new Thread(() -> {
            System.out.println("async send email...");
            MailUtil.send(account, email, "账号激活邮件", "您的验证码是:" + code + "。有效期10分钟,请尽快输入验证", false);
        }).start();
        return true;
    }
}



  • 在实现类上标注上 @Service注解
    (1)注意:这个注解是dubbo提供的服务注解@org.apache.dubbo.config.annotation.Service,用于声明此java服务实现为dubbo服务
import org.apache.dubbo.config.annotation.Service;

@Service
public class EmailServiceImpl implements EmailService {}



2.2.4 去掉EmailController这个控制类

因为邮箱服务需要被验证码服务调用,接下来会使用rpc进行远程调用,那就不需要再提供http的请求方法了

2.2.5 在配置文件application.yml上增加dubbo的配置

Dubbo 远程服务需要暴露网络端口,并设定通讯协议



dubbo:
  scan:
    # dubbo 服务扫描基准包
    base-packages: com.yyh.email.service.impl
  protocol:
    # dubbo 协议
    name: dubbo
    # dubbo 协议端口( -1 表示自增端口,从 20880 开始)
    port: -1
    host: 127.0.0.1



2.3 查看改造后效果

2.3.1 重启邮箱服务项目

2.3.2 在nacos中的lagou-service-email的详情中的元数据信息可以看到此服务的注册信息




springcloud微服务之间的调用post请求 springcloud 微服务调用_发送邮件


3. 改造验证码服务

3.1 定义验证码服务的dubbo服务接口

3.1.1 创建api接口模块

创建一个maven项目lagou-service-code-api

  • 不需要引入其他的依赖
  • lagou-service-codeCodeService迁移过来,创建业务接口
public interface EmailService {
    //发送邮件,发送成功返回true,失败返回false
    Boolean send(String email, String code);
}


3.2 改造验证码服务模块

项目是 lagou-service-code

3.2.1 在pom.xml中引入依赖

包括了dubbo依赖和前面定义的api接口依赖,因为还要调用邮箱的发送邮件服务,所以还需要把lagou-service-email-api也引用过来


<dependency>
    <groupId>com.yyh</groupId>
    <artifactId>lagou-service-code-api</artifactId>
    <version>0.0.1</version>
</dependency>

<dependency>
    <groupId>com.yyh</groupId>
    <artifactId>lagou-service-email-api</artifactId>
    <version>0.0.1</version>
</dependency>

<!--spring cloud+dubbo 依赖-->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-dubbo</artifactId>
</dependency>


3.2.2 修改验证码业务实现类CodeServiceImpl

  • 在实现类上标注上dubbo的 @Service注解

3.2.3 修改控制类CodeController

  • 声明验证码业务接口CodeService和邮箱业务接口EmailService(1)注意:这里使用dubbo提供的引用服务注解**@Reference**
  • 修改创建验证码的请求方法
    (1)因为还要暴露给外部web进行http调用,所以保留这方面的配置
    (2)修改发送邮件的方法,去掉原先的http调用,使用dubbo远程调用
    (3)因为校验验证码的接口后面是要被用户服务进行远程调用,这里就不需要再保留这个请求方法
@RestController
@RequestMapping("codes")
public class CodeController {
    @Reference
    private CodeService codeService;
    @Reference
    private EmailService emailService;

    @GetMapping("create")
    public String create(@RequestParam String email) {
        //生成验证码并发送到对应的邮箱中
        //生成验证码
        String code = codeService.createCode(email);
        //发送验证码到邮箱中
        Boolean result = emailService.send(email, code);

        return result ? "ok" : "error";
    }
}


3.2.4 在配置文件application.yml上增加dubbo配置

包括了两部分:注册配置以及订阅邮箱服务的配置


dubbo:
  scan:
    # dubbo 服务扫描基准包
    base-packages: com.yyh.code.service.impl
  protocol:
    # dubbo 协议
    name: dubbo
    # dubbo 协议端口( -1 表示自增端口,从 20880 开始)
    port: -1
    host: 127.0.0.1
  cloud:
    # 订阅服务提供方的应用列表,订阅多个服务提供者使用 "," 连接
    subscribed-services: lagou-service-email


3.3 查看改造后效果

3.3.1 重启验证码服务项目(邮箱服务也开启)

3.3.2 测试创建验证码方法


curl http://www.test.com/codes/create?email=yaohuiye@126.com


4. 改造用户服务

用户服务是服务提供方,需要调用验证码的校验功能

4.1 在pom.xml中引入依赖

包括了dubbo依赖,因为要调用验证码服务的的校验接口,所以还需要把lagou-service-code-api也引用过来


<dependency>
    <groupId>com.yyh</groupId>
    <artifactId>lagou-service-code-api</artifactId>
    <version>0.0.1</version>
</dependency>

<!--spring cloud+dubbo 依赖-->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-dubbo</artifactId>
</dependency>


4.2 修改控制类UserController

  • 声明验证码业务接口CodeService,使用**@Reference**注解标识
  • 修改注册请求方法中的验证码校验,去掉原先的http调用,使用dubbo远程调用
@Reference
private CodeService codeService;
@PostMapping("register")
public String register(@RequestParam String email,
                    @RequestParam String password, @RequestParam String code) {
    //校验验证码
    Integer checkCodeResult = codeService.checkCode(email, code);

    if(null != checkCodeResult && checkCodeResult > 0) {
        return "error";
    }

    userService.add(email, password);
    return "ok";
}


4.3 在配置文件application.yml上增加dubbo的配置

包括了订阅验证码服务的配置


dubbo:
  cloud:
    # 订阅服务提供⽅的应⽤列表,订阅多个服务提供者使⽤ "," 连接
    subscribed-services: lagou-service-code


4.4 重启用户服务项目(邮箱服务、验证码服务也开启)

4.5 访问静态页面,测试完整的注册、登录流程