SpringCloud超详细基础流程(Eureka集群+Ribbon+Feign+Zuul+Gitee配合CloudConfig集群)

(Eureka服务端集群+Eureka客户端集群+RestTemplate通信+Ribbon负载均衡[集成Hystrixs]+Feign[开启Hystrix]+Zuul+CloudConfig)

项目结构

  • springcloud-parent(父级模块,用于管理整体项目jar包)
    • springcloud-commons(存放项目中模拟假数据的实体类)
    • springcloud-config-server-1070(Config服务端,用于与gitee仓库连接拉取远端yml,properties文件)
    • springcloud-eureka-server-1010(Eureka服务端,用于应用的注册与发现,会做集群)
    • springcloud-order-server-1030(Eureka客户端,模拟分布式开发模块间通信,实现Ribbon集成Hystrix)
    • springclpud-pay-server-1040(Eureka客户端,模拟分布式开发模块间通信,实现Feign开启Hystrix)
    • springcloud-user-server-1020(Eureka客户端,模拟数据提供模块)
    • springcloud-zuul-server-1050(Zuul网关,实现过滤器权限控制)
      在这里插入图片描述
      父类模块中需要继承springboot与管理springcloud

继承

  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.0.5.RELEASE</version>
    <relativePath/> <!-- lookup parent from repository -->
  </parent>

管理

<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
      <version>2.0.5.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-dependencies</artifactId>
      <version>Finchley.SR1</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
    <dependency>
      <groupId>hi.same</groupId>
      <artifactId>springcloud-commons</artifactId>
      <version>1.0-SNAPSHOT</version>
    </dependency>
  </dependencies>
</dependencyManagement>

Eureka

服务端

单体服务端

导入Eureka服务端依赖

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>

在SpringBoot主类上打上@EnableEurekaServer注解,然后配置application.yml文件

server:
  port: 1010 #此处为springboot服务端口号
eureka:
  instance:
    hostname: localhost
  client:
    register-with-eureka: false #取消注册到EurekaServer
    fetch-registry: false #不拉取服务的通信地址
    service-url:
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ #客户端的注册地址

开启springboot服务,访问localhost:1010进入到eureka服务端页面

服务端集群

根据上面的单体服务端修改application.yml配置多套spring环境

eureka:
  client:
    service-url:
      defaultZone: http://peer1:1011/eureka/,http://peer2:1012/eureka/,http://peer3:1013/eureka/
  instance:
    prefer-ip-address: true
spring:
  profiles:
    active: peer3
  application:
    name: eureka-server
---
spring:
  profiles: peer1
eureka:
  instance:
    hostname: peer1
    instance-id: eureka-server:1011
server:
  port: 1011
---
spring:
  profiles: peer2
eureka:
  instance:
    hostname: peer2
    instance-id: eureka-server:1012
server:
  port: 1012
---
spring:
  profiles: peer3
eureka:
  instance:
    hostname: peer3
    instance-id: eureka-server:1013
server:
  port: 1013

需要注意此处要把刚才配置的取消自身注册与拉取通信地址删除掉,因为默认为开启,修改springs.profiles.active分别运行三次就可以完成Eureka服务端的集成了,如果无法重复运行三次springboot主配置文件则需要在运行配置里面设置
在这里插入图片描述

如果idea版本过低则需要去掉小勾

客户端

模拟数据公共类

在springcloud-commons中编写User实体类,并在父级模块中添加管理。

public class User {
    private Long id;
    private String username;
    private String password;

    public User() {
    }

    public User(Long id, String username, String password) {
        this.id = id;
        this.username = username;
        this.password = password;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                '}';
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}

单体客户端

导入相关jar包

