微服务温习笔记

发布于:2023-01-15 ⋅ 阅读:(625) ⋅ 点赞:(0)

微服务温习笔记(三)

本次温习主题:Feign

一、Feign 是什么?

Feign是Spring Cloud提供的声明式、模板化的HTTP客户端, 它使得调用远程服务就像调用本地服务一样简单,只需要创建一个接口并添加一个注解即可。

Spring Cloud集成Feign并对其进行了增强,使Feign支持了Spring MVC注解;Feign默认集成了Ribbon,所以Fegin默认就实现了负载均衡的效果。

简单示例图:

 二、入门案例

2.1创建服务提供者

模块结构:

pom.xml

<artifactId>feign_provider</artifactId>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>com.exeicise</groupId>
            <artifactId>springcloud_common</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
    </dependencies>

application.yml

server:
  port: 9090
spring:
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.116.131:8848 #注册中心的地址
  application:
    name: feign-provider #注册到nacos的名字

UserService

public interface UserService {
    User getUserById(Integer id);

    User deleteUserById(Integer id);

    User addUser(User user);
}

UserServiceImpl

@Service
public class UserServiceImpl implements UserService {

    @Override
    public User getUserById(Integer id) {

        return new User(id,"曹公公1",18);
    }

    @Override
    public User deleteUserById(Integer id) {
        return new User(id,"删除了曹公公1",18);
    }

    @Override
    public User addUser(User user) {
        user.setName("新增了曹公公1");
        return user;
    }
}

ProviderController

@RestController
@RequestMapping("/provider")
public class ProviderController {
	
	@Autowired
	private UserService userService;

	@RequestMapping("/getUserById/{id}")
	public User getUserById(@PathVariable Integer id){
		return userService.getUserById(id);
	}

	@RequestMapping("/deleteUserById")
	public User deleteUserById(Integer id){
		return userService.deleteUserById(id);
	}

	@RequestMapping("/addUser")
	User addUser(@RequestBody User user){
		return userService.addUser(user);
	}
}

启动类:FeignProviderApp

@SpringBootApplication
@EnableDiscoveryClient//注册该服务,并发现其它服务
public class FeignProviderApp {

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

2.2创建feign接口

模块结构:

 pom.xml


    <modelVersion>4.0.0</modelVersion>

    <artifactId>feign_interface</artifactId>

    <dependencies>
        <!--Spring Cloud OpenFeign Starter -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <!--将springcloud_common引入进来-->
        <dependency>
            <groupId>com.exercise</groupId>  
            <artifactId>springcloud_common</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>

接口:UserFeign

@FeignClient("feign-provider")
@RequestMapping("/provider")
public interface UserFeign {

    @RequestMapping("/getUserById/{id}")//拼接url
    public User getUserById(@PathVariable("id") Integer id);//restful形式拼接参数

    @RequestMapping("/deleteUserById")//拼接url
    User deleteUserById(@RequestParam("id") Integer id);//?形式拼接参数

    @RequestMapping("/addUser")
    User addUser(@RequestBody User user);//@RequestBody(原本是将json串转对象,在这里是将对象转json串), pojo--->json(变成了json串)
}

2.3创建服务消费者

模块结构:

 pom.xml


    <artifactId>ribbon_consumer</artifactId>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>com.exercise</groupId>
            <artifactId>springcloud_common</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!--feign接口-->
        <dependency>
            <groupId>com.exercise</groupId>
            <artifactId>feign_interface</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>

application.yml

server:
  port: 80
spring:
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.116.131:8848
  application:
    name: feign-consumer

ConsumerController

@RestController
@RequestMapping("/consumer")
public class ConsumerController {

    @Autowired
    private UserFeign userFeign;//代理类

    @RequestMapping("/getUserById/{id}")
    public User getUserById(@PathVariable Integer id){
        System.out.println(userFeign.getClass());
        return userFeign.getUserById(id);
    }
    @RequestMapping("/deleteUserById")
    public User deleteUserById(Integer id){
        return userFeign.deleteUserById(id);
    }

    @RequestMapping("/addUser")
    public User addUser(User user){
        return userFeign.addUser(user);
    }
}

启动类:ConsumerApp

@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients//开启feign注解的扫描
public class FeignConsumerApp {

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

测试:

1.访问路径:127.0.0.1/consumer/getUserById/250

2.访问路径:127.0.0.1/consumer/deleteUserById?250

 

3.访问路径:127.0.0.1/consumer/addUser?id=250&name=cgg&age=18

根据入门案例可以看出Feign参数传递方式:

  • restful风格:

feign接口:@PathVarible【拼接restful形式的url】

  • ?传参

feign接口:@RequestParam【拼接?形式的url】

  • pojo参数

provider:@RequestBody User user【获取请求体中的json串】

 三、Feign 工作原理

3.1 将Feign接口注入到Spring容器中

@EnableFeignClients注解开启Feign扫描,先调用FeignClientsRegistrar.registerFeignClients()方法扫描@FeignClient注解的接口,再将这些接口注入到Spring IOC容器中,方便后续被调用。

3.2 RequestTemplate封装请求信息

SynchronousMethodHandler.invoke(): 当定义的的Feign接口中的方法被调用时,通过JDK的代理方式为Feign接口生成了一个动态代理类,当生成代理时,Feign会为每个接口方法创建一个RequestTemplate。该对象封装了HTTP请求需要的全部信息,如请url、参数,请求方式等信息都是在这个过程中确定的。

3.3 发起请求

SynchronousMethodHandler.executeAndDecode():

通过RequestTemplate生成Request,然后把Request交给Client去处理,Client可以是JDK原生的URLConnection,Apache的HttpClient,也可以时OKhttp,最后Client结合Ribbon负载均衡发起服务调用。

四、Feign的优化

feign的优化大致分为四部分

1.开启feign日志 
        feign:
          client:
            config:
              default:
            loggerLevel: full
        logging:
          level:
            com.exercise.feign: debug

2、feign超时

1、方式一:
            ribbon:
               ConnectTimeout: 5000 #请求连接的超时时间
               ReadTimeout: 5000 #请求处理的超时时间
        2、方式二:
            feign:
              client:
                config:
                  feign-provider:
                ConnectTimeout: 5000 #请求连接的超时时间
                ReadTimeout: 5000 #请求处理的超时时间

如果请求超时控制台会爆出如下异常:

Read timed out executing GET http://feigh-provider/provider/getUserById/250] with root cause

前端页面爆500:

 3、http连接池 

<dependency>
            <groupId>io.github.openfeign</groupId>
            <artifactId>feign-httpclient</artifactId>
        </dependency>

4、gzip压缩

采用deflate算法data压缩,当gzip咋所到一个纯文本文件时,咋所过后可以减少70%以上的文件大小。
 

server:
          compression:
              enabled: true #开启gzip压缩

小结:

feign是spring cloud提供的声明式的http客户端(将注入接口注入给controller)工作在consumer端feign支持springmvc注解 feign集成了Ribbon,所以也支持负载均衡(优化后的ribbon和redistemplate                             

(ribbon+redistemplate)+ 优化 = feign

本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到