SpringCloud 初认笔记(二,服务消费者)

转载请标明出处:
http://blog.csdn.net/forezp/article/details/69808079
本文出自方志朋的博客

本文都是按照方志朋博客学习所做笔记,作者做的很详细,也很清晰。但可能是spring cloud有东西太多的原因,包括jar包版本之类的,跟着做的时候出现了许多的问题。
在作者的博客下面也有许多的评论,提问。有许多问题我也碰到了,但运气好,我的都解决了。
在本篇结尾有我遇到的坑和填坑方法。

在微服务架构中,业务都会被拆分成一个独立的服务,服务与服务的通讯是基于http restful的。Spring cloud有两种服务调用方式,一种是ribbon+restTemplate,另一种是feign。在这一篇文章首先讲解下基于ribbon+rest。

在实际开发中,一个业务的完成,常常会需要服务A调用服务B,这个过程是服务B的消费。

服务消费者:rest+ribbon

ribbon简介

ribbon是一个负载均衡客户端,可以很好的控制htt和tcp的一些行为。Feign默认集成了ribbon。
使用ribbon消费服务的时候,如果服务有多个实例,ribbon会根据默认根据轮流的策略消费这些实例。

准备

接着上个项目,将eureka创建两个实例。方法:见原博客—–开启多个服务实例

创建消费者

1,同最开始创建Eurake的服务端一样,创建一个springBoot项目:ribbondemo。

只要选择,spring-cloud-starter-netflix-eureka-server这个依赖,因为其中包涵了ribbon的依赖

pom文件如下:

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.example</groupId>
    <artifactId>demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>demo</name>
    <description>Demo project for Spring Boot</description>

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

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <spring-cloud.version>Finchley.SR1</spring-cloud.version>
    </properties>

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

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</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>


</project>

2, 创建配置文件如下:

eureka:
  client:
    service-url:
      defaultZone: http://localhost:8780/eureka/

server:
  port: 8789

spring:
  application:
    name: service-ribbon

3,在主程序上通过@EnableDiscoveryClient向服务中心注册。
并通过@Bean向容器中注入RestTemplate,再使用@LoadBalanced开启负载均衡

//向服务中心注册
@SpringBootApplication
@EnableDiscoveryClient
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
    /**
     * 向spring容器中注入一个bean,并通过LoadBalanced来开启负载均衡
     * @return
     */
    @Bean
    @LoadBalanced
    RestTemplate restTemplate(){
        return  new RestTemplate();
    }
}

4, 在创建一个Service类,在类通过RestTemplate对象调用服务对象消费服务。

@Service
public class ServiceTest {

    @Autowired
    RestTemplate restTemplate;

    //SERVICE-HI替代了具体的url, 因为ribbon会根据具体的服务名替代服务实例。
    public String hiService(String hi){
        return restTemplate.getForObject("http://SERVICE-HI/hi?name="+hi,String.class);
    }
}

5,创建Controller,接收浏览器请求。
并通过service来调用服务。


@RestController
public class TestController {

    @Autowired
    ServiceTest serviceTest;

    @RequestMapping("/hihihi")
    public String hi(@RequestParam String name){
        System.out.println("----------" + name);
        return  serviceTest.hiService(name);
    }


}

6:结果
eureka就有两个服务,第一个服务拥有两个实例。可以通过不同的端口访问。
这里写图片描述

通过ribbon,输入http://localhost:8789/hihihi?name=ribbon来消费服务
多次访问结果在下面两个中切换:

hi ribbon,i am from port:8781,time:Mon Sep 03 17:36:58 CST 2018
hi ribbon,i am from port:8782,time:Mon Sep 03 17:38:02 CST 2018

所以,负载均衡在我们调用下面这个方法时做到的。

restTemplate.getForObject(“http://SERVICE-HI/hi?name=“+hi,String.class);

服务消费者:feign

简介

  • 基于接口
  • 整合了ribbon

创建feign消费者

1,同样的需要前面的eureka客户端的两个实例。
2,同样的创建springboot的项目:feign
但是需要重新导入feign的依赖:

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

3,但修改application.yml配置文件:

eureka:
  client:
    service-url:
      defaultZone: http://localhost:8780/eureka/

server:
  port: 8788

spring:
  application:
    name: service-feign

4,在应用程序上是用注解开启Feign的功能

@EnableFeignClients
@EnableDiscoveryClient
@SpringBootApplication
public class FeigndemoApplication {

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

5,创建接口,使用注解@FeignClient指定调用注册中心的服务

@FeignClient(value = "service-hi")
public interface SchedualServiceHi {

    @RequestMapping(value = "/hi", method = RequestMethod.GET)
    String sayhi(@RequestParam(value = "name") String name);
}

6,再创建Contrloller,对外暴露”/hihihi”,注入接口来消费服务。

@RestController
public class SayHiController {

    @Resource
    private SchedualServiceHi schedualServiceHi;

    @RequestMapping(value = "/hi", method = RequestMethod.GET)
    String sayHi(@RequestParam String name){
        return  schedualServiceHi.sayhi(name);
    }

}

7,结果
这里写图片描述

通过http://localhost:8788/hihihi?name=feign访问:

hi feign,i am from port:8782,time:Mon Sep 03 18:09:29 CST 2018
hi feign,i am from port:8781,time:Mon Sep 03 18:09:53 CST 2018

问题

ps1: 按照作者的方法导入依赖,许多依赖都是unknow? 所以注解都找不到相应类。
与原作者不同,我使用springboot自带的eureka server的spring cloud 版本是Finchley.SR1
所以后面导入ribbon,feign的骨架id都不同。

  • 客户端也只需同服务端一样,从springBoot中选中即可
    依赖主要是:
<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
  • ribbon,不需要导其他依赖。同上。
  • feign,他的id是 …..-openfeign
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>

ps2: 我也出现过404的情况了,出现了下面这种报错
可是requestmapping明明都没有配错,一起都好好的啊。

Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.
Mon Sep 03 18:25:46 CST 2018
There was an unexpected error (type=Not Found, status=404).
No message available

那原因即有可能是你controller的注解使用的是@Controller.
这里必须得用@RestController.

ps3:我还出现了400的报错。
原因是请求的参数名与controller中的handler里接受的参数名不同导致的。
eg: 假如你请求是这样:http://localhost:/hi?name=cloud
而你的handler是这样。

@RequestMapping(value = “/hi”, method = RequestMethod.GET)
String sayHi(@RequestParam String hi){
return schedualServiceHi.sayhi(hi);
}

那对不起,他会报400。必要的参数hi,不存在。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值