在分布式微服务框架中,比较重要的就是远程方法调用了,阿里巴巴推出的Nacos+Dubbo框架是一种很不错的解决方案,其中Nacos不但可以作为注册中心,还可以作为配置中心,并且Dubbo也内置了几种很不错的负载均衡算法,这二者的组合可以取得不错的效果,目前也是一种主流的分布式微服务中间件。
我之前就写过一篇类似的文章,方法和过程都差不多,感兴趣的话可以瞅一眼,Nacos实现服务注册与消费(传送门)。现在重新整理一下,以供参考。
本文完整代码可见:https://github.com/BraisedPanda/xiqing-study-project.git
Nacos安装与启动直接去看官方文档就行,那里有最新的Nacos安装包,Nacos官方文档
安装完运行后,输入http://ip地址:8848/nacos/#/login,就可以进入登录界面了,用户名和密码默认都是nacos
这是登录后的页面,常用的界面就是配置中心以及注册中心了。
首先第一步当然是添加相关的依赖了,网上添加Nacos和Dubbo的依赖多种多样,这里提供一下我依赖的maven配置,这里需要注意下nacos和dubbo的对于版本,版本不对可能会造成项目的启动失败。
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-starter-alibaba-nacos-configartifactId>
<version>2.2.5.RELEASEversion>
dependency>
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
<version>2.2.5.RELEASEversion>
dependency>
<dependency>
<groupId>org.apache.dubbogroupId>
<artifactId>dubbo-spring-boot-starterartifactId>
<version>3.0.2.1version>
dependency>
<dependency>
<groupId>org.apache.dubbogroupId>
<artifactId>dubboartifactId>
<version>3.0.2.1version>
dependency>
<dependency>
<groupId>org.apache.dubbogroupId>
<artifactId>dubbo-registry-nacosartifactId>
<version>3.0.2.1version>
dependency>
接下来就是编写配置文件,注明Nacos和Dubbo的地址、命名空间和应用名称等信息,这里有个坑,建议把这些配置写入bootstrap.yaml文件中,否则可能会造成服务无法注册在正确的地址上。这个坑可以看我之前记录的文章,Nacos配置了远程地址,项目启动时却一直连接本地问题解决方法
微服务中一般分为服务消费者与服务提供者,通常来讲,服务消费者一般是请求的入口,集成了大量的controller,请求通过controller调用服务提供者提供的service接口,请求数据。因此,服务提供者与服务消费者的配置文件也稍微不同(不同之处主要在于消费者需要配置提供者的服务名称)。
bootstrao.yaml文件内容
spring:
application:
# 服务提供者的名称
name: xiqing-study-project-user-provider
cloud:
nacos:
discovery:
# 启动Nacos的地址
server-addr: 47.100.160.xx:8848
# 在Nacos页面建的命名空间
namespace: 56d98d62-6bbf-46d8-8e2a-f52c49c4798d
config:
server-addr: ${spring.cloud.nacos.discovery.server-addr}
group: provider
namespace: ${spring.cloud.nacos.discovery.namespace}
file-extension: yaml
server:
port: 8000
mybatis:
mapper-locations:
classpath: /mapper/*.xml
application.properties文件内容
dubbo.scan.base-packages=com.xiqing.study.project.user.service
dubbo.protocol.name=dubbo
dubbo.protocol.port=-1
dubbo.registry.address=nacos://47.100.160.xx:8848
dubbo.provider.loadbalance=leastactive
#dubbo.provider.actives=8
#dubbo.provider.executes=8
dubbo.provider.dispatcher=message
dubbo.provider.threadpool=cached
dubbo.provider.timeout=60000
dubbo.provider.delay=-1
dubbo.application.dump-directory=/tmp
mapper.before=true
mybatis.mapper-locations=classpath*:/mapper/**Mapper.xml
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
bootstrao.yaml文件内容
spring:
application:
# 服务消费者的名称
name: xiqing-study-project-web
cloud:
nacos:
discovery:
server-addr: 47.100.160.xx:8848
namespace: 56d98d62-6bbf-46d8-8e2a-f52c49c4798d
config:
server-addr: ${spring.cloud.nacos.discovery.server-addr}
group: consumer
namespace: ${spring.cloud.nacos.discovery.namespace}
file-extension: yaml
server:
port: 8080
mybatis:
mapper-locations:
classpath: /mapper/*.xml
application.properties文件内容
# 服务消费者订阅服务提供者的名称,多个用逗号隔开
dubbo.cloud.subscribed-services=xiqing-study-project-user-provider
dubbo.registry.address=nacos://47.100.160.xx:8848
dubbo.consumer.check=false
dubbo.registry.check=false
dubbo.consumer.actives=20
mapper.before=true
mybatis.mapper-locations=classpath*:/mapper/**Mapper.xml
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
其实这个代码就是平常写的代码,唯一有区别的就是在service类的注解使用
@DubboService(version = “1.0”) (替换之前的service注解@service)
,版本号是自定义的,可不加,controller类的注解使用
@DubboReference(version = “1.0”) (替换之前其他类的注解@Autowired)
这样就可以和调用本地方法一样,调用远程的服务。
package com.xiqing.study.project.user.service;
import com.xiqing.project.redis.RedisUtil;
import com.xiqing.study.project.base.model.DataResponseBean;
import com.xiqing.study.project.domain.po.People;
import com.xiqing.study.project.domain.po.PeopleExample;
import com.xiqing.study.project.user.mapper.PeopleMapper;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.List;
@DubboService(version = "1.0")
public class PeopleServiceImpl implements PeopleService{
@Autowired
private PeopleMapper peopleMapper;
@Autowired
private RedisUtil redisUtil;
@Override
public DataResponseBean<List<People>> selectAll() {
PeopleExample peopleExample = new PeopleExample();
List<People> list = peopleMapper.selectByExample(peopleExample);
return DataResponseBean.SUCCESS(list);
}
@Override
public DataResponseBean<People> selectById(Integer id) {
People people = (People) redisUtil.get(id.toString());
if(people == null){
people = peopleMapper.selectByPrimaryKey(id);
redisUtil.set(id.toString(), people);
}
return DataResponseBean.SUCCESS(people);
}
}
package com.xiqing.study.project.web.controller;
import com.xiqing.study.project.base.model.DataResponseBean;
import com.xiqing.study.project.domain.po.People;
import com.xiqing.study.project.user.service.PeopleService;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
@RequestMapping("/user")
public class UserController {
@DubboReference(version = "1.0")
private PeopleService peopleService;
@RequestMapping("/test")
public DataResponseBean<List<People>> test(){
return peopleService.selectAll();
}
@GetMapping("/{id}")
public DataResponseBean<People> selectById(@PathVariable Integer id){
return peopleService.selectById(id);
}
}
依次启动服务提供者与消费者,可以在Nacos页面中看到,这两个服务已经注册上去了。
使用postman测试,可以发现服务可以正常调用。