    <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-web</artifactId>
    </dependency>
    <dependency>
      <groupId>hi.same</groupId>
      <artifactId>springcloud-commons</artifactId>
    </dependency>

在SpringBoot主类上添加@EnableEurekaClient注解,修改application.yml文件

eureka:
  client:
    service-url:
      defaultZone: http://peer1:1011/eureka/,http://peer2:1012/eureka/,http://peer3:1013/eureka/ #eureka服务端的注册地址
  instance:
    instance-id: user-server:1020 #注册服务的ID
    prefer-ip-address: true #使用ip注册到eureka
server:
  port: 1020
spring:
  application:
    name: user-server #应用名

运行服务,访问之前的localhost:1010发现服务已经注册成功

客户端集群

和Eureka服务端操作相似,配置多套spring运行环境然后运行多次springboot服务即可

eureka:
  client:
    service-url:
      defaultZone: http://peer1:1011/eureka/,http://peer2:1012/eureka/,http://peer3:1013/eureka/ #eureka服务端的注册地址
instance:
  prefer-ip-address: true #使用ip注册到eureka
spring:
  application:
    name: user-server #应用名
  profiles:
    active: user-server:1022
---
eureka:
  instance:
    instance-id: user-server:1021 #注册服务的ID
server:
  port: 1021
spring:
  profiles: user-server:1021
---
eureka:
  instance:
    instance-id: user-server:1022 #注册服务的ID
server:
  port: 1022
spring:
  profiles: user-server:1022

order与pay的Eureka客户端不需要做集群,因为要用来实现Ribbon以及Feign。

RestTemplate实现客户端间通信

在user客户端中编写controller用于提供假数据给order和server

@RestController
public class UserController {
    @Value("${server.port}")
    private String port;
    @RequestMapping(value = "/user/{id}",method = RequestMethod.GET)
    public User getById(@PathVariable("id") Long id){
        return new User(id,"ls",port);
    }
}

order客户端的springboot主类中编写RestTemplate的Bean方便用于自动注入,再编写controller用于获取user客户端中的数据。
springboot主类

    @Bean
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }

controller

@RestController
public class OrderController {
    @Autowired
    private RestTemplate restTemplate;
    @RequestMapping(value = "/order/{id}",method = RequestMethod.GET)
    public User getById(@PathVariable("id") Long id){ 
        String url = "http://localhost:1020/user/"+id;
        return restTemplate.getForObject(url,User.class);
    }
}

访问localhost:1030/order/1返回数据

负载均衡

Ribbon实现

导入ribbon包

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
        </dependency>

在springboot主类的RestTemplate的Bean配置上加上@LoadBlanced注解

    @Bean
    @LoadBalanced
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }

再将controller中访问url的localhost:port改为user-server

    @RequestMapping(value = "/order/{id}",method = RequestMethod.GET)
    public User getById(@PathVariable("id") Long id){ 
        String url = "http://user-server/user/"+id;
        return restTemplate.getForObject(url,User.class);
    }

Feign实现

导入jar包

    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>

并在springboot主类上打上@EnableFeignClient标签,然后编写feignclient

@FeignClient(value = "user-server")
public interface UserFeignClient {
    @RequestMapping(value = "/user/{id}",method = RequestMethod.GET,consumes = "application/json")
    User getById(@PathVariable("id") Long id);
}

FeignClient指的是当前Feign客户端是针对哪个服务进行的负载均衡,接口中方法要与对应服务的 controller中方法一致(返回值,参数,请求方式,方法名,请求地址)

熔断器Hystrix

Ribbon集成熔断

导入jar包

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>

在springboot主配置类上打上@EnableCircuitBreaker注解开启熔断器,然后在controller的方法上打上@HystrixCommand标签,并编写降级方法

    @RequestMapping(value = "/order/{id}",method = RequestMethod.GET)
    @HystrixCommand(fallbackMethod = "getByIdFallbackMethod")
    public User getById(@PathVariable("id") Long id){ 
        String url = "http://user-server/user/"+id;
        return restTemplate.getForObject(url,User.class);
    }
    public User getByIdFallbackMethod(@PathVariable("id") Long id){
        return new User(-1L,"报错","正在殴打程序员");
    }

其中注解中的fallbackMethod值要与降级方法的方法名一致,并且降级方法的返回值参数要与熔断方法一致。

Feign开启熔断

由于Feign的jar包已经集成了熔断器所以直接配置application.yml开启熔断即可

feign:`在这里插入代码片`
  hystrix:
    enabled: true #开启熔断支持
ribbon:
  ReadTimeout: 300000
  SocketTimeout: 300000
  ConnectTimeout: 30000
hystrix:
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 10300
实现FeignClient接口编写降级方法
@Component
public class UserFeignClientFallback implements UserFeignClient {
    @Override
    public User getById(Long id) {
        return new User(-1L,"出错","正在殴打程序员");
    }
}

重写Client中的方法返回兜底数据即可

实现FallbakFactory接口编写降级方法
@Component
public class UserFeignClientFallbackFactory implements FallbackFactory<UserFeignClient> {
    @Override
    public UserFeignClient create(Throwable throwable) {
        return new UserFeignClient() {
            @Override
            public User getById(Long id) {
                throwable.printStackTrace();
                return new User(-1L,"出错","殴打程序员");
            }
        };
    }
}

