Spring Cloud Netflix 微服务全家桶(二)

Spring Cloud Netflix 微服务全家桶(二)

一、Restful风格的API

/**
* http://xxx/users                   Get 约定 获取列表信息
* http://xxx/users/{id}              Get 例如:http://xxx/users/1 获取Id=1的user信息
* 							       Delete 删除
* 							       Put    修改
*  
* 可以引入版本的概念
* http://xxx/v1/users  
* http://xxx/v2/users 
* 可以同时存在多个版本的URL 方便迭代
*
* 针对单表不再重复crud         =======> Spring Data Rest(Jpa + Restful)
*
*/
  • 为了防止URL地址出现变化不好修改 一般常用两种方法
    • 记录API 生成API文档 例如:Swagger、Yapi等…
    • 通过Jar包记录URL 进行Jar包依赖

二、远程服务调用 RestTemplate

2.1 使用方式
  • 依赖注入

    @Bean @LoadBalanced

  • 通过资源地址调用服务

    “http://provider/getHi” 底层自动解析成Ip+Port

2.2 getForEntity方法
  • 参数

    • URL地址
    • 返回值类型 URL接口返回值类型
  • 返回ResponseEntity对象(Spring封装Rest响应对象 包括状态码和资源)

    • Http请求头信息
    • Http响应码
    • Http响应体
2.3 getForObject 方法
  • 参数

    • URL地址
    • 返回值类型 URL接口返回值类型
  • 返回值

    • 调用的服务接口返回的数据 根据第二个参数封装
2.4 带参数的远程调用
  • 消费方代码

    • 通过占位符的方式
    String url = "http://provider/getObj?name={1}";
    Person obj = restTemplate.getForObject(url, Person.class, "lilianjie");
    return obj;
    
    // 可以通过这种方式将lijianjie参数传递到服务的提供方
    
    • 通过Map的方式
    String url = "http://provider/getObj?name={name}";
    Map<String, String> map = Collections.singletonMap("name", "chenglong");
    Person obj = restTemplate.getForObject(url, Person.class, map);
    return obj;
    
    // 可以通过这种方式将chenglong参数传递到服务的提供方
    
2.5 Post 等其他请求
  • 消费方代码

    // 发送Post请求
    // restTemplate.postForEntity()
    // restTemplate.postForLocation()
    // restTemplate.postForObject()
    // 注意 PostForLocation处理
    // 这里 服务的生产方必须在response Header中赋值才可以传递
    
    // 消费方代码 =========================================
    URI location = restTemplate.postForLocaion(url, map, Person.class);
    System.out.println(location);
    
    // 生产方代码 =========================================
    URI uri = new URI("https://www.baidu.com/s?wd=" + person.getName());
    // 如果不添加响应头 消费方获取不到返回值
    response.setHeader("Location", uri);
    return uri;
    
2.6 全局拦截器

拦截调用以及返回

  • 拦截器代码

    public class LoggingClientInterceptor implements ClientHttpRequestInterceptor {
    	
    	@Override
    	public ClientHttpResponse intercept(HttpRequest reqest, byte[] body, ClientHttpRequestExecution execution) throws IOException {
            System.out.println("拦截请求!");
            System.out.println(request.getURI());
            
            ClientHttpResponse response = execution.execute(request, body);
            System.out.println(response.getHeader());
            
            return response;  
    	}
    }
    
  • 将拦截器添加到RestTemplate中

    @Bean
    @LoadBalanced
    RestTemplate restTemplate() {
    	RestTemplate restTemplate = new RestTemplate();
        // 由此可见可以添加多个拦截器
    	restTemplate.getInterceptors().add(new LoggingClientInterceptor());
    	return restTemplate;
    }
    

三、声明式服务调用Feign

3.1 Feign和Open Feign的区别
  • Feign本身不支持Spring Mvc的注解
  • Open Fegin是Spring Cloud在Feign基础上支持了Spring Mvc的注解,通过解析注解值,动态代理生成实现类,在实现类中做负载均衡并调用其他服务
3.2 声明式服务调用
  • 配置类启动Feign

    @SpringBootApplication
    @EnableFeignClients
    
  • 创建远程调用接口

    // url即远程调用的服务名称
    
    // 通过IP+Port直接调用 不需要Eureka 也没有负载均衡
    // @FeignClient(name = "xxoo", url = "http://localhost:81")
    
    // 通过Eureka + ribbon 可以负载均衡
    // @FeignClient(name = "xxoo", url = "http://user-provider")
    @FeignClient(name = "user-provider")
    public interface UserApi {
        
        @GetMapping("/alive")
        public String alive();
    }
    
  • 前端控制器

    @Autowired
    UserApi userApi;
    
    @GetMapping("/alive")
    public String alive() {
        // 调用远程服务的alive方法
    	return userApi.alive();
    }
    
  • 优化

    • 服务提供方 提供接口Jar包

    • 服务消费方 通过pom引入接口的Jar包 不需要自己编写接口地址

    • 提供方和消费方都面向抽出的接口编程

    • 消费方接口继承抽出来的接口

    @FeignClient(name = "user-provider")
    public interface ConsumerApi extends UserApi {
        
    }
    
    • 提供方控制器实现抽出来的接口
    @RestController
    public class UserController implements UserApi {
    
        @Override
        public String alive() {
            return "xxxx";
        }
    }
    

注意问题:

  • Feign使用时 接口的参数需要添加@RequestParam注解 否则调用不通(会将Get请求转成Post请求

    • 解决方案:

      • 方案一:请求上添加注解(Feign的API接口上添加)

      • 方案二:pom添加依赖 替换底层实现(未验证)

        <dependency>
        	<groupId>io.github.openfeign</groupId>
        	<artifactId>feign-httpclient</artifactId>
        </dependency>
        
    • 原因:未添加@RequestParam注解时 Feign解析地址未将参数拼接

  • Post请求则不需要添加在参数中添加注解

四、相关思考

4.1 Spring Cloud 默认使用Http请求的好处?
  • 异构平台

    即可跨平台,可跨语言 不需要考虑其他服务是否是Java实现

  • 可插拔

    服务之间的调用是弱引用 服务的生产方下线对于消费方没有很大影响

    长连接服务之间的依赖性太强

    Http请求特点:

    1. 每次请求不一定到哪一个服务
    2. Http请求是无状态的

带来的好处:

  • 可用性无限提高

弊端:

  • 降低了一定的数据一致性(网络传输 通过Json序列化效率比RPC协议Byte数组低很多)
4.2 关于异构的Ribbon负载均衡问题
  • provider为PHP consumer为Java

    此时可以支持ribbon 无任何影响

  • consumer为PHP

    此时当然不可用ribbon ribbon是Java的组件

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值