[关闭]
@File 2019-10-29T07:07:06.000000Z 字数 7774 阅读 154

spring-cloud

java


image_1dob50djg1cvs1an01ne349qvvfp.png-48.5kB

一、 依赖(适用范围)

1. 配置服务端(配置中心)

  1. <!-- 配置服务端 -->
  2. <dependency>
  3. <groupId>org.springframework.cloud</groupId>
  4. <artifactId>spring-cloud-config-server</artifactId>
  5. </dependency>

2. 配置客户端(所有服务)

  1. <!-- 配置客户端 -->
  2. <dependency>
  3. <groupId>org.springframework.cloud</groupId>
  4. <artifactId>spring-cloud-starter-config</artifactId>
  5. </dependency>

3. 服务端(注册中心)

  1. <!-- eureka 服务端 -->
  2. <dependency>
  3. <groupId>org.springframework.cloud</groupId>
  4. <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
  5. </dependency>

4. 客户端(消费方/服务方)

  1. <!-- eureka 客户端 -->
  2. <dependency>
  3. <groupId>org.springframework.cloud</groupId>
  4. <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
  5. </dependency>

5. 负载均衡(消费方)

  1. <!-- ribbon 负载均衡 -->
  2. <dependency>
  3. <groupId>org.springframework.cloud</groupId>
  4. <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
  5. </dependency>
  6. <!-- feign 负载均衡(依赖 ribbon) -->
  7. <dependency>
  8. <groupId>org.springframework.cloud</groupId>
  9. <artifactId>spring-cloud-starter-openfeign</artifactId>
  10. </dependency>

6. 熔断,服务降级(消费方)

  1. <!-- Hystrix 断路器(依赖 feign) -->
  2. <dependency>
  3. <groupId>org.springframework.cloud</groupId>
  4. <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
  5. </dependency>
  6. <!-- Hystrix 监控 -->
  7. <dependency>
  8. <groupId>org.springframework.boot</groupId>
  9. <artifactId>spring-boot-starter-actuator</artifactId>
  10. </dependency>
  11. <dependency>
  12. <groupId>org.springframework.cloud</groupId>
  13. <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
  14. </dependency>

7. 路由网关(开方入口)

  1. <!-- zuul 路由 -->
  2. <dependency>
  3. <groupId>org.springframework.cloud</groupId>
  4. <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
  5. </dependency>

二、 yml配置

  1. eureka:
  2. instance:
  3. # eureka的服务机器名
  4. hostname: localhost
  5. client:
  6. #表示是否从注册中心抓取服务
  7. fetch-registry: false
  8. # 是否将我这个服务注册到注册中心
  9. register-with-eureka: false
  10. # 表示注册中心的地址
  11. service-url:
  12. defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
  1. spring:
  2. application:
  3. # 设置服务名(相同的服务,名称要一样)
  4. name: ms-provider
  5. eureka:
  6. client:
  7. #是否从注册中心抓取服务(消费方开启)
  8. fetch-registry: false
  9. # 是否注册到注册中心(服务方开启)
  10. register-with-eureka: true
  11. # 表示注册中心的地址
  12. service-url:
  13. # 地址为Eureka的地址,表示将我的服务注册到哪个注册中心
  14. defaultZone: http://localhost:7961/eureka/
  15. instance:
  16. # 将服务的IP地址信息注册到 Eureka上
  17. prefer-ip-address: true

三、 注册服务

入口文件开启服务

  • 服务端:@EnableEurekaServer
  • 客户端:@EnableEurekaClient

四、 消费方:负载均衡配置(二选一)

1. ribbon 负载均衡

配置:

  • 创建配置文件,通过 @LoadBalanced 启用负载均衡
  1. @Configuration
  2. public class BeanConfig {
  3. @Bean
  4. // @LoadBalanced 对接口使用 ribbon 负载均衡
  5. @LoadBalanced
  6. public RestTemplate restTemplate() {
  7. return new RestTemplate();
  8. }
  9. }

调用:

  • 调用 RestTemplate
  1. @RestController
  2. public class ConsumerController {
  3. @Resource
  4. private RestTemplate restTemplate;
  5. @GetMapping("/Lidaye")
  6. public String lidaye() {
  7. return restTemplate.getForObject("http://ms-provider/port", String.class);
  8. }
  9. }

2. feign 负载均衡

