1、定位不同,dubbo是一个开源的分布式架构框架,致力于解决内部或内网的RPC,是SOA(面向服务架构)时代的产物,它专注于服务的调用与治理;而SpringCloud是一个微服务全家桶,工功能远比dubbo丰富,如:网关、更完善的熔断器、分布式配置、服务跟踪、批量任务等
2、接口调用方式不同,dubbo默认是dubbo协议(也支持http协议),一般是以java接口的形式直接调用;SpringCloud是使用HTTP做接口调用,比较灵活不受开发语言限制;二者相比,dubbo接口调用的性能较好(采用Netty的NIO方式实现)
3、组件差异较多,Dubbo是阿里的开源框架,而SpringCloud是基于SpringBoot开发的框架,dubbo一般使用Zookeeper当注册中心,Springcloud一般使用Eureka或naocs
1、Zookeeper使用需要安装,而Eureka是项目中的一个java服务
2、集群设计不同,Zookeeper是主从设计,而Eureka是各节点平等
3、服务订阅方式不同,Zookeeper中的消费者首次启动将订阅服务信息缓存到本地,之后服务的变更会推送给消费者,而Eureka是采用定时轮询的方式去主动拉取服务的更新
1、zuul(网关):相当于网络服务架构的入口,所有请求必须通过网关转发到具体的服务,主要功能有统一管理微服务请求、负载均衡、动态路由、权限控制、监控、静态资源处理等
2、Eureka(注册中心):用来注册服务,其中包含Eureka Client、Eureka Server
Eureka Client:包含服务提供者,服务消费者,主要负责服务注册、心跳续约与健康状态查询
Eureka Server:提供注册服务,各个节点启动后都会在Eureka Server注册,可用的节点信息可在Eureka Server中的服务注册表中找到
3、Feign:一个HTTP请求的轻量级客户端框架,通过接口+注解的方式发起HTTP请求的调用
具体执行流程如下
a、在主程序上添加@EnableFeignClients注册开启对@FeignClient注解的扫描加载
b、调用接口中的方法时,基于JDK的动态代理,通过InvokeHandler分发远程调用,生成具体的RequestTemplate
c、RequestTemplate生成Request请求,结合Ribbon实现服务负载均衡策略
Feign最核心的就是动态代理,同时整合了Ribbon和Hystrix,具备负载均衡、隔离、熔断和降级功能
4、Ribbon:是一个客户端的负载均衡器,支持简单轮询、权重、随机、重试等多种策略
5、Hystrix:断路器,包含熔断、隔离、降级等功能
1、创建一个项目,笔者这里的demo项目叫bryant(注意需要创建SpringBoot项目),pom文件配置如下:
4.0.0
com.kobe
bryant
0.0.1-SNAPSHOT
pom
org.springframework.boot
spring-boot-starter-parent
2.7.9
eureka-server
user-api
user-client
feign-client
11
UTF-8
UTF-8
2021.0.5
0.0.1-SNAPSHOT
org.springframework.cloud
spring-cloud-dependencies
${spring-cloud.version}
import
pom
org.springframework.boot
spring-boot-starter
org.springframework.boot
spring-boot-starter-test
test
javax.xml.bind
jaxb-api
2.3.0
com.sun.xml.bind
jaxb-impl
2.3.0
org.glassfish.jaxb
jaxb-runtime
2.3.0
javax.activation
activation
1.1.1
bryant
bryant
org.springframework.boot
spring-boot-maven-plugin
2、在父项目下创建Eureka服务项目,eureka-server,pom文件配置如下:
4.0.0
com.kobe
bryant
0.0.1-SNAPSHOT
com.kobe
eureka-server
jar
0.0.1-SNAPSHOT
eureka-server
eureka-server
11
org.springframework.cloud
spring-cloud-starter-netflix-eureka-server
org.springframework.boot
spring-boot-maven-plugin
配置注册中心服务的端口号及其他参数:
#tomcat
server:
port: 8888
eureka:
instance:
hostname: localhost
client:
register-with-eureka: false
fetch-registry: false
service-url:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
spring:
application:
name: eureka-server
然后在启动类上加上@EnableEurekaServer注解:
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
好了,以上就是注册中心服务创建和配置,启动成功后访问http://localhost:8888会出现如下界面:
3、在父项目下创建服务提供者项目,user-api,pom文件如下:
4.0.0
com.kobe
bryant
0.0.1-SNAPSHOT
com.kobe
user-api
jar
0.0.1-SNAPSHOT
user-api
user-api
11
org.springframework.cloud
spring-cloud-starter-netflix-eureka-client
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-maven-plugin
配置服务端口并在配置文件中指定Eureka注册中心的地址:
#tomcat
server:
port: 8081
eureka:
client:
service-url:
defaultZone: http://localhost:8888/eureka/
spring:
application:
name: user-api
然后在启动类中添加@EnableEurekaClient注解:
@SpringBootApplication
@EnableEurekaClient
public class UserApiApplication {
public static void main(String[] args) {
SpringApplication.run(UserApiApplication.class, args);
}
}
在服务提供者项目简单定义几个http接口:
@RestController
public class UserApiController {
@Value("${spring.application.name}")
private String serverName;
@Value("${server.port}")
private String port;
@GetMapping("user/token")
public String getUserToken() {
return UUID.randomUUID().toString();
}
@GetMapping("user/hi/{name}")
public String sayHi(@PathVariable String name) {
return "Hello, " + name + ", I am " + serverName + ", my port is " + port + ".";
}
}
写好启动服务,刷新注册中心管理页面(http://localhost:8888)能看到已经发现服务:
现在可以修改一下服务提供者的端口,再启动一个服务,方便模拟多节点场景:
4、在父项目下创建rest+ribbon消费者项目,user-client,pom文件如下:
4.0.0
bryant
com.kobe
0.0.1-SNAPSHOT
com.kobe
user-client
jar
0.0.1-SNAPSHOT
user-api
user-api
org.springframework.cloud
spring-cloud-starter-netflix-eureka-client
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-maven-plugin
同样是定义端口和配置Eureka地址:
#tomcat
server:
port: 7071
eureka:
client:
service-url:
defaultZone: http://localhost:8888/eureka/
spring:
application:
name: user-client
然后在启动类中添加@EnableEurekaClient、@EnableDiscoveryClient注解,还需要配置一个RestTemplate类,用来调用服务提供者的接口:
@SpringBootApplication
@EnableEurekaClient
@EnableDiscoveryClient
public class UserClientApplication {
public static void main(String[] args) {
SpringApplication.run(UserClientApplication.class, args);
}
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
现在可以编写controller去调用服务提供者的接口,可以看到http协议后跟的是服务提供者的服务名,后面跟的是其http接口地址:
@RestController
public class UserController {
@Autowired
private RestTemplate restTemplate;
@GetMapping("user/token")
public String getUserToken() {
return restTemplate.getForObject("http://user-api/user/token", String.class);
}
@GetMapping("user/hi/{name}")
public String sayHi(@PathVariable("name") String name) {
return restTemplate.getForObject("http://user-api/user/hi/" + name, String.class);
}
}
启动消费者项目注册中心后台能看到如下结果:
接下来多次访问一下http://localhost:7071/user/hi/SpringCloud接口试试:
能看到已经实现了负载均衡!
5、在父项目下创建feign消费者项目,pom文件如下:
说明:其中rest+ribbon和feign(轻量级的HTTP请求客户端)只是调用代码风格不同,实际开发中任选其一(推荐用feign)
4.0.0
com.kobe
bryant
0.0.1-SNAPSHOT
com.kobe
feign-client
jar
0.0.1-SNAPSHOT
feign-client
feign-client
org.springframework.boot
spring-boot-starter-web
org.springframework.cloud
spring-cloud-starter-netflix-eureka-client
org.springframework.cloud
spring-cloud-starter-openfeign
org.springframework.boot
spring-boot-maven-plugin
配置feign消费者服务端口号及Eureka注册中心的地址:
#tomcat
server:
port: 7072
eureka:
client:
service-url:
defaultZone: http://localhost:8888/eureka/
spring:
application:
name: feign-client
在启动类上添加@EnableEurekaClient、@EnableDiscoveryClient、@EnableFeignClient来启用feign功能:
@SpringBootApplication
@EnableEurekaClient
@EnableDiscoveryClient
@EnableFeignClients
public class FeignClientApplication {
public static void main(String[] args) {
SpringApplication.run(FeignClientApplication.class, args);
}
}
使用feign需要先定义接口,@FeignClient是关键所在,这实际上是对服务提供者的接口的描述,跟定义controller接口相似,具体示例如下:
@FeignClient(value = "user-api")
public interface IUserApiRemoteService {
@GetMapping("user/token")
String getToken();
@GetMapping("user/hi/{name}")
String sayHi(@PathVariable String name);
}
然后使用就跟平时注入一个普通的service一样,它底层是使用代理来实现的:
@RestController
public class UserController {
@Autowired
private IUserApiRemoteService userRemoteService;
@GetMapping("user/token")
public String getUserToken() {
return userRemoteService.getToken();
}
@GetMapping("user/hi/{name}")
public String sayHi(@PathVariable("name") String name) {
return userRemoteService.sayHi(name);
}
}
启动该服务后访问http://localhost:7072/user/hi/SpringCloud接口:
以上就是SpringCloud的简单使用,这里没有集成网关,可以根据项目的实际需求来评估是否需要使用网关技术。