Spring Cloud 笔记----持续更新中......

本文深入探讨Spring Cloud的生态系统,包括服务注册与发现(Eureka的自我保护机制、服务提供者和消费者)、健康检查(Actuator)、安全验证、负载均衡(Ribbon的自定义策略)以及断路器(Hystrix)。通过实例解析Eureka的服务上下线,Ribbon的负载均衡配置,Feign的声明式服务调用,展示了Spring Cloud在微服务架构中的关键作用。
摘要由CSDN通过智能技术生成

why spring cloud?

  • 跨语言–异构平台服务调用
  • 可插拔–无状态,无强依赖,可随时下线,解决网络不可靠问题
  • 牺牲一部分性能,提高可用性–RPC二进制比http json性能高很多
  • RPC相当于QQ,HTTP相当于微信

Spring Cloud–生态

  • 服务–Spring Boot
  • 模板引擎–Thymeleaf
  • 服务注册–Netflix Eureka
  • 服务调用–Netflix Fegin
  • 负载均衡–Netflix Ribbon
  • 熔断降级–Netflix Hystrix
  • 服务网管–
    • Netflix Zuul–业务网关
    • Spring Cloud Gateway–业务网关
    • Nginx–流量网关
      • WAF
      • 定向流量分发
      • 负载策略
      • Kong
      • Openresty (Nginx+Lua)
  • 权限认证
    • Spring Security–OAuth2.0
    • Spring Shiro
    • Spring Session
    • JWT
  • 分布式事务
    • Alibaba Seata
    • TCC
  • 分布式锁
    • Zookeeper Curator
    • RedLock
  • 链路追踪
    • Spring Cloud Sleuth
    • zipkin
  • 健康检查–Spring Boot Actuator
  • 监控平台–Spring Cloud Admin
  • 消息总线–Spring Cloud Bus
    • Spring Cloud Stream
    • Spring Integration
    • Spring Messaging
    • Apache Camel

Eureka

自我保护机制

客户端每分钟续约数量小于客户端总数的85%时触发保护机制

  • eureka.server.enable-self-preservation=false;

Server

  • 注解:@EnableEurekaServer
  • application.properties
#是否将自己注册到Eureka Server,默认为true
eureka.client.register-with-eureka=false
#是否从Eureka Server获取注册信息,由于单节点,不需要同步其他节点数据,用false
eureka.client.fetch-registry=false
#设置服务注册中心URL,用于client和server端交流
eureka.client.service-url.defaultZone=http://localhost:7900/eureka
#集群配置
#eureka.instance.appname=EurekaServer
#server.port=7200
#eureka.instance.hostname=euk2.com #用来查找主机地址的
#eureka.client.service-url.defaultZone=http://euk1.com:7100/eureka
  • pom.xml
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>

Provider

  • Register–服务注册,在第一次心跳的时候提交
  • Renew–心跳,client向server端每30秒发起一次心跳;若90秒没有更新,则client端删除注册表实例
  • Fetch Registry–client从server获取注册表信息并缓存到本地
  • Cancel–client关闭时通知server,从server实例注册表中删除实例
  • Time Lag–同步时间延迟。更改传播到所有client可能需要2分钟
  • Communication mechanism–通讯机制。Http协议下的Rest请求,默认使用Jersey、Jackson、JSON完成节点通讯

注册

  • application.properties

    spring.application.name=provider
    server.port=80
    eureka.client.service-url.defaultZone=http://euk1.com:7100/eureka
    
    #自定义信息
    #eureka.instance.metadata-map.dalao=huangkb--provider
    
  • pom.xml

    <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>
    

服务列表查看

  • https://github.com/Netflix/eureka/wiki/Eureka-REST-operations
  • http://euk1.com:7100/eureka/apps
  • http://euk1.com:7100/eureka/status
  • http://euk1.com:7100/eureka/apps/provider

Consumer

  • application.properties

    spring.application.name=consumer
    server.port=90
    eureka.client.service-url.defaultZone=http://euk1.com:7100/eureka
    

获取服务列表信息

EurekaClient 版本
@Qualifier("eurekaClient")
@Autowired
EurekaClient client2;

@GetMapping("/client4")
public Object client4() {
    //获取单个
    //List<InstanceInfo> instances = client2.getInstancesById("localhost:provider:80");
    //获取所有
    List<InstanceInfo> instances = client2.getInstancesByVipAddress("provider", false);
    if (instances.size() > 0) {
        InstanceInfo instanceInfo = instances.get(0);
        if (instanceInfo.getStatus() == InstanceInfo.InstanceStatus.UP) {
            String url = "http://" + instanceInfo.getHostName() + ":" + instanceInfo.getPort() + "/getHi";
            System.out.println(url);
            RestTemplate restTemplate = new RestTemplate();
            String respStr = restTemplate.getForObject(url, String.class);
            System.out.println("respStr:" + respStr);
        }
    }
    return "client4";
}
LoadBalancerClient 版本
  • lb 做了负载均衡,默认过滤掉了DOWN的状态

    @Autowired
    LoadBalancerClient lb;
    
    @GetMapping("/client5")
    public Object client5() {
        //lb 做了负载均衡,默认过滤掉了DOWN的状态
        ServiceInstance instance = lb.choose("provider");
        //String url = "http://" + instanceInfo.getHostName() + ":" + instanceInfo.getPort() + "/getHi";
        String url = instance.getUri() + "/getHi";
        System.out.println(url);
    
        RestTemplate restTemplate = new RestTemplate();
        String respStr = restTemplate.getForObject(url, String.class);
        System.out.println("respStr:" + respStr);
        return "client5";
    }
    

