学习:SpringCloud

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/apache_z/article/details/102496436

ZuulFilter#### 写在前面:
这只是我在学习SpringCLoud的学习笔记,不是系统的知识点,只是做的学习总结和备忘。

备忘:

  1. SpringCloud 项目是在SpringBoot项目的基础上修改而来的,所以先建好一个SpringBoot项目。也就是说每一个微服务就是一个SpringBoot项目。
  2. 引入SpringCloud jar包,注意不同的SpringCloud的架包支持不同版本的SpringBoot
    在这里插入图片描述
    在文件中引入架包
<properties>
       <spring-cloud.version>Greenwich.SR3</spring-cloud.version>
   </properties>
<dependencyManagement>
       <dependencies>
           <!-- 引入spring cloud的依赖 -->
           <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>
  1. 然后就是注册中心,服务提供者,消费者三部分的创建
  2. 创建注册中心,首先引入依赖(SpringCloud上面的依赖已经引入)
<dependency>
           <groupId>org.springframework.cloud</groupId>
           <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
       </dependency>

开启注册服务

@SpringBootApplication
@EnableEurekaServer//开启注册服务
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class,args);
    }
}

添加注册中心配置

server:
  port: 8761                    # 指定该Eureka实例的端口

spring:
  application:
    name: eureka-server
    #服务名称
eureka:
  instance:
      hostname: localhost
  client:
    #是否开启注册服务,因为这里如果为true表示自己注册自己,而自己就是一个服务注册方,没必要自己注册自己
    registerWithEureka: false
    #是否拉取服务列表,这里我只提供服务给别的服务。
    fetchRegistry: false
    #注册中心地址
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/

至此注册中心算是完成了,运行项目,在浏览器中打开链接:localhost:8761,就会进入注册中心的页面,里面可以看到在注册的服务。

  1. 实现服务提供者
    引入依赖架包
<!--引入注册中心客户端依赖,eureka client-->
       <dependency>
           <groupId>org.springframework.cloud</groupId>
           <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
       </dependency>

因为他不是注册服务的服务器,他不需要开启注册服务,所以它省略了这一步
添加依赖

server:
  port: 8000  # 指定该Eureka实例的端口

spring:
  application:
    name: provider-member
eureka:
#eureka里面的注册默认开启,拉取服务列表都是默认开启
  client:
    #注册中心地址
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/

至此服务提供者注册成功,可以在eureka的服务器上看到这个服务,同时消费者可以将这个服务的地址和端口拉取到本地,直接调用
7. 实现服务消费者(同时也可以是服务提供者)
引入依赖架包

<!--引入注册中心客户端依赖,eureka client-->
       <dependency>
           <groupId>org.springframework.cloud</groupId>
           <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
       </dependency>

因为他不是注册服务的服务器,他不需要开启注册服务,所以它省略了这一步

server:
  port: 8010
spring:
  application:
    name: cosumer

eureka:
  client:
    #注册中心地址
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/

可以知道消费者跟服务提供者很像,都是将直击注册到服务器上,并拉取服务列表(默认开启,没有在配置文件中修改就是默认开启),当然你也可以只拉取服务列表,不进行服务注册。
如何使用的服务拉取列表
可以使用多种方式来进行访问,我这里用的是RestTemplate来访问,如下面代码。

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

    //注入restTemplate对象
    @Bean
    //添加负载均衡注解,为restTemplate整合Ribbon
    //restTemplate 本身包含了choose中
    @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate(); //默认使用URLConnection
    }
}

上面的创建Bean,RestTemplate来实现通过URL访问微服务,注解LoadBalanced是是负载均衡,你如果不加可能无法访问微服务。
下面是在Controller中具体调用

@Resource
    private RestTemplate restTemplate;//首先注入RestTemplate
@GetMapping("/{memberid}")
    public Member getMemberId(@PathVariable Integer memberid){
        return  restTemplate.getForObject("http://provider-member/member/"+memberid,Member.class);
    }

里面的URL,provider-member是服务提供者的服务名。Member是返回的值对应的实体类。
8. 负载均衡
为了降低单点故障,我们会提供多个注册中心,多个同名的服务提供者,当时这时候消费者应该调用哪个服务器就需要考虑了。
创建多个注册中心(让注册中心实现HA高可用),多个注册中心相互复制,相互注册。

eureka:
  instance:
    hostname: peer1
  client:
    #注册中心地址
    serviceUrl:
      defaultZone: http://peer2:8762/eureka/

就是服务中心也默认开启注册,将他自己注册到另一个注册中心,并从另一个注册中心拉取服务列表,另外一个服务器也是一样。
这时候因为两个注册中心有了相互联系,如果一台没有启动,就会一直报错。
多个服务提供者:可以在不同端口启动这个服务提供者的应用,这样就是另外一个微服务
开启负载均衡Ribbon
这个负载均衡是写在消费者的代码中(其实就是在RestTemplated的头上加的@Loadbalanced注解)默认是轮询策略,当然也可以修改

扫描二维码关注公众号,回复: 7648235 查看本文章
#这个是服务端的名字
provider-member:
  ribbon:
  #下面是固定的写法,需要不同的策略就使用不同的类名
    NIWSServerListClassName: com.netflix.loadbalancer.ConfigurationBasedServerList
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.WeightedResponseTimeRule

