前言
Spring Cloud是一个较为全面的微服务框架集,集成了如服务注册发现、配置中心、消息总线、负载均衡、断路器、API网关等功能实现。
而在网上经常会发现Spring Cloud与阿里巴巴的Dubbo进行选择对比,这样做其实不是很妥当,前者是一套较为完整的架构方案,而Dubbo只是服务治理与RPC实现方案。
Dubbo在国内有着非常大的用户群体,但是其周边设施与组件相对来说并不那么完善。很多开发者用户又很希望享受Spring Cloud的生态,因此也会有一些Spring Cloud与Dubbo一起使用的案例与方法出现,但是一直以来大部分Spring Cloud整合Dubbo的使用方案都不完善。
直到Spring Cloud Alibaba的出现,才得以解决这样的问题。 在此之前,我们已经学了如何使用Spring Cloud Alibaba来集成Nacos与Spring Cloud应用,并且在此之下可以如传统的Spring Cloud应用一样地使用Ribbon或Feign来微服务之间的协作。
由于Feign是基于Http Restful的调用, 在高并发下的性能不够理想,RPC方案能否切换为Dubbo?Spring Cloud与阿里系的若干组件能否完美集成呢?
可以!本案例将指引大家集成一个微服务的基础架构,并讨论其合理性
总体架构
项目结构
nacos-micro-service
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.lichun</groupId>
<artifactId>nacos-micro-service</artifactId>
<version>1.0-SNAPSHOT</version>
<modules>
<module>application-1</module>
<module>service-1</module>
<module>service-2</module>
<module>gateway</module>
</modules>
<packaging>pom</packaging>
<!--springboot的版本控制-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.4.RELEASE</version>
</parent>
<dependencyManagement>
<dependencies>
<!--spring cloud的版本控制-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Greenwich.SR1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--spring cloud alibaba版本-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.1.1.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>
service-2
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>nacos-micro-service</artifactId>
<groupId>com.lichun</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>service-2</artifactId>
<packaging>pom</packaging>
<modules>
<module>service-2-api</module>
<module>service-2-server</module>
</modules>
</project>
service-2-api
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>service-2</artifactId>
<groupId>com.lichun</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>service-2-api</artifactId>
</project>
ProviderService.java
package com.lichun.service2.api;
public interface ProviderService {
public String service();
}
service-2-server
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>service-2</artifactId>
<groupId>com.lichun</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>service-2-server</artifactId>
<dependencies>
<dependency>
<groupId>com.lichun</groupId>
<artifactId>service-2-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dubbo</artifactId>
</dependency>
</dependencies>
</project>
bootstrap.yml
server:
port: ${port:8083}
spring:
application:
name: service2
main:
allow-bean-definition-overriding: true
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
namespace: dev
cluster-name: DEFAULT
config:
server-addr: 127.0.0.1:8848
file-extension: yaml
namespace: dev
group: LICHUN_GROUP
dubbo:
scan:
base-packages: com.lichun.service2.impl
protocol:
name: dubbo
port: ${dubbo_port:20891}
registry:
address: nacos://127.0.0.1:8848
application:
qos-enable: false
consumer:
check: false
Server2Application.java
package com.lichun.service2;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient
public class Server2Application {
public static void main(String[] args) {
SpringApplication.run(Server2Application.class, args);
}
}
ProviderServiceImpl.java
package com.lichun.service2.impl;
import com.lichun.service2.api.ProviderService;
import org.apache.dubbo.config.annotation.Service;
@Service
public class ProviderServiceImpl implements ProviderService {
@Override
public String service() {
return "Provider invoke";
}
}
service-1
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>nacos-micro-service</artifactId>
<groupId>com.lichun</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>service-1</artifactId>
<packaging>pom</packaging>
<modules>
<module>service-1-api</module>
<module>service-1-server</module>
</modules>
</project>
service-1-api
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>service-1</artifactId>
<groupId>com.lichun</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>service-1-api</artifactId>
</project>
ConsumerService.java
package com.lichun.service1.api;
public interface ConsumerService {
public String service();
}
service-1-server
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>service-1</artifactId>
<groupId>com.lichun</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>service-1-server</artifactId>
<dependencies>
<dependency>
<groupId>com.lichun</groupId>
<artifactId>service-2-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.lichun</groupId>
<artifactId>service-1-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dubbo</artifactId>
</dependency>
</dependencies>
</project>
bootstrap.yml
server:
port: ${port:8082}
spring:
application:
name: service1
main:
allow-bean-definition-overriding: true
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
namespace: dev
cluster-name: DEFAULT
config:
server-addr: 127.0.0.1:8848
file-extension: yaml
namespace: dev
group: LICHUN_GROUP
dubbo:
scan:
base-packages: com.lichun.service1.impl
protocol:
name: dubbo
port: ${dubbo_port:20881}
registry:
address: nacos://127.0.0.1:8848
application:
qos-enable: false
consumer:
check: false
Server1Application.java
package com.lichun.service1;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient
public class Server1Application {
public static void main(String[] args) {
SpringApplication.run(Server1Application.class, args);
}
}
ConsumerServiceImpl.java
package com.lichun.service1.impl;
import com.lichun.service1.api.ConsumerService;
import com.lichun.service2.api.ProviderService;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.dubbo.config.annotation.Service;
@Service
public class ConsumerServiceImpl implements ConsumerService {
@Reference
ProviderService providerService;
@Override
public String service() {
String service = providerService.service();
return "Consumer invoke | " + service ;
}
}
application-1
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>nacos-micro-service</artifactId>
<groupId>com.lichun</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>application-1</artifactId>
<description>应用层,提供http接口服务</description>
<dependencies>
<dependency>
<groupId>com.lichun</groupId>
<artifactId>service-1-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-dubbo</artifactId>
</dependency>
</dependencies>
</project>
bootstrap.yml
server:
port: ${port:8081}
servlet:
context-path: /application1
spring:
application:
name: application1
main:
allow-bean-definition-overriding: true
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
namespace: dev
cluster-name: DEFAULT
config:
server-addr: 127.0.0.1:8848
file-extension: yaml
namespace: dev
group: DEFAULT_GROUP
Application1.java
package com.lichun;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient
public class Application1 {
public static void main(String[] args) {
SpringApplication.run(Application1.class, args);
}
}
Application1Controller.java
package com.lichun.controller;
import com.lichun.service1.api.ConsumerService;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class Application1Controller {
@Reference
private ConsumerService consumerService;
@GetMapping("/service")
public String service() {
String service = consumerService.service();
return "application1 | " + service ;
}
}
gateway
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>nacos-micro-service</artifactId>
<groupId>com.lichun</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>gateway</artifactId>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!--网关依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
</dependencies>
</project>
bootstrap.yml
server:
port: ${port:8080}
spring:
application:
name: gateway
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
namespace: dev
cluster-name: DEFAULT
gateway:
default-filters:
- AddResponseHeader=Response-Default-MyName,lichu
routes:
- id: springcloud-service-route
# 路由的服务地址
uri: lb://application1
# 路由拦截的地址配置(断言)
predicates:
- Path=/application1/**
GateWayApplication.java
package com.lichun;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient
public class GateWayApplication {
public static void main(String[] args) {
SpringApplication.run(GateWayApplication.class, args);
}
}
LoginGlobalFilter.java
package com.lichun.filter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
@Component
public class LoginGlobalFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String token = exchange.getRequest().getQueryParams().getFirst("token");
if (StringUtils.isEmpty(token)) {
exchange.getResponse().setStatusCode(HttpStatus.PAYLOAD_TOO_LARGE);
return exchange.getResponse().setComplete();
}
return chain.filter(exchange);
}
@Override
public int getOrder() {
return 0;
}
}