SpringCloud配置与详解


一、Springcloud介绍

pring Cloud是一系列框架的有序集合。它利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等,都可以用Spring Boot的开发风格做到一键启动和部署。Spring Cloud并没有重复制造轮子,它只是将各家公司开发的比较成熟、经得起实际考验的服务框架组合起来,通过Spring Boot风格进行再封装屏蔽掉了复杂的配置和实现原理,最终给开发者留出了一套简单易懂、易部署和易维护的分布式系统开发工具包。

下面只简单介绍下经常用的5个

服务发现——Netflix Eureka

客服端负载均衡——Netflix Ribbon

断路器——Netflix Hystrix

服务网关——Netflix Zuul

分布式配置——Spring Cloud Config

二、Springcloud自我保护机制

EMERGENCYI EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ARE UP WHEN THEY' RE NOT. RENEWALS ARE LESSE

这是触发了Eureka的自我保护机制。当服务未按时进行心跳续约时,Eureka会统计服务实例最近15分钟心跳续约的比例是否低于了85%。在生产环境下,因为网络延迟等原因,心跳失败实例的比例很有可能超标,但是此时就把服务剔除列表并不妥当,因为服务可能没有宕机。Eureka在这段时间内不会剔除任何服务实例,直到网络恢复正常。生产环境下这很有效,保证了大多数服务依然可用,不过也有可能获取到失败的服务实例,因此服务调用者必须做好服务的失败容错,一句话讲解:好死不如赖活着

综上,自我保护模式是一种应对网络异常的安全保护措施。它的架构哲学是宁可同时保留所有微服务(健康的微服务和不健康的微服务都会保留),也不盲目注销任何健康的微服务。使用自我保护模式,可以让Eureka集群更加的健壮、稳定。

因此服务调用者必须做好服务的失败容错,可以通过在yml中配置来关停自我保护(不建议):

eureka:

  server:

​    enable-self-preservation:false#关闭自我保护模式(缺省为打开)

Springcloud配置案例

1.EurekaServer(服务注册中心)

pom.xml
<?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.1.7.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.itheima</groupId>
    <artifactId>eureka-server</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>eureka-server</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Greenwich.SR2</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>
        <!--security安全认证依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-security</artifactId>
            <version>2.1.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>com.netflix.ribbon</groupId>
            <artifactId>ribbon</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>

    <repositories>
        <repository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/milestone</url>
        </repository>
    </repositories>

</project>
application.yml
# 端口
server:
  port: 8500
# 配置服务的名称
spring:
  application:
    name: eureka-server
  security: #是否开启用户认证,开启后需要账号密码才能注册,例http://root:123456@127.0.0.1:8501/eureka/
    basic:
      enabled: true
    user:
      name: root
      password: 123456
eureka:
  client:
    register-with-eureka: false #表示是否向eureka注册中心注册自己
    fetch-registry: false #fetch-registry如果为false,则表示自己为注册中心,我的职责就是维护服务实例,并不需要去检索服务
    service-url:
      defaultZone: http://root:123456@127.0.0.1:8501/eureka/ #监控交互界面,注册中心地址,多个注册中心相互注册形成高可用集群,多个地址通过","分隔
  #      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/       #设置与Eureka Server交互的地址查询服务和注册服务都需要依赖这个地址(单机)。
  instance: server1
#  instance: #eureka服务端的实例名称
#    instance-id: eureka-server #修改eureka上默认的描述信息
#    hostname: localhost
  server:
    enable-self-preservation: false
WebSecurityConfig.java
package com.itheima.eurekaserver.crsf;

import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

/**
 * Created by itcast on 2019/10/31.
 */

@EnableWebSecurity
class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        super.configure(http);//加这句是为了访问eureka控制台和/actuator时能做安全控制
        http.csrf().disable();
    }
}
EurekaServerApplication.java
package com.itheima.eurekaserveranother;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