当然也可以写在代码里面的配置类来实现不同策略,具体使用需要在查询。

  1. feign伪装RestTemplate请求
    这个组件也是写在消费者端的
<!-- 添加openfeign依赖 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
            <version>2.1.3.RELEASE</version>
        </dependency>

引入依赖,并开启feign功能

@SpringBootApplication
//添加Feign相关注解
@EnableFeignClients
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class,args);
    }

    //注入restTemplate对象
    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate(); //默认使用URLConnection
    }
}

添加配置文件


#feign的配置,连接超时及读取超时配置
feign:
  client:
    config:
      default:
        connectTimeout: 5000
        readTimeout: 5000
        loggerLevel: basic
  #支持压缩
  compression:
    request:
      enabled: true
    response:
      enabled: true
      

写服务器端的方法映射接口

@FeignClient(value = "provider-member1")
public interface MemberFeignClient {
    //服务中方法的映射路径
    @GetMapping("/member/{id}")
    Member getById(@PathVariable("id")Long id);

    @GetMapping("/member/getByAccountAndPass")
    Member getByAccountAndPass(@RequestParam("memberAccount") String memberAccount,@RequestParam("memberPass") String memberPass);

    @PostMapping("/member/add")
    int add(@RequestBody Member member);
}

在Controller中通过feign调用微服务

@Autowired
    private MemberFeignClient memberFeignClient;
	//注入的这个就是之前写的映射接口,这个被注入为实现类
    /**
     * @param memberid
     * @return
     */
    @GetMapping("/{memberid}")
    public Member getMemberId(@PathVariable Long memberid){
       return  memberFeignClient.getById(memberid);
       //调用接口中的方法,本质上就是封装,将参数重新拿出来拼接为一个URL,来实现访问
    }
  1. Hystrix的使用
    引入架包
<!--引入hystrix包-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
            <version>2.1.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
            <version>2.1.3.RELEASE</version>
        </dependency>

在主类上面添加@EnableCircuitBreaker

@SpringBootApplication
@EnableHystrix
//这个是Hystrix面板的注解(也需要添加依赖)
@EnableHystrixDashboard
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class,args);
    }

    //注入restTemplate对象
    @Bean
    //添加负载均衡注解,为restTemplate整合Ribbon
    //restTemplate 本身包含了choose中
    @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate(); //默认使用URLConnection
    }
}

使用就是在你的Controller的方法上面加上注解

@HystrixCommand(fallbackMethod = "getMemberIdFallBack")
    @GetMapping("/{memberid}")
    public Member getMemberId(@PathVariable Integer memberid){
        return  restTemplate.getForObject("http://provider-member1/member/"+memberid,Member.class);
    }

这个注解里面的参数,fallbackMethod值得是回退函数,当发生故障时,调用这个方法。
12. Zuul的添加
首先这个网关是面向于客户端的,它目的就是尽量减少客户端的请求个数,减少客户端知道后台的架构情况。
(1)首先添加依赖

 <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
            <version>2.1.3.RELEASE</version>
        </dependency>
        <!--引入注册中心依赖,eureka client-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
            <version>2.1.3.RELEASE</version>
        </dependency>

同时也要引入注册中心的客户端,因为网关也要拉取服务,为客户提供服务。
(2)添加配置类
它本质就是通过拦截器,拦截请求然后分发请求到各个微服务,然后拿到返回值。

public class PreRequestLogFilter extends ZuulFilter {

    private static final Logger LOGGER=LoggerFactory.getLogger(PreRequestLogFilter.class);

    //返回过滤器的类型(pre /route/post/error)
    @Override
    public String filterType() {
        //"pre" 类型的过滤器
        return FilterConstants.PRE_TYPE;
    }

    //指定过滤器的执行顺序
    @Override
    public int filterOrder() {
        return 2;
    }

    //返回一个boolean值来判断过滤器是否要执行,true表示执行
    @Override
    public boolean shouldFilter() {
        return true;
    }

    //过滤器的具体逻辑。
    @Override
    public Object run() throws ZuulException {
        RequestContext rc= RequestContext.getCurrentContext();
        HttpServletRequest request=rc.getRequest();
        PreRequestLogFilter.LOGGER.info("{},{}",request.getMethod(),request.getRequestURL());
        return null;
    }
}

只要继承ZuulFilter这个类,并实现里面的抽象方法,就可以设置一个过滤器。同时记得在主类上加注解

@SpringBootApplication
@EnableZuulProxy
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class,args);
    }
//这个是Bean也可以直接在类的头上加上Component注解
    @Bean
    public PreRequestLogFilter preRequestLogFilter(){
        return new PreRequestLogFilter();
    }
}

然后通过这个网关访问所有的微服务,同时访问 /actuator/routes 查看路由列表 ,已经集成了actuator,访问/actuator/filters 端点查看过滤器详情。并且这个网关集合了负载均衡和熔断器的功能。

猜你喜欢

转载自blog.csdn.net/apache_z/article/details/102496436
今日推荐