springcloud+consul+feign+ribbon搭建
由于一些原因,没有使用springcloud alibaba+nacos那一套微服务框架,所以尝试了使用consul这一套。搭建过程中也遇到了一些问题。这次搭建并没有加入网关、链路追踪等技术框架。
一、安装consul
consul安装在了腾讯云上面,使用的是docker-compose工具进行安装的。
consul.yml
version: '3.8'
services:
consul:
image: consul:1.10.1
container_name: consul
restart: always
command: ["consul","agent","-server","-bootstrap","-data-dir","/consul/data","-ui","-bind","127.0.0.1","-client","49.234.11.169"]
#– net=host docker参数, 使得docker容器越过了net namespace的隔离,免去手动指定端口映射的步骤
#- server consul支持以server或client的模式运行, server是服务发现模块的核心, client主要用于转发请求
#- advertise 将本机私有IP传递到consul
#- retry-join 指定要加入的consul节点地址,失败后会重试, 可多次指定不同的地址
#- client 指定consul绑定在哪个client地址上,这个地址可提供HTTP、DNS、RPC等服务,默认是>127.0.0.1
#- client=49.234.11.169
#- bind 绑定服务器的ip地址;该地址用来在集群内部的通讯,集群内的所有节点到地址必须是可达的,>默认是0.0.0.0
#- allow_stale 设置为true则表明可从consul集群的任一server节点获取dns信息, false则表明每次请求都会>经过consul的server leader
#- bootstrap-expect 数据中心中预期的服务器数。指定后,Consul将等待指定数量的服务器可用,然后>启动群集。允许自动选举leader,但不能与传统-bootstrap标志一起使用, 需要在server模式下运行。
#- data-dir 数据存放的位置,用于持久化保存集群状态
#- data-dir=/consul/data
#- node 群集中此节点的名称,这在群集中必须是唯一的,默认情况下是节点的主机名。
#- node=consul_node
#- config-dir 指定配置文件,当这个目录下有 .json 结尾的文件就会被加载,详细可参考https://www.consul.io/docs/agent/options.html#configuration_files
#- enable-script-checks 检查服务是否处于活动状态,类似开启心跳
#- enable-script-checks=true
#- datacenter 数据中心名称
#- ui 开启ui界面
#- ui=true
#- join 指定ip, 加入到已有的集群中
networks:
- consulnet
ports:
- 8500:8500
- 8300:8300
volumes:
- /home/consul/data:/consul/data
- /home/consul/config:/consul/config
networks:
consulnet:
driver: bridge
#启动consul
docker-compose -f consul.yml up -d
二、搭建 Maven项目
新建两个最简单的Maven项目,过程就不贴出来了。这里我并没有将多个服务放在一个父工程下,而是将每个服务单独成一个maven项目。所以创建了多个不同的Maven项目。
项目目录如下图所示:
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>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.8.RELEASE</version>
<relativePath />
</parent>
<groupId>com.example</groupId>
<artifactId>cloud_test</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<!-- springcloud的版本与springboot版本需要对应 -->
<spring-cloud.version>Finchley.RELEASE</spring-cloud.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- 这里使用的是webflux依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<!-- 提供服务发现的能力 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
<!-- 熔断 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>
<!-- ribbon负载均衡 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
<!-- feign -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.70</version>
</dependency>
</dependencies>
<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>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<fork>true</fork>
</configuration>
</plugin>
</plugins>
</build>
</project>
CloudTestApplication.java
@EnableDiscoveryClient
@EnableFeignClients
@SpringBootApplication
public class CloudTestApplication {
public static void main(String[] args) {
new SpringApplicationBuilder(CloudTestApplication.class).web(WebApplicationType.SERVLET).run(args);
}
}
application.yml
server:
port: 8080
servlet:
context-path: /cloud-test
spring:
application:
name: cloud-test
cloud:
consul:
host: consul_ip
port: 8500
discovery:
#服务名称
service-name: ${spring.application.name}
#健康检查时间间隔
health-check-interval: 60s
#启用健康检查
heartbeat:
enabled: true
healthCheckPath: /application/health
health-check-critical-timeout: 3m
prefer-ip-address: true
management:
endpoints:
web:
exposure:
include: '*'
base-path: /application
feign:
hystrix:
enabled: true
hystrix:
command:
default:
execution:
timeout:
enabled: true
isolation:
thread:
timeoutInMilliseconds: 5000
threadpool:
default:
coreSize: 5
maxQueueSize: 100# BlockingQueue的最大队列数,默认值-1
queueSizeRejectionThreshold: 80# 即使maxQueueSize没有达到,达到queueSizeRejectionThreshold该值后,请求也会被拒绝,默认值5
ribbon:
ConnectTimeout: 5000 # 请求连接的超时时间
ReadTimeout: 5000 # 请求处理的超时时间
MaxAutoRetries: 0 # 对当前实例的重试次数
MaxAutoRetriesNextServer: 0 # 切换实例的重试次数
OkToRetryOnAllOperations: true # 对所有操作请求都进行重试
三、feign调用
feign的调用,需要在启动类上加 @EnableFeignClients注解,然后新建一个feign接口,在接口上添加@FeignClient注解。可以新建一个类,用于指定调用失败后的操作。
feign接口
@FeignClient(value = "服务名",fallbackFactory = TestFeignFallback.class)
public interface TestFeign {
/**
* feign测试
* @param str 字符串
* @return mono
*/
@RequestMapping(value = "/get/feignTest",method = RequestMethod.GET)
Result feignTest(@RequestParam(value = "str") String str);
}
@Slf4j
@Component
public class TestFeignFallbackimplements FallbackFactory<TestFeign> {
@Override
public TestFeign create(Throwable throwable) {
String msg = throwable == null ? "" : throwable.getMessage();
return str -> {
log.error("服务调用失败: feignTest: {}", msg);
return new Result().error(400,msg);
};
}
}
四、搭建中遇到的问题
1.部署consul时失败,查看日志发现端口绑定失败,使用开启端口命令无效,需要在控制台进行手动开启。
2.启动服务,服务注册进consul,状态为failing。原因在于未开启健康检测。最后查看application.yml时发现,健康检测开启的配置写错了。
五、总结
我在这里只是简单搭建了一个微服务框架,而且只涉及到了服务治理这块的东西。还有链路追踪、服务网关等都没有涉及。