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-orderprofiles:active: devdatasource:driverClassName: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/springcloud?characterEncoding=UTF8&&serverTimezone=Asia/Shanghaiusername: rootpassword: 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 {@Autowiredprivate 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 {@Autowiredprivate OrderDao orderDao;@Autowiredprivate RestTemplate restTemplate;/*** 根据id查询* @param id* @return*/@Overridepublic 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);}//远程调用@Beanpublic 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-userprofiles:active: devdatasource:driverClassName: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/springcloud?characterEncoding=UTF8&&serverTimezone=Asia/Shanghaiusername: rootpassword: 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 {@Autowiredprivate 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 {@Autowiredprivate UserDao userDao;/*** 根据id查询用户信息* @param id* @return*/@Overridepublic 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:8848discovery: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规则的客户端也会将其忽略。并发连接数的上限,可以由客户端的 |
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:8848discovery:cluster-name: SZ #集群名称namespace: devnamespace #命名空间,填ID
最后就是(前面有些图上没说明这环境隔离也有dev这个空间,是我当时配备了的):
注意:如果没给springcloud-user配置,然后访问地址会出错:
这里修改一个做参考:
-Dspring.cloud.nacos.discovery.namespace=devnamespace
Springcloud、Nacos 服务注册、负载均衡Ribbon、http客户端Feign相关推荐
- 客户端负载均衡与服务端负载均衡
原文:https://segmentfault.com/a/1190000011081111 通过Nginx负载均衡服务器发送到不同的上游服务器去处理,这种负载均衡就是一种典型的服务端负载均衡,那么客 ...
- 跟着狂神学SpringCloud(Rest环境搭建+Eureka服务注册与发现+ribbon+Feign负载均衡+Hystrix+服务熔断+Zuul路由网关+SpringCloud config分布)
跟着狂神学SpringCloud SpringCloud 回顾之前的知识- JavaSE 数据库 前端 Servlet Http Mybatis Spring SpringMVC SpringBoot ...
- 微服务2——服务的注册,调用(Nacos服务注册中心+服务调用+调用负载均衡)sca-comsumersca-provider
一.Nacos的安装和构建 以及启动 其官网地址如下: Nacos官网 1.安装前提: 第一:确保你电脑已配置JAVA_HOME环境变量(Nacos启动时需要),例如: 第二:确保你的MySQL版本 ...
- SpringCloud微服务(四)——Nacos服务注册和配置中心
SpringCloud Alibaba Nacos服务注册和配置中心 Spring Cloud Netflix Projects Entering Mainterance Mode SpringClo ...
- SpringCloud Alibaba实战--第二篇:NacosⅠ服务注册和配置中心
系列文章目录 微服务新王SpringCloudAlibaba 文章目录 系列文章目录 前言 一.Nacos是什么?能干啥? 二.Nacos下载及安装 1. 下载 2. 安装并运行 3. 对比Eurek ...
- SpringCloud Alibaba微服务实战(二) - Nacos服务注册与restTemplate消费
说在前面 基础环境搭建,理论,请看上一篇,在这就不扯理论了,直接上代码. 项目结构 代码实现 第一步:在父pom的项目中引入dependencyManagement 在引入父pom之前咱们先来回顾下d ...
- SpringCloud学习之(十八)SpringCloud Alibaba Nacos服务注册和配置中心
文章目录 (十八)SpringCloud Alibaba Nacos服务注册和配置中心 1.Nacos简介 1.1 为什么叫Nacos 1.2 Nacos是什么 1.3 Nacos能干嘛 1.4 Na ...
- SpringCloud Alibaba Nacos服务注册和配置中心-微服务(二十六)
Nacos作为服务注册中心演示 官网文档 基于Nacos的服务提供者 新建Module cloudalibaba-provider-payment9001 POM 父POM <?xml vers ...
- SpringCloud学习笔记(6)----Spring Cloud Netflix之负载均衡-Ribbon的使用
1. 什么是负载均衡? 负载均衡,就是分发请求流量到不同的服务器. 负载均衡一般分为两种 1. 服务器端负载均衡(nginx) 2. 客户端负载均衡(Ribbon) 2. 服务提供者(spring-c ...
最新文章
- I - Ant Trip (无向图欧拉回路+并查集),判断
- 理解Go Interface
- 网线主管(信息学奥赛一本通-T1242)
- sharepoint中使用xslt构建Spotlight(焦点图效果)
- 在ASP.NET WebAPI 中使用缓存【Redis】
- crontab命令 :Linux下定时执行脚本
- 合理使用“搜索引擎和工具书”,提升“速度和加速度”
- 沟通CTBS助×××系统巨头解决南北互通问题
- 「成人学习」掘金者,从教育走向生活方式
- 1000瓶药水,其中1瓶有毒,最少要几只老鼠?
- 计算机学院表白情书,大学各专业的表白情书!啊,我的少女心要炸了…
- Bootstrap网站模板
- pymysql无法访问本地计算机,使用Python和odo模块在mysql上加载csv时出错
- win10控制面板快捷键_你没玩过的全新版本 Win10这些操作你知多少
- 【STM32】 电解电容
- plc模拟量与通信控制应用实践_电气控制基础+PLC编程入门+工程应用实例
- 使用fiddler实现苹果ios手机抓包--的补充
- android7.1自带壁纸,RK3399 Android7.1 修改壁纸
- 时间格式转换2021-08-17T16:00:00.000Z存入数据库问题
- 2.面向性能的设计与开发