实现工厂接口时泛型为Client接口泛型,重写方法后要求返回一个接口对象则使用匿名内部类的方法重写接口方法实现降级方法的编写并返回兜底数据

Zuul网关

请求分发配置

导入jar包

        <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-web</artifactId>
        </dependency>
        <dependency>
            <groupId>hi.same</groupId>
            <artifactId>springcloud-commons</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.62</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-config-client</artifactId>
        </dependency>

在springboot主类上打上@EnableZuulProxy注解开启网关配置并编写application.yml文件

  client:
    service-url:
      defaultZone: http://peer1:1011/eureka/,http://peer2:1012/eureka/,http://peer3:1013/eureka/ #eureka服务端的注册地址
  instance:
    instance-id: zuul-server:1050 #注册服务的ID
    prefer-ip-address: true #使用ip注册到eureka
server:
  port: 1050
spring:
  application:
    name: zuul-server #应用名
zuul:
  prefix: "/servers"  #统一访问前缀
  ignoredServices: "*"  #禁用掉使用浏览器通过服务名的方式访问服务
  routes:
    pay-server: "/pay/**"   #指定pay-server这个服务使用 /pay路径来访问  - 别名
    order-server: "/order/**"

过滤器权限控制配置

@Component
public class LoginFilter extends ZuulFilter {
    @Override
    public String filterType() {
        return FilterConstants.PRE_TYPE;
    }

    @Override
    public int filterOrder() {
        return FilterConstants.DEBUG_FILTER_ORDER;
    }

    @Override
    public boolean shouldFilter() {
        RequestContext requestContext = RequestContext.getCurrentContext();
        HttpServletRequest request = requestContext.getRequest();
        String uri = request.getRequestURI();
        if(uri.contains("/login") || uri.contains("/register")){
            return false;
        }
        return true;
    }

    @Override
    public Object run() throws ZuulException {
        RequestContext requestContext = RequestContext.getCurrentContext();
        HttpServletRequest request = requestContext.getRequest();
        HttpServletResponse response = requestContext.getResponse();
        response.setContentType("application/json;charset=utf-8");
        try{
            request.setCharacterEncoding("utf-8");
        }catch (Exception e){
            e.printStackTrace();
        }
        String token = request.getHeader("token");
        if(!StringUtils.hasLength(token)){
            Map<String,Object> jsonResult = new HashMap<>();
            jsonResult.put("success",false);
            jsonResult.put("message","没登陆");
            String json = JSON.toJSONString(jsonResult);
            try{
                response.getWriter().print(json);
            }catch (Exception e){
                e.printStackTrace();
            }
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            requestContext.setSendZuulResponse(false);
        }
        return null;
    }
}

filterType为过滤器类型,一般编写的都是pre类型,filterOrder为过滤器优先级,可以决定同类型过滤器的执行顺序,sholdFilter返回true则执行run方法,返回false不执行run方法,run方法中则是具体的过滤逻辑代码

CloudConfig配置

服务端配置

将模块中的application.yml修改为对应名字传到gitee远端仓库中,例如user-server的配置文件命名为application-user.yml
导包

        <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-web</artifactId>
        </dependency>
        <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-config-server</artifactId>
        </dependency>

在springboot主类上打上@EnableConfigServer注解开启配置中心服务端配置,并编写application.yml文件

eureka:
  client:
    service-url:
      defaultZone: http://peer1:1011/eureka/,http://peer2:1012/eureka/,http://peer3:1013/eureka/ #eureka服务端的注册地址
  instance:
  	instance-id: config-server:1070 #注册服务的ID
    prefer-ip-address: true #使用ip注册到eureka
spring:
  application:
    name: config-server #应用名
  cloud:
    config:
      server:
        git:
          uri: https://gitee.com/HisameKenshin/springcloud-config.git
          username: 17360074797
          password: izayoi16.
	server:
	  port: 1070

需要注意uri为远端gitee仓库uri,username为gitee登陆账户,password为登陆密码

客户端配置

以zuul-server为例,导入jar包

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-config-client</artifactId>
        </dependency>

在resources下编写bootstrap.yml文件

spring:
  cloud:
    config:
      label: master
      name: application-zuul
      discovery:
        service-id: config-server
        enabled: true
eureka:
  client:
    service-url:
      defaultZone: http://peer1:1011/eureka/,http://peer2:1012/eureka/,http://peer3:1013/eureka/ #eureka服务端的注册地址

开启config-server服务自动发现,并配置要获取的是远端仓库中master分支的application-zuul.yml文件

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值