配置:

  • 在入口文件添加 @EnableFeignClients
  • 创建一个service接口,用 @FeignClient 绑定一个服务名
  1. // 绑定服务名
  2. @FeignClient("ms-provider")
  3. public interface TicketService {
  4. // 绑定服务接口名
  5. @GetMapping("/port")
  6. String run();
  7. }

调用:

  • 调用自定义的 service
  1. @RestController
  2. public class ConsumerController {
  3. @Resource
  4. private TicketService ticketService;
  5. @GetMapping("/Lidaye")
  6. public String lidaye() {
  7. return ticketService.run();
  8. }
  9. }

3. 修改负载均衡策略

3.1 原有的均衡策略

类名 描述
RoundRobbinRule 轮询(默认策略)
RandomRule 随机挑选
RetryRule 按照轮询的方式去调用服务,如果其中某个服务不可用,但是还是会尝试几次,如果尝试过几次都没有成功,那么就不在调用该服务,会轮询调用其他的可用服务。
AvailabilityFilteringRule 会先过滤掉因为多次访问不可达和并发超过阈值的服务,然后轮询调用其他的服务
WeightedResponseTimeRule 根据平均响应时间计算权重,响应越快权重越大,越容易被选中。服务刚重启的时候,还未统计出权重会按照轮询的方式;当统计信息足够的时候,就会按照权重信息访问
ZoneAvoidanceRule 判断server所在的区域性能和可用性选择服务器
BestAvailableRule 会过滤掉多次访问都不可达的服务,然后选择并发量最小的服务进行调用,默认方式

3.2 案例(改为随机策略)

  1. @Configuration
  2. public class BeanConfig {
  3. @Bean
  4. public IRule getRule() {
  5. return new RandomRule();
  6. }
  7. }

3.3 自定义策略

  1. public class CustomizeRule extends AbstractLoadBalancerRule {
  2. private int limit = 5;
  3. /**
  4. * 当前调用的服务
  5. */
  6. private Server currentServer;
  7. /**
  8. * 调用次数
  9. */
  10. private AtomicInteger num = new AtomicInteger(0);
  11. @Override
  12. public Server choose(Object key) {
  13. ILoadBalancer loadBalancer = getLoadBalancer();
  14. //获取可用服务
  15. List<Server> serverList = loadBalancer.getReachableServers();
  16. synchronized (this) {
  17. if(null == currentServer && serverList != null && serverList.size() > 0) {
  18. this.currentServer = serverList.get(0);
  19. num.getAndIncrement();
  20. return currentServer;
  21. }
  22. }
  23. /**
  24. * 1.当前服务是否服务是否满5次,如果是调用下一个。
  25. * 2.如果没有下一个服务,再回到第一个服务。
  26. */
  27. int size = serverList.size();
  28. for(int i = 0; i < size; i++) {
  29. Server server = serverList.get(i);
  30. // 判断当前服务是否为正在循环的服务
  31. if(server.getId().equals(currentServer.getId())) {
  32. // 如果num为4
  33. synchronized (this) {
  34. if (num.get() >= limit) {
  35. // 调用下一个服务,次数要置零, 重新开始计算
  36. num.set(0);
  37. // 表示当前服务为最后一个服务
  38. if (i == (size - 1)) {
  39. // 再从头开始调用
  40. currentServer = serverList.get(0);
  41. // 次数要 +1
  42. num.getAndIncrement();
  43. return currentServer;
  44. } else {
  45. // 走下一个服务
  46. currentServer = serverList.get(i + 1);
  47. num.getAndIncrement();
  48. return currentServer;
  49. }
  50. } else{
  51. num.getAndIncrement();
  52. return currentServer;
  53. }
  54. }
  55. }
  56. }
  57. return null;
  58. }
  59. // 初始化配置
  60. @Override
  61. public void initWithNiwsConfig(IClientConfig iClientConfig) {
  62. }
  63. }
  1. @Bean
  2. public IRule getRule() {
  3. return new CustomizeRule();
  4. }

五、消费方:熔断机制

1. yml配置

  1. feign:
  2. hystrix:
  3. #开启feign的熔断机制
  4. enabled: true

2. 入口文件开启机制

3. 创建降级的服务类

  1. // 实现 TicketService 接口
  2. @Component
  3. public class TicketServiceFallback implements TicketService {
  4. @Override
  5. public String run() {
  6. // 熔断机制触发时执行的内容
  7. return null;
  8. }
  9. }

4. 绑定降级的服务类

  1. // 配置熔断机制
  2. @FeignClient(value = "ms-provider", fallback = TicketServiceFallback.class)
  3. public interface TicketService {
  4. @GetMapping("/port")
  5. String run();
  6. }

