前提
最近创业公司的项目组基于业务需要,开发一套新的微服务,考虑到选用的组件必须是主流、社区活跃、生态完善以及方便迁移到云上等因素,引入了SOFAStack
全家桶。微服务开发里面,一个很重要的功能就是服务发现与注册,笔者花了点时间做了一个SOFABoot
、SOFARpc
结合Nacos
实现微服务发现注册与远程调用的示例。

依赖版本踩坑
笔者花了点时间去尝试SOFABoot
、SOFARpc
结合Nacos
客户端的依赖版本关系,截止本文编写完成的时候(2020-01-01),sofaboot-dependencies
的最新版本为3.2.1
,对应于SOFABoot-3.2.1
、SOFARpc-5.6.3
和SpringBoot-2.1.x.RELEASE
。在这两个最新版本的项目中,无论引入什么版本的nacos-clinet
,都没有办法向Nacos-Server
注册服务信息。关于这一点,笔者曾经从Issues
里面查找相关的内容,暂时无果,于是把示例项目分享给社区的大佬进行分析,如果有解决方案,会在这篇博文中更新。试出来的可用的版本组合为:
sofaboot-dependencies:3.2.0
spring-boot-dependencies:2.1.0.RELEASE
nacos-api:0.6.0
和nacos-client:0.6.0
引入依赖如下:
<properties> <sofa.boot.version>3.2.0</sofa.boot.version> <spring.boot.version>2.1.0.RELEASE</spring.boot.version> <nacos.version>0.6.0</nacos.version> </properties> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>${spring.boot.version}</version> <scope>import</scope> <type>pom</type> </dependency> <dependency> <groupId>com.alipay.sofa</groupId> <artifactId>sofaboot-dependencies</artifactId> <version>${sofa.boot.version}</version> <scope>import</scope> <type>pom</type> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>com.alipay.sofa</groupId> <artifactId>healthcheck-sofa-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>com.alipay.sofa</groupId> <artifactId>rpc-sofa-boot-starter</artifactId> </dependency> <dependency> <groupId>com.alibaba.nacos</groupId> <artifactId>nacos-client</artifactId> <version>${nacos.version}</version> </dependency> <dependency> <groupId>com.alibaba.nacos</groupId> <artifactId>nacos-api</artifactId> <version>${nacos.version}</version> </dependency> </dependencies>
|
编写服务提供方和服务消费方代码
这里有一个前提,需要启动一个Nacos-Server
,为了方便起见,使用单机模式本地启动即可,那么服务注册的地址就是http://127.0.0.1:8848
。示例项目的结构如下:
├─src │ └─main │ ├─java │ │ └─club │ │ └─throwable │ │ ├─client │ │ │ ClientApplication.java │ │ │ │ │ ├─contract │ │ │ HelloService.java │ │ │ │ │ └─server │ │ DefaultHelloService.java │ │ ServerApplication.java │ │ │ └─resources │ application-client.properties │ application-server.properties
|
其中contract
为契约包,可以提供给客户端和服务端使用,client
包里面编写客户端(comsumer
)的代码,而server
包里面编写服务端(provider
)的代码。
契约接口HelloService
很简单:
public interface HelloService {
String sayHello(String name); }
|
服务提供方需要实现此接口,实现类是DefaultHelloService
:
@Service @SofaService(interfaceType = HelloService.class, bindings = { @SofaServiceBinding(bindingType = "bolt") }) public class DefaultHelloService implements HelloService {
@Override public String sayHello(String name) { return String.format("%s say hello!", name); } }
|
这里使用的服务协议绑定类型为bolt
,是官方示例建议的协议,当然还有dubbo
、http
等等,可以混合配置。接着编写服务提供方启动类ServerApplication
:
@SpringBootApplication(scanBasePackages = {"club.throwable.server", "club.throwable.contract"}) public class ServerApplication {
public static void main(String[] args) { SpringApplication.run(ServerApplication.class, args); } }
|
服务提供方应用的配置文件application-server.properties
如下:
spring.application.name=sofa-rpc-provider server.port=9092
com.alipay.sofa.rpc.registry-address=nacos://127.0.0.1:8848
|
使用spring.profiles.active=server
启动ServerApplication
,启动成功后用浏览器打开Nacos-Console
:

可见目前sofa-rpc-provider
服务已经成功注册到Nacos-Server
。接着编写客户端代码,为了方便起见,所有的代码编写在启动类ClientApplication
:
@Slf4j @SpringBootApplication(scanBasePackages = {"club.throwable.client", "club.throwable.contract"}) public class ClientApplication implements CommandLineRunner {
@SofaReference(binding = @SofaReferenceBinding(bindingType = "bolt")) private HelloService helloService;
public static void main(String[] args) { SpringApplication.run(ClientApplication.class, args); }
@Override public void run(String... args) throws Exception { log.info("调用HelloService#sayHello(),结果:{}", helloService.sayHello("throwable")); } }
|
服务消费方的配置文件application-client.properties
如下:
spring.application.name=sofa-rpc-consumer server.port=9091
com.alipay.sofa.rpc.registry-address=nacos://127.0.0.1:8848
|
使用spring.profiles.active=client
启动ClientApplication
,启动完成后控制台输出:
2020-01-02 17:07:58.782 INFO 2900 --- [main] club.throwable.client.ClientApplication : 调用HelloService#sayHello(),结果:throwable say hello!
|
基本原理如下:

小结
SOFABoot
、SOFARpc
底层依赖于Spring
容器,可以跟随SpringBoot
版本迭代升级,底层通讯使用Netty
,在性能上有保障,而且真正做到了兼容HTTP
、Dubbo
、Service Mesh
(后面应该会把Service Mesh
作为通讯协议进行兼容)等等协议,对于开发者而言相对友好,学习成本低,做到真正的开箱添加少量配置即可使用。除了目前发现依赖版本的问题,暂时没有大的坑,尝尝鲜的感觉还是挺不错的。
示例项目:
(本文完 c-1-d e-a-20200101)