SpringCloud微服务框架搭建个人总结(避坑专用)
搭建springcloud微服务框架(基础)
你好! 这篇文章对于你搭建springcloud框架避坑可能会有帮助,转载请附加说明。
踩坑记录
- 把遇到的bug放在前面,希望你们创建的时候多注意一点
1、集成spring-cloud-gateway 启动报以下错误:
No qualifying bean of type 'org.springframework.core.convert.ConversionService' available
原因是因为我们在网关中引入了web依赖,去掉即可。
2、集成feign的时候启动报错:
Service id not legal hostname
原因是因为:一是路径配置的原因。@FeignClient(name= “/eureka_client”)这个注解配置的是服务名,不用加/。二是因为服务名的原因,feign不支持”_“,需要改成”–“。所以项目刚开始创建就得注意起名。
搭建框架
我们使用idea来搭建springcloud框架。
- 搭建父框架选用maven
- 创建成功记得设置jdk和maven。然后把src文件夹删除。
- 接着创建module,在父模块上新建module
- 先创建注册中心Eureka模块
Eureka服务注册中心
- 这儿springboot版本可以不关注,因为版本会在父pom里统一配置
- 然后下一步,然后完成finish。我们把没用的文件删除。留下src和pom,对应pom里面的test依赖也用不到了,可以删除,之后的module创建都警醒该操作。
- 进行pom操作,先上父pom的,springboot的版本可以自己选择,但是一定要注意和cloud版本的匹配问题。我这儿用的2.1.5的boot版本,对应cloud版本是Greenwich.SR2
<groupId>com.test.springcloud</groupId>
<artifactId>muck-up</artifactId>
<version>1.0-SNAPSHOT</version>
<modules>
<module>muck-eureka</module>
</modules>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.5.RELEASE</version>
<relativePath />
</parent>
<properties>
<org.apache.shiro.version>1.4.0</org.apache.shiro.version>
<mysql-connector.version>5.1.35</mysql-connector.version>
<mybatis-spring-boot.version>1.3.2</mybatis-spring-boot.version>
<lombok.version>1.18.10</lombok.version>
</properties>
<dependencyManagement>
<dependencies>
<!-- cloud -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Greenwich.SR2</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- shiro -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>${org.apache.shiro.version}</version>
</dependency>
<!--mysql驱动包-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql-connector.version}</version>
</dependency>
<!-- mybatis支持 -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>${mybatis-spring-boot.version}</version>
</dependency>
<!-- 配置文件小绿叶问题 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-commons-dependencies</artifactId>
<version>Greenwich.SR2</version>
</dependency>
<!-- lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
- 然后配置eureka模块的pom,注意parent一定要和父pom的对应
<parent>
<groupId>com.test.springcloud</groupId>
<artifactId>muck-up</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>muck-eureka</artifactId>
<name>muck-eureka</name>
<description>Demo project for Spring Boot</description>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
- 在eureka启动类加上对应开启eureka服务的注解EnableEurekaServer,表示它是eureka服务。
- 配置文件修改,先创建bootstrap.yml文件。因为微服务优先加载。
- 然后是bootstrap.yml中的配置
server:
port: 8761
eureka:
instance:
prefer-ip-address: true
#hostname: eureka.test.com #eureka服务端的实例名称
server:
enable-self-preservation: false # 中小规模下,自我保护模式坑比好处多,所以关闭它
#renewal-threshold-update-interval-ms: 120000 ## 心跳阈值计算周期,如果开启自我保护模式,可以改一下这个配置
eviction-interval-timer-in-ms: 5000 # 主动失效检测间隔,配置成5秒
use-read-only-response-cache: false # 禁用readOnlyCacheMap
client:
register-with-eureka: false #false表示不向注册中心注册自己。
fetch-registry: false #false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
- 然后启动服务。看到页面服务中心启动。没有服务。
Gateway网关
- 然后集成网关中心选用的gateway,依然是创建module模块,起名为muck-gateway,记得在父pom的modules中添加对应模块名。需要注册在eureka注册中心。上pom
<parent>
<groupId>com.test.springcloud</groupId>
<artifactId>muck-up</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>muck-gateway</artifactId>
<name>muck-gateway</name>
<description>Demo project for Spring Boot</description>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
</dependencies>
- 在启动类上加上euraka的注解EnableEurekaClient,注册到服务中心。这儿注意一个点,有的人注解用的是EnableDiscoveryClient,区别就是用EnableDiscoveryClient是启用服务注册发现功能,而EnableEurekaClient是启用eureka的注册发现。建议使用EnableEurekaClient。
- 然后是配置文件,创建bootstrap.yml,不多说了,上配置
server:
port: 7001
spring:
application:
name: muck-gateway
#eureka配置
eureka:
instance:
prefer-ip-address: true
#hostname: eureka.test.com #eureka服务端的实例名称
instance-id: ${spring.cloud.client.ip-address}:${server.port}
lease-renewal-interval-in-seconds: 5 # 心跳间隔,5秒
lease-expiration-duration-in-seconds: 10 # 没有心跳的淘汰时间,10秒
client:
register-with-eureka: true #true表示向注册中心注册自己。
registry-fetch-interval-seconds: 5 # 定时刷新本地缓存时间
fetch-registry: true #需要注册中心去检索服务
service-url:
defaultZone: http://${spring.cloud.client.ip-address}:8761/eureka/
- 然后启动gateway网关,查看注册中心,注册成功。依照此流程可以创建多个模块。进行注册测试。
路由配置
- 我选用的是路径匹配路由,在gateway的pom配置文件中添加。
spring:
application:
name: muck-gateway
#路由配置(根据路径)
cloud:
loadbalancer:
retry:
enabled: true # 开启重试机制,默认为关闭
gateway:
routes:
#路由的ID,没有固定规则但要求唯一,建议配合服务名
- id: muck-gateway
#匹配后提供服务的路由地址
uri: http://news.baidu.com
predicates:
#断言,路径相匹配的进行路由
- Path= /guonei/**
# filters:
# - StripPrefix=1
- 上面配置path是访问网关的匹配路径,uri是匹配后的跳转路径。id可以自己起名,但是要唯一,建议和服务名一样。然后启动服务器。访问:http://localhost:7001/guonei 如下界面:
- 对应如果你添加了其他模块,也可以进行配置,访问网关进行匹配分发请求
spring:
application:
name: muck-gateway
#路由配置(根据路径)
cloud:
loadbalancer:
retry:
enabled: true # 开启重试机制,默认为关闭
gateway:
routes:
#路由的ID,没有固定规则但要求唯一,建议配合服务名
- id: muck-gateway
#匹配后提供服务的路由地址
uri: http://news.baidu.com
predicates:
#断言,路径相匹配的进行路由
- Path= /guonei/**
# filters:
# - StripPrefix=1
- id: muck-user
#匹配后提供服务的路由地址
uri: http://${spring.cloud.client.ip-address}:7002
predicates:
#断言,路径相匹配的进行路由
- Path= /muck-user/**
- id: muck-auth
#匹配后提供服务的路由地址
uri: http://${spring.cloud.client.ip-address}:7003
predicates:
#断言,路径相匹配的进行路由
- Path= /muck-auth/**
Feign服务通信
- 一个服务调用另一个服务的方法,可以采用Feign,它对加了注解FeignClient的类创建代理,如果该服务通过FeignClient注解的类访问的话,会从服务中心eureka获取对应注解中的服务名,然后访问对应方法的路径。
- 首先在访问端微服务引入pom,启动类加注解。
<!-- openfeign服务调用 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
- 然后创建一个访问接口类,用于定义要访问的接口。注意这里FeignClient的value值是注册服务上对应的名字。fallback 的是如果接口访问超时或者发生错误的回滚方法,对应得开启配置文件中的断路器。GetMapping中的路径也可以添加context-path中设置的路径。路径一定要注意,否则会出现404的问题。
/**
* @author lyl
* @create 2021-04-23 11:54
* @description
* @FeignClient("生产者实例名") 指定生产者实例名称,在生产者的配置文件中,加上该注解表示其他服务可以
*/
@FeignClient(value = "muck-auth",fallback = UserFeignClientFallback.class)
public interface UserClient {
@GetMapping("/muck-auth/auth/getByUserPrint")
public String getByAuth();
}
/**
* @author lyl
* @create 2021-04-25 11:57
* @description 功能描述
*/
@Component
public class UserFeignClientFallback implements UserClient {
@Override
public String getByAuth() {
return "调用auth异常!";
}
}
- 配置文件,请求超时时间设置5秒,在接口中打断点5秒不放可以测试fallback方法。注意日志配置一定要加上,这样可以有效的查看你访问的路径,解决因为路径不正确导致的调用不同。
- connectTimeout连接和读取超时也要配置大点,不然会报错,feign默认1秒
server:
port: 7002
servlet:
context-path: /muck-user
spring:
application:
name: muck-user
#eureka配置
eureka:
instance:
prefer-ip-address: true
#hostname: eureka.test.com #eureka服务端的实例名称
instance-id: ${spring.cloud.client.ip-address}:${server.port}
lease-renewal-interval-in-seconds: 5 # 心跳间隔,5秒
lease-expiration-duration-in-seconds: 10 # 没有心跳的淘汰时间,10秒
client:
register-with-eureka: true # true表示向注册中心注册自己。
registry-fetch-interval-seconds: 5 # 定时刷新本地缓存时间
fetch-registry: true # 需要注册中心去检索服务
service-url:
defaultZone: http://${spring.cloud.client.ip-address}:8761/eureka/
#服务调用配置 feigh自带断路器hystrix
feign:
httpclient:
connection-timeout: 5000 #请求服务超时时间
client:
config:
default:
connectTimeout: 50000 # 连接超时时间
readTimeout: 50000 # 读超时时间
hystrix:
enabled: true #打开断路器
#日志
logging:
level:
com.test.auth.service.AuthClient: debug
- 最后要保证不访问的接口存在,路径正确。
@RestController
@RequestMapping("/auth")
public class AuthController {
@Autowired
AuthClient authClient;
@GetMapping("/getPrint")
public Object getPrint() {
System.out.println("auth-------------------------------11"+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
System.out.println("auth-------------------------------22"+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
return "auth----------";
}
@GetMapping("/getByUserPrint")
public String getByUserPrint() {
System.out.println("auth-------------------------------11"+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
System.out.println("auth-------------------------------22"+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
return "feign调用auth成功!";
}
}
Hystrix 熔断配置
- 在网关中进行熔断配置
- pom中加依赖
<!-- hystrix -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
- 启动类加注解
@SpringBootApplication
@EnableEurekaClient
@EnableHystrix //开启熔断器
public class MuckGatewayApplication {
public static void main(String[] args) {
SpringApplication.run(MuckGatewayApplication.class, args);
}
}
- 配置文件配置
spring:
application:
name: muck-gateway
#路由配置(根据路径)
cloud:
loadbalancer:
retry:
enabled: true # 开启重试机制,默认为关闭
gateway:
routes:
#路由的ID,没有固定规则但要求唯一,建议配合服务名
- id: muck-gateway
#匹配后提供服务的路由地址
uri: http://news.baidu.com
predicates:
#断言,路径相匹配的进行路由
- Path= /guonei/**
# filters:
# - StripPrefix=1
- id: muck-user
#匹配后提供服务的路由地址
uri: http://${spring.cloud.client.ip-address}:7002
predicates:
#断言,路径相匹配的进行路由
- Path= /muck-user/**
filters:
- name: Hystrix # Hystrix Filter的名称、设置成默认的
args: # Hystrix 配置参数
name: fallbackcmd # HystrixCommand 的名字
fallbackUrl: forward:/fallback # 熔断fallback对应的uri
- id: muck-auth
#匹配后提供服务的路由地址
uri: http://${spring.cloud.client.ip-address}:7003
predicates:
#断言,路径相匹配的进行路由
- Path= /muck-auth/**
default-filters:
- name: Hystrix
args:
name: fallbackcmd
fallbackUri: forward:/default-error
# Hystrix 配置
hystrix:
command:
fallbackcmd: #对应user的Hystrix的name配置参数
execution:
isolation:
thread:
timeoutInMilliseconds: 5000 # Hystrix 的fallbackcmd 时间
threadpool:
default:
coreSize: 100 # Hystrix 更改默认并发数配置(默认是10,这里改为100)
- 对应的熔断回滚方法要定义好
@RestController
@RequestMapping
public class HystrixFallbackConfiguration {
@RequestMapping(value = "/fallback")
public String fallBackController() {
return "服务读取超时";
}
@RequestMapping("/default-error")
public String DefaultErrorHandle(){
return "这是通用错误处理返回的信息。";
}
}
重试配置
- gateway网关配置
ribbon:
ReadTimeout: 3000 #请求处理的超时时间(时间要小于Hystix的时间,否则没有重试就服务熔断了)
ConnectTimeout: 3000 #请求连接的超时时间,默认时间为1秒
OkToRetyrOnAllOperations: true #对所有操作都重试
MaxAutoRetyiesNextServer: 1 #切换实例的重试次数
MaxAutoRetries: 1 #对当前实例的重试次数