Springcloud学习
eureka:
- 首先选择版本,springboot和springcloud版本对应关系可查看官网:
https://start.spring.io/actuator/info
{
"spring-cloud": {
"Hoxton.SR12": "Spring Boot >=2.2.0.RELEASE and <2.4.0.M1",
"2020.0.5": "Spring Boot >=2.4.0.M1 and <2.6.0-M1",
"2021.0.0-M1": "Spring Boot >=2.6.0-M1 and <2.6.0-M3",
"2021.0.0-M3": "Spring Boot >=2.6.0-M3 and <2.6.0-RC1",
"2021.0.0-RC1": "Spring Boot >=2.6.0-RC1 and <2.6.1",
"2021.0.1": "Spring Boot >=2.6.1 and <2.6.7-SNAPSHOT",
"2021.0.2-SNAPSHOT": "Spring Boot >=2.6.7-SNAPSHOT and <3.0.0-M1",
"2022.0.0-M1": "Spring Boot >=3.0.0-M1 and <3.0.0-M2",
"2022.0.0-M2": "Spring Boot >=3.0.0-M2 and <3.1.0-M1"
}
}
新建一个项目空maven项目,用于做父级pom
<?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>org.example</groupId>
<artifactId>springcloud2</artifactId>
<version>1.0-SNAPSHOT</version>
</project>
在新建一个eureka服起名eurekaserver,pom文件如下
<?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 https://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.6.6</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>eurekaserver</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>eurekaserver</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>2021.0.1</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</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>
</plugin>
</plugins>
</build>
</project>
将配置文件改为application.yml
spring:
application:
name: eureka-server
server:
port: 8761
- 然后在主启动类上加上一个server注解
@SpringBootApplication
@EnableEurekaServer
public class EurekaserverApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaserverApplication.class, args);
}
}
小技巧:如果项目启动过多,那么可以在idea的workspace.xml加上这段代码,重启idea,这样,你的项目就会数列排
<component name="RunDashboard">
<option name="configurationTypes">
<set>
<option value="SpringBootApplicationConfigurationType" />
</set>
</option>
</component>
启动项目,访问127.0.0.1:8761
eureka客户端
- 新建项目user springboot项目。
pom文件如下,我这里选了mybatis和eureka-client,spring-web。可以直接复制
<?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 https://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.6.6</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>user</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>user</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>2021.0.1</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</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>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
- 主启动类上加上EnableDiscoveryClient
@SpringBootApplication
@EnableDiscoveryClient
public class UserApplication {
public static void main(String[] args) {
SpringApplication.run(UserApplication.class, args);
}
}
然后配置文件
server:
port: 8763
spring:
application:
name: user
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:8761/eureka/
register-with-eureka: true
fetch-registry: true
instance:
prefer-ip-address: true
启动项目,打开8761端口,可以看到此时的管理界面已经有了user服务,30s心跳机制
ribbon组件
一种负载均衡策略(默认是轮询)
openfeign
新建一个consumer服务用于调用user服务:
里面组件有eureka-client,hystrix,openfeign
<?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 https://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.6.6</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>consumer</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>consumer</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>2021.0.1</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
<version>2.2.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</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>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
启动类:
@SpringBootApplication
@EnableDiscoveryClient //是eureka的客户端
@EnableFeignClients //开启feign
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class, args);
}
}
yml
server:
port: 8764
spring:
application:
name: consumer
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:8761/eureka/
register-with-eureka: true
fetch-registry: true
instance:
prefer-ip-address: true
logging:
level:
com.example.consumer: debug
#如果你的springcloud版本是2021.0.1,那么开始feign的回退机制就是feign.circuitbreaker.enable=true
#版本是Brixton.RELEASE ,那就使用feign.hystrix.enable=true
feign:
circuitbreaker:
enabled: true
-
测试
新建一个配置文件
@Configuration public class RestTemplateConfig { @Bean @LoadBalanced public RestTemplate restTemplate(){ return new RestTemplate(); } }
然后在控制器层新建一个
@RestController
public class HelloController {
@Resource
private RestTemplate restTemplate;
//这里就是ribbon负载均衡策略。
@GetMapping("/getName")
public String getName(@RequestParam String name) {
//这里的USER是要对应你的user服务,如果你是aaa,那就写成aaa
String url = String.format("http://USER/hello?name=%s", name);
String forObject = restTemplate.getForObject(url, String.class);
return forObject;
}
}
调用成功,返回http://127.0.0.1:8764/getName?name=1212 返回1212,证明调用成功。
使用feign远程调用,
并回退机制(如果远程服务崩了,启动断路机制)
首先定义一个接口
@FeignClient(name = "user",fallback = UserNameClientFallback.class)
public interface UserNameClient {
@GetMapping("/hello")
String getName(@RequestParam String name);
}
@Component
public class UserNameClientFallback implements UserNameClient{
//这里就是feign的断路机制
@Override
public String getName(String name) {
return "服务崩了,报错了";
}
}
hellocontroller
// 使用feign远程调用
@Resource
private UserNameClient userNameClient;
@GetMapping("/getFeign")
public String getFeign(@RequestParam String name) {
String forObject = userNameClient.getName(name);
return forObject;
}
user服务完好,就会成功,如果user服务崩了,就会打印服务崩了,报错了。
hystrix:使用
@RestController
//默认的回退机制,不带参数
@DefaultProperties(defaultFallback = "defaultFallback")
public class HelloController {
@Resource
private RestTemplate restTemplate;
@GetMapping("/getName")
@HystrixCommand(fallbackMethod = "fallback")
public String getName(@RequestParam String name) {
String url = String.format("http://USER/hello?name=%s", name);
String forObject = restTemplate.getForObject(url, String.class);
return forObject;
}
private String fallback(String username) {
return "太拥挤了,请稍候再试~~";
}
//默认回退机制不能带参数
private String defaultFallback() {
return "太拥挤了222,默认的回退机制~~";
}
}
如果user崩了,如果HystrixCommand不代fallbackMethod那么就默认使用defaultFallback,
如果呆了,就用它自己的。
这里打印:太拥挤了,请稍候再试~~
zuul组件
它的功能有:限流,网关过滤请求,前端跨域也可以做
新建一个springboot项目,只选zuul和eureka-client
<?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 https://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.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>api-gateway</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>api-gateway</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Hoxton.SR12</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-test</artifactId>
<scope>test</scope>
</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>
</plugin>
</plugins>
</build>
</project>
配置文件
server:
port: 8762
spring:
application:
name: zuul-config
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:8761/eureka/
register-with-eureka: true
fetch-registry: true
instance:
prefer-ip-address: true
zuul:
routes:
#这个aaaa可以随便怎么写都行,路由地址 user-info/xxxuser服务的地址
# aaaaa:
# path: /myUser/**
# serviceId: user-info
# 简介写法
user: /myUser/**
#设置敏感头信息为空,获取cookie
sensitiveHeaders:
#不暴露访问 的接口,通俗讲就是不可以让外部访问的接口,服务之间可以访---排除某些路由
#也可以直接排除整个服务。 - /consumer/**
# ignored-patterns:
# - /consumer/rest/userinfo
#显示路由zuul的端口配置,不配置无法访问 /routes
management:
endpoints:
web:
exposure:
include: "*"
endpoint:
health:
show-details: ALWAYS
主启动类
@SpringBootApplication
@EnableZuulProxy
@EnableDiscoveryClient
public class ApiGatewayApplication {
public static void main(String[] args) {
SpringApplication.run(ApiGatewayApplication.class, args);
}
}
具体使用
- 第一限流
@Component
public class RateLimitFilter extends ZuulFilter {
//限制100个请求,类似于多线程的信号量,发放100个信号,使用的时候tryAcquire,拿到一个信号灯。
private static final RateLimiter RATE_LIMITER = RateLimiter.create(100);
@Override
public String filterType() {
return PRE_TYPE;
}
@Override
public int filterOrder() {
return SEND_ERROR_FILTER_ORDER-1;
}
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() throws ZuulException {
if(!RATE_LIMITER.tryAcquire()){
throw new RuntimeException("xxxx");
}
return null;
}
}
限制请求
@Component
public class ConsumerFilter extends ZuulFilter {
@Override
public String filterType() {
return PRE_TYPE;
}
@Override
public int filterOrder() {
return SEND_ERROR_FILTER_ORDER - 1;
}
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() {
RequestContext context = RequestContext.getCurrentContext();
HttpServletResponse response = context.getResponse();
HttpServletRequest request = context.getRequest();
//往header头里设置
response.setHeader("X-Foo", UUID.randomUUID().toString());
// 进行token校验
String token = request.getParameter("token");
if (StringUtils.isEmpty(token)) {
context.setSendZuulResponse(false);
context.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value());
}
return null;
}
}
跨域使用:
@Configuration
public class CorsConfig {
@Bean
public CorsFilter corsFilter() {
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
final CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowCredentials(true);
configuration.setAllowedOrigins(Arrays.asList("*")); //http:www.a.com
configuration.setAllowedHeaders(Arrays.asList("*"));
configuration.setAllowedMethods(Arrays.asList("*"));
configuration.setMaxAge(300L);
source.registerCorsConfiguration("/**", configuration);
return new CorsFilter(source);
}
}
所有的请求,都通过网关访问,就实现了以上的功能。
config组件
将配置文件放入到git上(我这里是使用码云)
首先新增一个springboot项目,
pom文件如下
<?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 https://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.6.6</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>config</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>config</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>2021.0.1</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</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-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-amqp</artifactId>
</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>
</plugin>
</plugins>
</build>
</project>
yml配置文件
spring:
application:
name: config
cloud:
config:
server:
git:
uri: https://gitee.com/xxxx
username: xxxx
password: xxxx
# cloud.config.server.environment.NoSuchLabelException: No such label: main报错,用这个 default-label: master
default-label: master
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:8761/eureka/
server:
port: 8765
@SpringBootApplication
@EnableDiscoveryClient
@EnableConfigServer
public class ConfigApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigApplication.class, args);
}
}
启动项目注册到服务中。
然后在码云下新建一个地址,举user服务为例
在码云下新建一个user-dev.yml
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
username: root
password:
url: jdbc:mysql://127.0.0.1:3306/sell?characterEncoding=utf8&serverTimezone=UTC
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:8761/eureka/
register-with-eureka: true
fetch-registry: true
instance:
prefer-ip-address: true
然后更改user的yml为bootstrap.yml
里面的内容
server:
port: 8763
spring:
application:
name: user
cloud:
config:
discovery:
enabled: true
service-id: CONFIG
profile: dev
mybatis:
mapper-locations: classpath:mapper/*.xml
启动项目,即可。
Rabbitmq
win安装erl,然后在安装rabbitmq。安装好,访问127.0.0.1:15672
密码账户都是guest。
使用mq,在consumer项目下添加包
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
在项目下新增一个接受类
@Component
@Slf4j
public class RabbitMqTest {
@RabbitListener(bindings = @QueueBinding(
value = @Queue("myQueue"),
exchange = @Exchange("myChange")
))
public void process(Object message){
log.info("rabbitMQ收到的消息:{}",message);
}
}
在添加一个发送类
@RestController
public class MessageController {
@Autowired
private AmqpTemplate amqpTemplate;
@Autowired
private RabbitTemplate rabbitTemplate;
@GetMapping("sendMessage")
public String sendMessage(){
Map<String,Object> map = new HashMap<>();
map.put("k1",new Date());
amqpTemplate.convertAndSend("myQueue",map);
return "success";
}
}
以上就是mq的使用
备忘录:报错
Description:
No spring.config.import property has been defined
Action:
Add a spring.config.import=configserver: property to your configuration.
If configuration is not required add spring.config.import=optional:configserver: instead.
To disable this check, set spring.cloud.config.enabled=false or
spring.cloud.config.import-check.enabled=false.
springcloud2020 版本 把Bootstrap被默认禁用,同时spring.config.import加入了对解密的支持。对于Config Client、Consul、Vault和Zookeeper的配置导入,如果你需要使用原来的配置引导功能,那么需要将org.springframework.cloud:spring-cloud-starter-bootstrap依赖引入到工程中
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>