5. 监控配置(一般不用)

  1. @Bean
  2. public ServletRegistrationBean getServlet() {
  3. HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();
  4. ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet);
  5. registrationBean.setLoadOnStartup(1);
  6. registrationBean.addUrlMappings("/actuator/hystrix.stream");
  7. registrationBean.setName("HystrixMetricsStreamServlet");
  8. return registrationBean;
  9. }

六、 zuul 路由

1. yml配置

  1. server:
  2. port: 8086
  3. spring:
  4. application:
  5. name: shop-zuul
  6. eureka:
  7. client:
  8. #是否从注册中心抓取服务(消费方开启)
  9. fetch-registry: true
  10. # 是否注册到注册中心(服务方开启)
  11. register-with-eureka: false
  12. # 表示注册中心的地址
  13. service-url:
  14. # Eureka的地址
  15. defaultZone: http://localhost:7961/eureka/
  16. instance:
  17. # 将服务的IP地址信息注册到 Eureka上
  18. prefer-ip-address: true
  19. zuul:
  20. routes:
  21. # 别名,无固定形式(一般使用服务名)
  22. ms-consumer:
  23. # 绑定服务
  24. serviceId: ms-consumer
  25. # 设置服务访问路径
  26. path: /mc/**
  27. # 前缀
  28. prefix: /v1
  29. # 忽略所有默认路径(只开放 path 指定的路径)
  30. ignored-services: "*"

2. 入口类配置

3. 设置 zuul 过滤

  1. @Component
  2. public class MyZuulFilter extends ZuulFilter {
  3. /**
  4. * 过滤时机
  5. * pre 要用在路由映射的阶段是寻找路由映射表的
  6. * post routing,error运行完后才会调用该过滤器,是在最后阶段的
  7. * error 一旦前面的过滤器出错了,会调用error过滤器。
  8. * route 具体的请求转发的时候会调用
  9. */
  10. @Override
  11. public String filterType() {
  12. return "pre";
  13. }
  14. /**
  15. * 优先级
  16. * @return 数值越小越优先级越大
  17. */
  18. @Override
  19. public int filterOrder() {
  20. return 0;
  21. }
  22. /**
  23. * 是否执行过滤
  24. * @return 是或否
  25. */
  26. @Override
  27. public boolean shouldFilter() {
  28. // 检测前面是否有把 sendZuulResponse 设置为 false
  29. return RequestContext.getCurrentContext().sendZuulResponse();
  30. }
  31. /**
  32. * 核心逻辑
  33. * @return
  34. * @throws ZuulException
  35. */
  36. @Override
  37. public Object run() throws ZuulException {
  38. // 取 servlet 中的请求对象
  39. RequestContext requestContext = RequestContext.getCurrentContext();
  40. HttpServletRequest request = requestContext.getRequest();
  41. // 获取头部 token 信息
  42. String access_token = request.getHeader("access_token");
  43. if(access_token == null || "".equals(access_token)){
  44. // 是否要转发请求
  45. requestContext.setSendZuulResponse(false);
  46. // 状态码
  47. requestContext.setResponseStatusCode(403);
  48. // 返回内容
  49. requestContext.setResponseBody("token is invalid");
  50. }
  51. return null;
  52. }
  53. }

七、云配置部署

1. 创建 github 仓库

image_1dllroc4915h41jic1n33gtp1r0v9.png-19.7kB

image_1dllrru1c1kq6k8fa4is884o7m.png-48.4kB

image_1dllsqv221sc33vu15cljmp19mi13.png-39.9kB

2. 上传配置到 github

  1. # 添加到暂存区
  2. git add -A
  3. # 提交到本地版本控制库
  4. git commit -m 'config init'
  5. # 上传到 github(要修改上边拿到的git地址)
  6. git push <git地址> master

image_1dllurvojm44efiaim1h74h0a1g.png-45.1kB

3. 部署配置服务端

  1. server:
  2. port: 7070
  3. spring:
  4. cloud:
  5. config:
  6. server:
  7. git:
  8. # git 地址
  9. uri: https://github.com/theFiles/spring-cloud-config.git

4. 部署配置客户端

  1. spring:
  2. cloud:
  3. # 模拟请求:http://localhost:7070/application-dev.yml
  4. config:
  5. # 文件名
  6. name: application
  7. # 加载哪个文件
  8. profile: dev
  9. # config服务端的地址
  10. uri: http://localhost:7070
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注