@SpringBootApplication
@EnableEurekaServer //服务端启动类,可以接收别人注册进来
@EnableDiscoveryClient //用法上基本与@EnableEurekaClient一致,在服务启动后自动注册到Eureka中,如果是注册中心推荐使用@EnableDiscoveryClient
public class EurekaServerApplication {

    public static void main(String[] args) {
        SpringApplication.run(EurekaServerApplication.class, args);
    }

}

2.goods-provider(服务提供者)

pom.xml
<!--eureka依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
application.yml
server:
  port: 8750
spring:
  datasource:
    url: jdbc:mysql://127.0.0.1:3306/online_retailers?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf-8
    username: root
    password: 123456
    driver-class-name: com.mysql.cj.jdbc.Driver
  application:
    name: b2b-goods-provider #在其他提供者与之相同的服务名称,表明提供提供的服务一样,常用于ribbon负载均衡
eureka:
  client:
    service-url:
      defaultZone: http://root:123456@localhost:8500/eureka/
  instance:
    hostname: localhost
mybatis:
  mapper-locations: classpath:/mapper/*

GoodsProviderApplication.java
@SpringBootApplication
@EnableEurekaClient //在服务启动后自动注册到Eureka中
Controller中方法接收值
//绑定@RequestParam或者@RequestBody 
@RequestMapping(value = "/selectActivityById",method = RequestMethod.GET)
    public Activity selectActivityById(@RequestParam(value = "id")Long id){
        return activityDao.selectActivityById(id);
    };

3.user-consumer.java(消费者)

pom.xml
        <!--feign依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
            <version>2.1.2.RELEASE</version>
        </dependency>
        <!--eureka依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <!--thymeleaf前面模板依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
            <version>2.1.8.RELEASE</version>
        </dependency>
        <!--hystrix熔断依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
            <version>2.1.2.RELEASE</version>
        </dependency>
application.yml
server:
  port: 8893  #服务端口
spring:
  application:
    name: user-consumer   #服务名
  main:
    allow-bean-definition-overriding: true #遇到同当样名字的时候,是否允许覆盖注册
eureka:
  client:
    service-url:
      defaultZone: http://root:123456@localhost:8500/eureka/  #服务注册地址
  instance:
    hostname: localhost
thymeleaf:
  cache: false      #关闭缓存
  prefix: classpath:/template/
  suffix: .html
  encoding: UTF-8
feign: #feign负载均衡,feign集成ribbon
   hystrix:
     enabled: true
#   httpclient:
#     enabled: true
UserConsumerApplication.java
@SpringBootApplication
@EnableFeignClients
@EnableEurekaClient
@EnableHystrix
ActivityService.java
@Component
//熔断配置
@FeignClient(value = "b2b-goods-provider",fallback = ActivityServiceHystix.class)
public interface ActivityService
{
ActivityServiceHystix.java(熔断处理)
//实现并重写接口,在方法内编写熔断处理
@Component
public class ActivityServiceHystix implements ActivityService
{

Ribbon(负载均衡配置)

在消费者端配置

@Configuration
public class RibbonConfig {
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate(RestTemplateBuilder builder) {
        return builder.build();
    }
}

此时消费端访问服务提供者地址应该是一个地址变量,可能有多个服务提供者(基于服务名字访问

不用担心访问地址和端口号

private static final String url = "http://SPRINGCLOUD-PROVIDER-DEPT"

gateway(路由网关)

pom.xml
        <!--zuul网关依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
            <version>2.1.2.RELEASE</version>
        </dependency>
Application.java
@EnableZuulProxy
application.yml
zuul:
  host:
    connect-timeout-millis: 60000
  routes:
    api-a:
      path: /api-a/**
      serviceId: user-consumer
    api-b:
      path: /api-b/**
      serviceId: b2b-goods-consumer
      add-host-header: true

文章作者: 艾茶叶蛋
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 艾茶叶蛋 !
  目录