SpringCloud 是当前最流行的分布式框架之一 而负载均衡也是分布式的核心模块 虽然我没有做过分布式项目 但是学习新东西还是有必要的 就简单的做了一个负载均衡和熔断器
首先需要的是注册中心
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@EnableEurekaServer
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
public class BootCenter {
public static void main(String[] args) {
SpringApplication.run(BootCenter.class, args);
}
}
以及注册中心的配置 这里我就简单的在application.配置了一下
server.port=8888
eureka.instance.hostname=localhost
eureka.client.registerWithEureka=false
eureka.client.fetchRegistry=false
eureka.server.enable-self-preservation=false
eureka.client.serviceUrl.defaultZone=http://localhost:8888/eureka/
消费方–狗的配置
server.port=2333
spring.application.name=boot-orange
eureka.client.serviceUrl.defaultZone=http://localhost:8888/eureka/
feign.hystrix.enabled=true//需要手动开启熔断功能
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=5000//超时5秒熔断服务
消费方需要去实现一个接口
import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
import com.dog.config.FallBack;
//name需要服务方的名单,,fallbackFactory指向一个实现熔断失败的接口 由我们自定义·实现
@FeignClient(name = "boot-apple", fallbackFactory = FallBack.class)
public interface DogImp {
//注意 这个接口是调用服务方的接口 必须保证一致 所有服务方的接口必须和该接口一致 方法名同样必须一致
@RequestMapping("/info/getData")
public String getData();
}
熔断实现的接口 由于原服务方已经无法提供服务 所以需要我们自定义实现并返回接口对象
import org.springframework.stereotype.Component;
import com.dog.service.DogImp;
import feign.hystrix.FallbackFactory;
@Component
public class FallBack implements FallbackFactory<DogImp> {
@Override
public DogImp create(Throwable cause) {
return new DogImp() {
@Override
public String getData() {
return "服务繁忙";
}
};
}
}
接下来是提供服务的服务方–鸭
上面需要服务方的名单就是这个: spring.application.name=boot-apple
所以必须保持一致
server.port=2335
spring.application.name=boot-apple
eureka.client.serviceUrl.defaultZone=http://localhost:8888/eureka/
feign.hystrix.enabled=true
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=5000//熔断时间设置为5秒
服务方的实现就比较简单了
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.duck.entity.User;
@Controller
@RequestMapping("/info")
public class DuckController {
@RequestMapping("/getData")
@ResponseBody
public String getData(@RequestBody User u) {
// try {
// Thread.sleep(5000);
// } catch (Exception e) {
// }
System.out.println("调用duck服务");
return "duck";
}
}
服务方–猫 同理 这个也必须和上面的服务方名单保持一致 spring.application.name=boot-apple
server.port=2334
spring.application.name=boot-apple
eureka.client.serviceUrl.defaultZone=http://localhost:8888/eureka/
feign.hystrix.enabled=true
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=5000
mport org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@RequestMapping("/info")
public class CatController {
@RequestMapping("/getData")
@ResponseBody
public String getData() {
// try {
// Thread.sleep(1000);
// } catch (Exception e) {
//
// }
System.out.println("调用cat服务");
return "cat";
}
}
调用服务
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.dog.service.DogImp;
@Controller
public class DogController {
@Autowired
private DogImp dogImp;
@RequestMapping("/dog")
@ResponseBody
public String dog() {
return dogImp.getData();
}
}
结果发现结果是一次 调用cat服务,一次 服务繁忙 。 说明鸭提供的服务被熔断了 结果发现是鸭方提供的接口多了一个注解
重新开启一次 可以发现这几次都实现了轮训的访问服务方
实现熔断接口 就要让服务器响应时间超过熔断器设定的时间 把鸭方服务器sleep 5秒
可以发现 鸭方服务熔断之后就不在访问鸭方服务 而是每一个请求都去访问猫服务
熔断实现