服务上下线

只是改变了服务在Eureka Service中的状态,服务下线为DOWN

/**
 * 手动操作服务上下线
 */
@Service
public class HealthStatusService implements HealthIndicator {
    public boolean getStatus() {
        return status;
    }
    public void setStatus(boolean status) {
        this.status = status;
    }
    private Boolean status = true;

    @Override
    public Health health() {
        if (status) {
            return new Health.Builder().up().build();
        }
        return new Health.Builder().down().build();
    }
}

actuator–健康上报

  • pom.xml

    <!--节点信息上报-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    
  • application.properties

    #上报信息
    management.endpoints.web.exposure.include=*
    
    #允许手动关闭tomcat
    management.endpoint.shutdown.enabled=true
    
    #上报真实健康状态
    eureka.client.healthcheck.enabled=true
    

security–安全验证

  • pom.xml

    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-security</artifactId>
    </dependency>
    
  • application.properties

    #安全认证
    spring.security.user.name=huangkb
    spring.security.user.password=123456
    
  • 关闭方式跨域攻击

    @Configuration
    @EnableWebSecurity
    public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.csrf().disable();//关闭跨域攻击
            super.configure(http);
        }
    }
    
  • 远程连接

    eureka.client.service-url.defaultZone=http://huangkb:123456@euk1.com:7100/eureka
    

Ribbon

负载均衡算法

负载均衡算法–自定义

public static AtomicInteger atomicInteger = new AtomicInteger();
@GetMapping("/client7")
public Object client7() {
    List<ServiceInstance> instances = client.getInstances("provider");
    int nextInt = 0;
    //随机负载均衡
    nextInt = new Random().nextInt(instances.size());
    //轮训负载均衡
    int i = atomicInteger.getAndIncrement();
    nextInt = i % instances.size();
    //权重负载均衡
    //hash负载均衡
    ServiceInstance instance = instances.get(nextInt);
    
    String url = "http://" + instance.getHost() + ":" + instance.getPort() + "/getHi";
    System.out.println(url);

    String respStr = restTemplate.getForObject(url, String.class);
    System.out.println("respStr:" + respStr);
    return "client7";
}

负载均衡策略–自定义

//自定义负载均衡策略
@Bean
public IRule myRule() {
    //return new RoundRobinRule();//默认
    return new RandomRule();
    //return new RetryRule();
}

ribbon负载均衡配置

  • application.properties

    #负载均衡策略
    provider.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RandomRule
    

ribbion直连

#直连
ribbon.eureka.enabled=false
ribbon.listOfServers=localhost:80

RestTemplate–远程服务调用

基于LoadBalanced远程

@LoadBalanced
@Bean
RestTemplate getRestTemplate() {
    return new RestTemplate();
}

@GetMapping("/client9")
public Object client9() {
    // ServiceInstance instance = lb.choose("provider");
    // String url = instance.getUri() + "/getHi";
    String url = "http://provider/getHi";
    System.out.println(url);

    String respStr = restTemplate.getForObject(url, String.class);
    System.out.println("respStr:" + respStr);
    return "client9";
}

拦截器

@LoadBalanced
@Bean
RestTemplate getRestTemplate() {
    RestTemplate restTemplate=new RestTemplate();
    restTemplate.getInterceptors().add(new LoggingClientHttpRequestInterceptor());
    return restTemplate;
}

//拦截器
public class LoggingClientHttpRequestInterceptor implements ClientHttpRequestInterceptor {
@Override
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
        System.out.println("");
        System.out.println("拦截器--拦截啦");
        System.out.println("拦截器url:"+request.getURI());

        ClientHttpResponse response = execution.execute(request, body);
        System.out.println("拦截器res--"+response.getHeaders());

       return response;
   }
}

Feign–声明式服务调用

@EnableFeignClients----feign本质就是RestTemplate进一步封装

方式一

@FeignClient(name = "xxoo", url = "http://localhost:82")
public interface UserApi {
    @GetMapping("/alive")
    public String alive();
}

方式二

@FeignClient(name = "user-provider")
public interface UserApi {
    @GetMapping("/alive")
    public String alive();
}

方式三

面向接口编程,类似dubbo

  • UserApi 通用接口类包

    @RequestMapping("/User")
    public interface UserApi {
        /**
         * hello 测试
         * @return xxoo
         */
        @GetMapping("/alive")
        public String alive();
    }
    
  • consumer extends UserApi 调用

    @FeignClient(name = "user-provider")
    public interface ConsumerApi extends UserApi {
    }
    
    @RestController
    public class MainController {
        @Autowired
        ConsumerApi api;
    
        @GetMapping("/alive")
        public String alive() {
            return api.alive();
        }
    }
    
    
  • provider implement UserApi 实现方法

    @RestController
    public class UserController implements UserApi {
        @Override
        public String alive() {
            return "xxoo";
        }
    }
    

Hystrix–断路器

未完待续```

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值