nacos是springcloud的扩展,注册中心功能通过NacosDiscoveryClient 继承DiscoveryClient,在springcloud中,与Eureka可以无侵入的切换。注册中心可以手动剔除服务实例,通过消息通知客户端更新缓存的实例信息。
Dubbo是一个分布式服务框架,Doubbo的产生让我们告别了HTTP+restful和webservice进行服务数据交互的模式,而Doubbo采用的是分布式SOA服务治理方案,通过RPC远程调用服务。
在项目中注意:
1、product和consumer的包名需一致。
2、Spring boot的版本为2.1.5.RELEASE
3、Product中调用dubbo中config的Service,在consumer端调用dubbo的config中的Reference,同时指定group和version,保证Product和consumer生产者和消费者之间的通信。
这里以Intellij IDEA 2021为例来使用Spring Cloud进行nacos的服务注册及Dubbo分布式框架的使用。
1、点击”文件”--->”新建”---->”项目”。
2、在弹出的对话框中,左边点击Spring Initializr初始化项目,在右边出现对应的栏目, 在名称栏输入项目名称,注意java的对应版本。如下图。
3、然后点击“下一步”进入项目向导的下一步。在左边的Developer Tools中选择lombok,在右边web栏目下选择Spring Web。如下图。
设置完成后,点击“完成”即可。
设置pom.xml的依赖关系,这里需要添加dubbo和nacos的依赖,需要添加3个依赖,如下。
org.springframework.cloud
spring-cloud-starter-dubbo
0.9.0.RELEASE
org.springframework.cloud
spring-cloud-alibaba-nacos-discovery
0.9.0.RELEASE
org.springframework.cloud
spring-cloud-alibaba-nacos-config
0.9.0.RELEASE
还需要一个使用 spring-boot-starter-actuator 包,其可以用于检测系统的健康情况、当前的Beans、系统的缓存等。
org.springframework.boot
spring-boot-starter-actuator
其依赖包设置后,如下图所示。
注意,这里设置org.junit.jupiter包,这个包是spring boot测试的依赖包。
依赖设置成功后,需要重新加载项目。如下图所示。
接下来建立services包,结构如下图。
注意,这里的包名是com.example,除了生产者这样,消费者也需要这样的包名。
在services包点击“新建”-->“java类”。如下图。
在这里输入Balancer类,并设置Balancer类中的属性为
id,diamon,ticket和message。
Balancer类的代码如下。
package com.example.services;
import lombok.Data;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import java.io.Serializable;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Balancer implements Serializable{
private int id;
private int diamond;
private int ticket;
private String message;
}
Balancer类由于需要从生产端Producer向Consumer消费端传送,这里需要实现Serializable序列化,代码如图所示。
利用实现的Balancer类,设置BalancerService服务接口,这里新建服务类接口,如下图所示。
在新建Java类后,选择接口,并命名为BalancerService,如下图所示。
在接口中设置获取Balancer接口方法getBalancer。代码如下。
package com.example.services;
public interface BalancerService {
public Balancer getBalancer(Integer id);
}
现在需要实现BalancerService接口的实现类,新建java的实现类如下图。
新建的类名,输入BalancerServiceImpl确定BalancerService的实现类,如下图。
实现类中需要声明dubbo的service服务,这样可以保证在消费端进行消费。实现的getBalancer接口中,产生静态的balancer信息,通过传入的id获取对应的balancer信息。代码如下。
package com.example.services;
import org.apache.dubbo.config.annotation.Service;
import java.util.Map;
import java.util.HashMap;
@Service(protocol="dubbo",group="dubbo",version="1.0.0")
public class BalancerServiceImpl implements BalancerService{
final static Map balancerMap=new HashMap(){
{
put(1,new Balancer(1,10,1000,"OK"));
put(2,new Balancer(2,0,10000,"OK"));
put(3,new Balancer(3,100,0,"OK"));
}
};
@Override
public Balancer getBalancer(Integer id) {
if(id!=null&&balancerMap.containsKey(id)){
return balancerMap.get(id);
}
return new Balancer(0,0,0,"不存在");
}
}
这里定义了静态的balacerMap,并注入了3个balancer类型的信息。
在getBalancer实现接口的方法中,通过Map的get方法获取对应键的balancer信息。如果没有这个balancer就返回空的balancer信息。
在主类上,还需要设置nacos服务注册能够发现这样的注册信息,需要在主启动类上加上EnableDiscoveryClient注解。主类代码如下。
package com.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient
public class Myproductdubbo1Application {
public static void main(String[] args) {
SpringApplication.run(Myproductdubbo1Application.class, args);
}
}
除了程序的设置外,还需要设置配置文件。配置文件上需要在resources文件夹下设置application.yml和bootstrap.yml.
application.yml中设置dubbo的服务名称。代码如下。
dubbo:
scan:
base-packages: com.example.services
registry:
address: spring-cloud://localhost
protocols:
dubbo:
name: dubbo
port: -1
application:
qos:
enable: false
这里设置dubbo分布式服务的scan扫描包,registry注册地址,及protocols协议,协议中的名称name命名为dubbo,这个名称必须与service中的protocol的名称一致。下图是两个代码的对比图。
bootstap.xml的配置文件内容如下。
spring:
main:
allow-bean-definition-overriding: true
application:
name: myprovider1
cloud:
nacos:
discovery:
enabled: true
register-enabled: true
server-addr: 127.0.0.1:8848
config:
server-addr: 127.0.0.1:8848
这里需要设置应用的名称,这个名称可以在消费端访问,同时需要设置nacos服务注册的发现地址,这个地址是nacos服务的注册地址。配置文件代码截图如下。
至此,spring cloud的provider服务端启动成功。
下面设置spring cloud 的consumer端。
1、点击”文件”--->”新建”---->”项目”
2、在弹出的对话框中,左边点击Spring Initializr初始化项目,在右边出现对应的栏目, 在名称栏输入项目名称,注意java的对应版本。如下图。
3、然后点击“下一步”进入项目向导的下一步。在左边的Developer Tools中选择lombok,在右边web栏目下选择Spring Web。如下图。
设置完成后,点击“完成”即可。
设置pom.xml的依赖关系,这里需要添加dubbo和nacos的依赖,
这里需要添加两个依赖。
org.springframework.cloud
spring-cloud-starter-dubbo
0.9.0.RELEASE
org.springframework.cloud
spring-cloud-alibaba-nacos-discovery
0.9.0.RELEASE
这里也需要一个使用 spring-boot-starter-actuator 包,其可以用于检测系统的健康情况、当前的Beans、系统的缓存等。
org.springframework.boot
spri
其依赖包设置后,如下图所示。
注意,这里设置org.junit.jupiter包,这个包是spring boot测试的依赖包。
依赖设置成功后,需要重新加载项目。如下图所示。
接下来建立services包,结构如下图。
注意,这里的包名是com.example,消费者的包名称需要与生产者相同。
在services包点击“新建”-->“java类”。如下图。
在这里输入Balancer类,Balancer类需要与Provider端一样,这也是为了方便在consumer消费端调用Balancer 类中信息,并设置Balancer类中的属性为
id,diamon,ticket和message。
Balancer类的代码如下。
package com.example.services;
import lombok.Data;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import java.io.Serializable;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Balancer implements Serializable{
private int id;
private int diamond;
private int ticket;
private String message;
}
Balancer类由于需要从生产端Producer向Consumer消费端传送,这里需要实现Serializable序列化,代码如图所示。
利用实现的Balancer类,设置BalancerService服务接口,这里新建服务类接口,如下图所示。
在新建Java类后,选择接口,并命名为BalancerService,如下图所示。
在接口中设置获取Balancer接口方法getBalancer。代码如下。
package com.example.services;
public interface BalancerService {
public Balancer getBalancer(Integer id);
}
接下来,在services包下建立User类,一个User类对应一个Balancer类。这里新建一个User类,如下图所示。
在新建Java类后,选择类,并命名为User,如下图所示。
User类的代码如下。
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
public class User {
private int id;
private String name;
private Balancer balancer;
public User(int id, String name) {
this.id = id;
this.name = name;
}
}
这里的User类有属性id和name,同时一个用户对应消费一个Balancer,这个Balancer需要通过id获取,因此这里获取User时只传入id和name两个参数。
Producer实现生产者,Consumer端实现消费者,消费者需要实现Controller控制器,通过控制器去消费服务端Producer的信息。
在Controller端需要定义Referece注解,Reference注解的作用指出。
让定义的接口引用去指向一个具体的接口实现,但是这个实现肯定不会是生产者端的实现,不然的话,RPC就没有意义了,所以我们现在来探究一下Dubbo中是如何实现的。其原理如下。
总的来说,就是我们看似在调用生产者的方法实现,实际上调用的是本地生成的方法,这个生成方法多种多样,不过这个实现是在内存中的实现,也就是说,消费者并不能显式的看到它.
在这个接口实现中具体要做的事情很明确,就是向生产者发送数据进行通信,并且获取它的返回值.当方法的入参中有类对象时,需要进行序列化转为字节流进行传输.而在生产者,接收到字节流之后要进行反序列化,然后进行具体的实现,再将处理结果返回给消费者(有需要的话需要再次序列化和反序列化)。
在Controller的方法中,除了Reference指定Service方法外,还需要设置user的相关信息,通过getUser的控制器方法获取User,同时设置User的Balancer内容。
package com.example.controller;
import com.example.services.BalancerService;
import com.example.services.User;
import org.springframework.web.bind.annotation.RestController;
import java.util.Map;
import java.util.HashMap;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
@RestController
public class AccountController {
final static Map mapperUser=new HashMap(){
{
put(1,new User(1,"张三"));
put(2,new User(2,"李四"));
put(3,new User(3,"王二麻子"));
}
};
@Reference(version="1.0.0",group="dubbo")
private BalancerService balancerService;
@RequestMapping("/acc/user")
public User getUser(@RequestParam Integer id){
if(id!=null&&mapperUser.containsKey(id)){
User user=mapperUser.get(id);
user.setBalancer(balancerService.getBalancer(id));
return user;
}
return new User(0,"");
}
}
代码设置成功后,还需要设置配置文件 application.yml和bootstrap.yml文件。
application.yml配置文件内容如下。
spring:
application:
name: myprovider2
dubbo:
registry:
address: spring-cloud://localhost
application:
qos:
enable: false
cloud:
subscribed-services: ${provider.application.name}
server:
port: 8805
provider:
application:
name: myprovider1
这里设置了spring消费者的名称,也设置了dubbo的注册地址以及cloud端的subscribed-services属性,这个属性专门说明了用于消费者订阅提供方的应用名称列表。这里定义了provider的应用名称,也定义了provider 的application的应用name名称。
设置的bootstrap.yml文件如下。
spring:
main:
allow-bean-definition-overriding: true
cloud:
nacos:
discovery:
enabled: true
register-enabled: true
server-addr: 127.0.0.1:8848
config:
server-addr: 127.0.0.0:8848
zookeeper:
enabled: false
consule:
enaled: false
eureka:
client:
enabled: false
ribbon:
nacos:
enabled: false
生产者和消费者设置成功后,可以下载nacos的服务端,然后通过startup命令启动nacos,启动时可能会报Tomcat的错误,需要使用-m参数指定standalone独立启动。
启动界面如下图。
启动命令如下。
Startup -m standalone
启动后可以通过浏览器,访问localhost:8848/nacos,访问界面如下。
在nacos界面中输出用户名nacos和密码nacos。进入到nacos中的主页中。
这里启动product生产者。启动后,可以点击左侧“服务管理”中的“服务列表”查看启动的生产者服务。如下图所示。
这时可以看到启动的服务。
接下来再启动消费者。
也可以从nacos服务列表中看到启动的消费者。如下图。
现在,可以启动消费端的访问地址。
http://localhost:8805/acc/user?id=1
访问后页面的显示如下。
至此,项目创建结束。