IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> Springcloud、Nacos 服务注册、负载均衡Ribbon、http客户端Feign -> 正文阅读

[网络协议]Springcloud、Nacos 服务注册、负载均衡Ribbon、http客户端Feign

? ? ? ? SpringCloud是基于SpringBoot的一整套实现微服务的框架。它提供了微服务开发所需的配置管理、服务发现、断路器、智能路由、微代理、控制总线、全局锁、决策竞选、分布式会话和集群状态管理等组件。最重要的是,基于SpringBoot,会让开发微服务架构非常方便。

官网地址:Spring Cloud


Spring Cloud环境:idea+jdk1.8+maven

gitee代码:java_springcloud: springcloud

springcloud开始入门包结构(api包开始可以不用创建),注意maven的某些依赖需要修改成自己的

?初始需要的代码:

sql代码:

tb_orde

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for tb_order
-- ----------------------------
DROP TABLE IF EXISTS `tb_order`;
CREATE TABLE `tb_order`  (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '订单id',
  `userId` bigint(20) NOT NULL COMMENT '用户id',
  `name` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '商品名称',
  `price` bigint(20) NOT NULL COMMENT '商品价格',
  `num` int(10) NULL DEFAULT 0 COMMENT '商品数量',
  PRIMARY KEY (`id`) USING BTREE,
  UNIQUE INDEX `username`(`name`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 109 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;

-- ----------------------------
-- Records of tb_order
-- ----------------------------
INSERT INTO `tb_order` VALUES (101, 1, 'Apple 苹果 iPhone 12 ', 699900, 1);
INSERT INTO `tb_order` VALUES (102, 2, '雅迪 yadea 新国标电动车', 209900, 1);
INSERT INTO `tb_order` VALUES (103, 3, '骆驼(CAMEL)休闲运动鞋女', 43900, 1);
INSERT INTO `tb_order` VALUES (104, 4, '小米10 双模5G 骁龙865', 359900, 1);
INSERT INTO `tb_order` VALUES (105, 5, 'OPPO Reno3 Pro 双模5G 视频双防抖', 299900, 1);
INSERT INTO `tb_order` VALUES (106, 6, '美的(Midea) 新能效 冷静星II ', 544900, 1);
INSERT INTO `tb_order` VALUES (107, 2, '西昊/SIHOO 人体工学电脑椅子', 79900, 1);
INSERT INTO `tb_order` VALUES (108, 3, '梵班(FAMDBANN)休闲男鞋', 31900, 1);

SET FOREIGN_KEY_CHECKS = 1;

tb_user:

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for tb_user
-- ----------------------------
DROP TABLE IF EXISTS `tb_user`;
CREATE TABLE `tb_user`  (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `username` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '收件人',
  `address` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '地址',
  PRIMARY KEY (`id`) USING BTREE,
  UNIQUE INDEX `username`(`username`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 109 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;

-- ----------------------------
-- Records of tb_user
-- ----------------------------
INSERT INTO `tb_user` VALUES (1, '唐伯虎', '上海');
INSERT INTO `tb_user` VALUES (2, '祝枝山', '北京');
INSERT INTO `tb_user` VALUES (3, '华沉鱼', '贵州');
INSERT INTO `tb_user` VALUES (4, '张必沉', '西安');
INSERT INTO `tb_user` VALUES (5, '郑爽爽', '辽宁');
INSERT INTO `tb_user` VALUES (6, '饭兵兵', '山东');

SET FOREIGN_KEY_CHECKS = 1;

springcloud-parent:

pom.xml:

<?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.demon</groupId>
    <artifactId>springcloud-parent</artifactId>
    <packaging>pom</packaging>
    <version>1.0-SNAPSHOT</version>
    <modules>
        <module>springcloud-order</module>
        <module>springcloud-pojo</module>
        <module>springcloud-user</module>
        <module>springcloud-api</module>
    </modules>
    <!--spring-boot起步依赖-->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.8.RELEASE</version>
    </parent>
    <!--版本控制-->
    <properties>
        <!--spring cloud版本-->
        <spring.cloud-version>Hoxton.SR10</spring.cloud-version>
        <!--jdk版本-->
        <java.version>1.8</java.version>
        <skipTests>true</skipTests>
        <mybatis.version>2.1.1</mybatis.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.20</version>
        </dependency>
    </dependencies>
    <!--依赖-->
    <dependencyManagement>
        <dependencies>
            <!--引入SpringCloudAlibaba的依赖-->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>2.2.6.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring.cloud-version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!--mybatis-->
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>${mybatis.version}</version>
            </dependency>
        </dependencies>
    </dependencyManagement>
</project>

springcloud-order:

包结构:

pom.xml:

<?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">
    <parent>
        <artifactId>springcloud-parent</artifactId>
        <groupId>com.demon</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>springcloud-order</artifactId>

    <dependencies>
        <!--依赖pojo-->
        <dependency>
            <groupId>com.demon</groupId>
            <artifactId>springcloud-pojo</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <!--nacos-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!--sentinel-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>
       
        <!--web起步依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--引入mysql驱动包-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <!--mybatis-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <!--springboot maven插件-->
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

yml:

server:
  port: 1314
spring:
  application:
    name: springcloud-order
  profiles:
    active: dev
  datasource:
    driverClassName: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/springcloud?characterEncoding=UTF8&&serverTimezone=Asia/Shanghai
    username: root
    password: root

controller:

package com.demon.controller;

import com.demon.order.pojo.Order;
import com.demon.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * Order的控制层
 */
@RestController
@RequestMapping("/order")
public class OrderController {

    @Autowired
    private OrderService orderService;

    /**
     * 查询订单信息
     */
    @GetMapping(value = "/{id}")
    public Order one(@PathVariable(value = "id") Long id){
        return orderService.selectById(id);
    }

}

dao:

package com.demon.dao;

import com.demon.order.pojo.Order;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
@Mapper
public interface OrderDao {
    /**
     * 根据id查询
     * @param id
     * @return
     */
    @Select(value = "select * from tb_order where id = #{id}")
    Order selectById(Long id);
}

service:

package com.demon.service;

import com.demon.order.pojo.Order;

public interface OrderService {
    /**
     * 根据id查询
     * @param id
     * @return
     */
    Order selectById(Long id);
}

impl:

package com.demon.service.impl;


import com.demon.dao.OrderDao;
import com.demon.order.pojo.Order;
import com.demon.service.OrderService;
import com.demon.user.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

@Service
public class OrderServiceImpl implements OrderService {

    @Autowired
    private OrderDao orderDao;

    @Autowired
    private RestTemplate restTemplate;

    /**
     * 根据id查询
     * @param id
     * @return
     */
    @Override
    public Order selectById(Long id) {
        //1.查询订单
        Order order = orderDao.selectById(id);
        //2.根据订单查询用户信息 RestTemplate 远程调用方法
        String url="http://localhost:10086/user/"+order.getUserId();
        User forObject = restTemplate.getForObject(url, User.class);
        //3.封装信息
        order.setUser(forObject);
        //4.返回订单信息
        return order;
    }
}

启动类:

package com.demon;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

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

    //远程调用
    @Bean
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
}

springcloud-pojo:

Order:

package com.demon.order.pojo;

import com.demon.user.pojo.User;
import lombok.Data;

import java.io.Serializable;

@Data
public class Order implements Serializable {
    private Long id;
    private Long price;
    private String name;
    private Integer num;
    private Long userId;
    private User user;
}

User:

package com.demon.user.pojo;

import lombok.Data;

import java.io.Serializable;

@Data
public class User implements Serializable {
    private Long id;
    private String username;
    private String address;
}

springcloud-user:

包结构:

pom.xml:

<?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">
    <parent>
        <artifactId>springcloud-parent</artifactId>
        <groupId>com.demon</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>springcloud-user</artifactId>

    <dependencies>
        <!--依赖pojo-->
        <dependency>
            <groupId>com.demon</groupId>
            <artifactId>springcloud-pojo</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <!--nacos-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!--sentinel-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>
        <!--引入feign-api-->

        <!--web起步依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!--引入mysql驱动包-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>

        <!--mybatis-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
        </dependency>
    </dependencies>
</project>

yml:

server:
  port: 10086
spring:
  application:
    name: springcloud-user
  profiles:
    active: dev
  datasource:
    driverClassName: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/springcloud?characterEncoding=UTF8&&serverTimezone=Asia/Shanghai
    username: root
    password: root

controller:

package com.demon.controller;

import com.demon.service.UserService;
import com.demon.user.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private UserService userService;

    /**
     * 调用用户微服中controller的方法
     */
    @GetMapping(value = "/{id}")
    public User one(@PathVariable(value = "id") Long id){
        return userService.selectById(id);
    }
}

dao:

package com.demon.dao;

import com.demon.user.pojo.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;

@Mapper
public interface UserDao {
    /**
     * 根据id查询用户信息
     * @param id
     * @return
     */
    @Select(value = "select * from tb_user where id = #{id}")
    User selectById(Long id);
}

service:

package com.demon.service;

import com.demon.user.pojo.User;

public interface UserService {
    /**
     * 根据id查询用户信息
     * @param id
     * @return
     */
    User selectById(Long id);
}

impl:

package com.demon.service.impl;

import com.demon.dao.UserDao;
import com.demon.service.UserService;
import com.demon.user.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserDao userDao;

    /**
     * 根据id查询用户信息
     * @param id
     * @return
     */
    @Override
    public User selectById(Long id) {
        return userDao.selectById(id);
    }
}

启动类:

package com.demon;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

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

按照上面调用流程,消费者调用服务者存在很多问题: ?:

1:服务消费者该如何获取服务提供者的地址信息?
2:如果有多个服务提供者,消费者该如何选择?
3:消费者如何得知服务提供者的健康状态?


注册中心(选择的是nacos):

nacos注册:nacos下载地址

nacos下载地址nacos访问地址:http://localhost:8848/nacos

Nacos是SpringCloudAlibaba的组件,而SpringCloudAlibaba也遵循SpringCloud中定义的服务注册、服务发现规范。因此使用Nacos和使用Eureka对于微服务来说,并没有太大区别。

主要差异在于:

? ? ? ? 1.依赖不同

? ? ? ? 2.服务地址不同

nacos依赖:

在springcloud-parent父工程添加依赖:

    <dependencyManagement>
        <dependencies>
            .......
            <!--引入SpringCloudAlibaba的依赖-->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>2.2.6.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

在springcloud-order和springcloud-user中导入依赖

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

在springcloud-order和springcloud-user的yml注册nacos的地址

spring:
  cloud:
    nacos:
      server-addr: localhost:8848 #nacos地址配置

启动:

第一步

?第二步:

如果没有下面这个就去启动类上启动之后就会出现了在这里面

查看nacos出现了两个所以注册上了:

但是上面不符合实际所以:

nacos服务分级存储模型:

一个服务可以有多个实例 :而且这些实例分布在不同的地区。如下图:

?而且微服务互相访问时候,应该尽量访问同集群的实例,应为本地访问速度更快。当本集群内不可用才访问其他集群。如下图:

代码:springcloud-order和springcloud-user的yml配置集群

spring:
  cloud:
    nacos:
      server-addr: localhost:8848
      discovery:
        cluster-name: SZ # 集群名称

nacos的界面:?

?这只做出了一个实例所以增加2个实例端口为10087和10088:

第一步:? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 第二步:

? ??

复制启动查看:

?但是全部实例都在SZ这个集群所以:修改UserApplication3在启动

-Dserver.port=10088 -Dspring.cloud.nacos.discovery.cluster-name=HZ


查看nacos:

?搭建好nacos后在springcloud-user的UserController中写入好在后端查看

访问浏览器输入:http://localhost:1314/order/101?或?http://localhost:10086/user/1

浏览器页面:?

?

查看后端

http://localhost:1314/order/101 ?发现访问总是出现是一个接收,所以在返回去第一点查看springcloud-order的OrderServiceImpl发现写死的地址2.所以出现了负载均衡Ribbon

负载均衡Ribbon

Ribbon是Netflix发布的负载均衡器,有助于控制HTTP客户端行为。为Ribbon配置服务提供者地址列表后,Ribbon就可基于负载均衡算法,自动帮助服务消费者请求。

概念:Ribbon是基于Http协议请求的客户端负载均衡器,能实现很丰富的负载均衡算法。

负载均衡流程(用的EurekaServer 演示,演示端口号和上面不一样但还是效果一样的):?

负载均衡算法?:

轮询调用会涉及到很多负载均衡算法,负载均衡算法比较多,关系图如下:

内置负载均衡规则类
RoundRobinRule简单轮询服务列表来选择服务器。
AvailabilityFilteringRule

对以下两种服务器进行忽略:

(1)在默认情况下,这台服务器如果3次连接失败,这台服务器就会被设置为“短路”状态。短路状态将持续30秒,如果再次连接失败,短路的持续时间就会几何级地增加。

(2)并发数过高的服务器。如果一个服务器的并发连接数过高,配置了AvailabilityFilteringRule规则的客户端也会将其忽略。并发连接数的上限,可以由客户端的<clientName>.<clientConfigNameSpace>.ActiveConnectionsLimit属性进行配置。

WeightedResponseTimeRule为每一个服务器赋予一个权重值。服务器响应时间越长,这个服务器的权重就越小。这个规则会随机选择服务器,这个权重值会影响服务器的选择。
ZoneAvoidanceRule【默认】

以区域可用的服务器为基础进行服务器的选择。使用Zone对服务器进行分类,这个Zone可以理解为一个机房、一个机架等。而后再对Zone内的多个服务做轮询。它是Ribbon默认的负载均衡规则。

BestAvailableRule忽略哪些短路的服务器,并选择并发数较低的服务器。
RandomRule随机选择一个可用的服务器。
RetryRule重试机制的选择逻辑

Ribbon负载均衡算法的使用有2种方式:

1.代码方式

注册IRule接口的实现类(负载均衡算法):在springcloud-order中的启动类中添加如下负载均衡注册代码:

/**
 * 随机负载均衡算法
 * @return
 */
@Bean
public IRule randomRule() {
    return new RandomRule();
}

2.配置方式

为指定服务配置负载均衡算法:在springcloud-order的核心配置文件中添加如下配置:

#注意配置到跟节点
#指定服务使用指定负载均衡算法
springcloud-user:
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule #负载均衡规则

开启饥饿加载:

Ribbon默认是采用懒加载,即第一次访问时才会去创建LoadBalanceClient,请求时间会很长。 而饥饿加载则会在项目启动时创建,降低第一次访问的耗时,在springcloud-order的核心配置文件中,添加如下配置开启饥饿加载:

#注意配置到跟节点
#饥饿加载
ribbon:
  eager-load:
    clients: springcloud-user #指定对user这个服务饥饿加载
    enabled: true #开启饥饿加载 

在访问网址http://localhost:1314/order/101又发现问题了: 三个集群都能实现没有:同集群优先的负载均衡没有实现。

同集群优先的负载均衡:

默认的ZoneAvoidanceRule并不能实现根据同集群优先来实现负载均衡。

因此Nacos中提供了一个NacosRule的实现,可以优先从同集群中挑选实例。

修改springcloud-order的yml文件重启

#同集群优先的负载均衡
springcloud-user:
  ribbon:
    NFLoadBalancerRuleClassName: com.alibaba.cloud.nacos.ribbon.NacosRule # 负载均衡规则

但是在返回springcloud-order的OrderServiceImpl查看下面这个代码:

RestTemplate发起远程调用的代码存在问题:

1.代码可读性差,编程体验不统一

2.参数复杂URL难以维护

解决:采用Feign解决

Feign:

是一个声明式的http客户端,官方地址:GitHub - OpenFeign/feign: Feign makes writing java http clients easier

1:引入依赖包 spring-cloud-starter-openfeign

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

2:添加注解@EnableFeignClients开启Feign功能

??3:定义远程调用接口,在接口中知名远程调用的【服务名字】、【方法签名】

package com.demon.client;

import com.demon.user.pojo.User;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

/**
 * order调用user服务(代替了 String url="http://springcloud-user/user/"+order.getUserId();)
 * 1.接口上使用@FeignClient(value="被调用服务名")
 * 2.定义被调用接口中的方法(基于被调用的controller编写)
 *  2.1 requestMapping中的路径必须是全路径(controller类上的+方法上的)
 *  2.2 使用PathVariable注解,必须取别名
 */
@FeignClient(value = "springcloud-user")
public interface UserClient {

    /**
     * 调用用户微服中controller的方法
     */
    @GetMapping(value = "/user/{id}")
    public User one(@PathVariable(value = "id") Long id);
}

主要是基于SpringMVC的注解来声明远程调用的信息,比如:

  • 服务名称:user

  • 请求方式:GET

  • 请求路径:/user/{username}

  • 请求参数:String username

  • 返回值类型:User

4:注入接口,执行远程调用(接口)

Feign最佳实现:

方式一(继承):给消费者的FeignClient和提供者的controller定义统一的父接口作为标准。

产生的问题:1.服务耦合? ? ? 2.父接口参数列表中的映射不会被继承

??方式二(抽取):将FeignClient抽取为独立模块,并且把接口有关的POJO、默认的Feign配置都放到这个模块中,提供给所有消费者使用。

1:创建springcloud-api,然后引入feign的starter依赖 springcloud-user依赖

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

        <!--httpClient依赖-->
        <dependency>
            <groupId>io.github.openfeign</groupId>
            <artifactId>feign-httpclient</artifactId>
        </dependency>

        <dependency>
            <groupId>org.example</groupId>
            <artifactId>springcloud-pojo</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>

2:将springcloud-order中编写的UserClient复制到itheima-api项目中
3:在springcloud-order中引入springcloud-api的依赖
4:重启测试

Feign需要注意:

有时候idea会抽风导致(一般复制代码进去出问题的):什么步骤都做了,依赖没错等等,但是在OrderServiceImpl一直导不了包,没有显示UserClient。这时候要查看下图这点,如果不是自己的就删了从新输入,QAQ当初复制我上一份代码,然后自己晕了好久,重启idea发现还是不行,一不小心放上面发现不是我本地写的。

?当定义的FeignClient不在SpringBootApplication的扫描包范围时,这些FeignClient无法使用。

有两种方式解决:

方式一:指定FeignClient所在包

@EnableFeignClients("com.demon.client")

方式二:指定FeignClient字节码

@EnableFeignClients(clients = UserClient.class)

Feign功能:

Feign运行自定义配置来覆盖默认配置,可以修改的配置如下:

类型作用说明
feign.Logger.Level修改日志级别包含四种不同的级别:NONE、BASIC、HEADERS、FULL
feign.codec.Decoder响应结果的解析器http远程调用的结果做解析,例如解析json字符串为java对象
feign.codec.Encoder请求参数编码将请求参数编码,便于通过http请求发送
feign. Contract支持的注解格式将请求参数编码,便于通过http请求发送
feign. Retryer失败重试机制请求失败的重试机制,默认是没有,不过会使用Ribbon的重试

Feign日志配置:

logging:
  level:
    # feign 日志以什么级别监控哪个接口
    com.demon: debug

NONE:默认的,不显示任何日志
BASIC:仅记录请求方法、URL、响应状态码以及执行时间
HEADERS:除了BASIC中定义的信息以外,还有请求和响应的头信息
FULL:除了HEADERS中定义的信息之外,还有请求和响应的正文及元数据

两种方式:

方式一配置文件方式:

feign:
  client:
    config:
      default: #这里用default就是全局配置,如果是写服务名称,则是针对某个微服务的配置
        loggerLevel: BASIC #日志级别
      springcloud-user: #指定服务
        loggerLevel: BASIC #日志级别

方式二代码方式:(QAQ我还没搞懂,可以去百度或者其他地方找一下)

Feign性能优化:

Feign底层的客户端实现:

  • URLConnection:默认实现,不支持连接池

  • Apache HttpClient :支持连接池

  • OKHttp:支持连接池

因此优化Feign的性能主要包括:

  • 使用连接池代替默认的URLConnection

  • 日志级别,最好用basic或none

feign:
  client:
    config:
      default: #这里用default就是全局配置,如果是写服务名称,则是针对某个微服务的配置
        loggerLevel: BASIC #日志级别
      springcloud-user: #指定服务
        loggerLevel: BASIC #日志级别
  httpclient:
    enabled: true #开启feign对HttpClient的支持
    max-connections: 200 #最大的连接数
    max-connections-per-route: 50 #每个路径的最大连接数

nacos权重配置:

实际部署中会出现这样的场景:

服务器设备性能有差异,部分实例所在机器性能较好,另一些较差,我们希望性能好的机器承担更多的用户请求。

但默认情况下NacosRule是同集群内随机挑选,不会考虑机器的性能问题。

因此,Nacos提供了权重配置来控制访问频率,权重越大则访问频率越高。

在nacos控制台,找到user-service的实例列表,点击编辑,即可修改权重:

?点击编辑进入权重修改:

?注意:权重值不能改为0,否则该实例

nacos的环境隔离:

Nacos提供了namespace来实现环境隔离功能。

nacos中可以有多个namespace(环境隔离:test dev pro

namespace下有group、service等

不同namespace之间相互隔离,例如不同namespace的服务互相不可见

?默认情况下,所有service、data、group都在同一个namespace,名为public:

创建

并且修改springcloud-order的yml文件类的

spring:
  cloud:
    nacos:
      server-addr: localhost:8848
      discovery:
        cluster-name: SZ #集群名称
        namespace: devnamespace #命名空间,填ID

最后就是(前面有些图上没说明这环境隔离也有dev这个空间,是我当时配备了的):

?注意:如果没给springcloud-user配置,然后访问地址会出错:

?这里修改一个做参考:

-Dspring.cloud.nacos.discovery.namespace=devnamespace

  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2021-11-22 12:42:59  更:2021-11-22 12:44:54 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 7:18:02-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码