1、下载微服务的nacos(注册中心+配置中心)
https://github.com/alibaba/nacos/releases
把Linux版的nacos-server-1.4.0.tar.gz下载下来
在服务器上解压 tar zxvf nacos-server-1.4.0.tar.gz
可以不改配置,默认集群启动,所以启动要加上-m standalone
参数,我是直接修改/bin/startup.sh中的export MODE="standalone"
,然后nacos/bin/startup.sh
直接启动,
访问http://192.168.1.178:8848/nacos
,输入初始nacos/nacos登录。
看到是没有任何注册的服务,也没有配置的:
打开idea,搭建springcloud项目
-
1、新建一个
blog-parent
项目,把src目录删掉,添加.gitignore文件,在根目录下执行git init
初始化为git项目。 -
2、为了便于统一管理所有依赖,直接在
blog-parent
的pom.xml文件中继承springboot parent,同时指定版本:
<?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>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.5.RELEASE</version>
</parent>
<groupId>org.lwr</groupId>
<artifactId>blog-parent</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
<spring.cloud.version>Hoxton.SR8</spring.cloud.version>
<spring.cloud.alibaba.version>2.2.3.RELEASE</spring.cloud.alibaba.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring.cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring.cloud.alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.16</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
解析:
1、<packaging>pom</packaging>
表示父项目不打包
2、<dependencyManagement>
的<scope>import</scope>
表示引入spring-cloud和Alibaba的版本管理
<?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>
<parent>
<artifactId>blog-parent</artifactId>
<groupId>org.lwr</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>blog-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>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- 使用jwt签名验证 -->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.11.0</version>
</dependency>
<!-- 使用redis -->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
<!--
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>-->
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
说明:
1、继承blog-parent,使用统一的版本依赖,使用blog-parent的依赖
2、引入依赖:服务发现spring-cloud-starter-alibaba-nacos-discovery
3、引入依赖:网关服务:spring-cloud-starter-gateway
4、gateway一般需要做登录鉴权,使用jwt签名配合redis来做
server:
port: 8080
spring:
application:
name: blog-gateway
cloud:
nacos:
discovery:
server-addr: 192.168.1.178:8848
redis:
host: 192.168.1.178
database: 8
#自定义配置中心参数
nacos:
config:
address: 192.168.1.178:8848
data-id: blog.gateway.routes
group-id: blog
timeout: 5000
#启用监控
management:
endpoints:
web:
exposure:
include:
- "*" # 开放所有端点包括health,info,metrics
endpoint:
health:
show-details: always
说明: server-addr: 192.168.1.178:8848指定nacos注册中心的地址
启动类:
说明:@EnableDiscoveryClient注解把服务注册到注册中
@SpringBootApplication
@EnableDiscoveryClient
public class GatewayApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayApplication.class, args);
}
}
[
{
"id": "gateway-router",
"order": 0,
"predicates": [
"Path=/gateway/**"
],
"filters": [
"RewritePath=/gateway/(?<segment>.*), /$\\{segment}"
],
"uri": "lb://blog-gateway"
},
{
"id": "auth-router",
"order": 2,
"predicates": [
"Path=/auth/**"
],
"filters": [
"RewritePath=/auth/(?<segment>.*), /$\\{segment}"
],
"uri": "lb://blog-auth"
}
]
@Service
public class DynamicRouteService implements ApplicationEventPublisherAware {
@Resource
private RouteDefinitionRepository routeDefinitionRepository;
private ApplicationEventPublisher publisher;
/**
* 手动刷新路由,立即生效
*/
public void refreshRoutes() {
this.publisher.publishEvent(new RefreshRoutesEvent(this));
}
/**
* 保存单个路由,id相同直接覆盖
*/
public void save(RouteDefinition definition) {
routeDefinitionRepository.save(Mono.just(definition)).subscribe();
}
/**
* 删除单个路由
*/
public void delete(String id) {
routeDefinitionRepository.delete(Mono.just(id)).subscribe();
}
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.publisher = applicationEventPublisher;
}
/**
* 清空路由
*/
public void removeAll() {
routeDefinitionRepository.getRouteDefinitions().toStream().forEach(routeDefinition -> {
routeDefinitionRepository.delete(Mono.just(routeDefinition.getId())).subscribe();
});
}
}
@Component
@Slf4j
public class DynamicNacosRouteConfig implements CommandLineRunner {
@Resource
private DynamicRouteService dynamicRouteService;
@Resource
private NacosRouteConfigProperties nacosRouteConfigProperties;
@Resource
private ObjectMapper mapper;
@Override
public void run(String... args) throws Exception {
dynamicRouteByNacosListener();
initRoutersByNacosConfig();
}
private void dynamicRouteByNacosListener() {
try {
ConfigService configService = NacosFactory.createConfigService(nacosRouteConfigProperties.getAddress());
configService.addListener(nacosRouteConfigProperties.getDataId(), nacosRouteConfigProperties.getGroupId(), new Listener() {
@Override
public void receiveConfigInfo(String configInfo) {
refreshRouters(configInfo);
}
@Override
public Executor getExecutor() {
return null;
}
});
} catch (NacosException e) {
e.printStackTrace();
}
}
/**
* 项目启动时从nacos配置中心初始化网关路由
*/
private void initRoutersByNacosConfig() {
try {
ConfigService configService = NacosFactory.createConfigService(nacosRouteConfigProperties.getAddress());
String configInfo = configService.getConfig(nacosRouteConfigProperties.getDataId(), nacosRouteConfigProperties.getGroupId(), nacosRouteConfigProperties.getTimeout());
if (configInfo != null) {
refreshRouters(configInfo);
}
} catch (NacosException e) {
e.printStackTrace();
}
}
private void refreshRouters(String configInfo) {
log.info(configInfo);
try {
JavaType javaType = mapper.getTypeFactory().constructParametricType(ArrayList.class, RouteDefinition.class);
List<RouteDefinition> list = mapper.readValue(configInfo, javaType);
dynamicRouteService.removeAll();
list.forEach(definition -> {
dynamicRouteService.save(definition);
});
dynamicRouteService.refreshRoutes();
} catch (JsonProcessingException e) {
log.error(e.getMessage());
}
}
}
@Data
@Configuration
@ConfigurationProperties(prefix = "nacos.config")
public class NacosRouteConfigProperties {
private String address;
private String dataId;
private String groupId;
private Long timeout;
}
至此,网关模块就能跑起来了,等后面加入其他模块再动态加下路由即可。
源码我放到这里了:https://gitee.com/luckcy/blog-all/tree/gateway-init/