1.Eureka
要是user-service服务有多个,order-service该怎么调用?
这就需要用到 注册中心 了 。
1.1 搭建Eureka服务
1. pom引入依赖
<dependencies> <!--eureka服务端--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency> </dependencies>2.yaml增加配置
eureka: client: service-url: # eureka的地址信息 defaultZone: http://127.0.0.1:10086/eureka3.启动类加注解
@EnableEurekaServer @SpringBootApplication public class EurekaApplication { public static void main(String[] args) { SpringApplication.run(EurekaApplication.class, args); } }
1.2 服务注册
将user-service服务注册到Eukeka。
1.pom引依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>2.yml加配置
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:10086/eureka
然后创建多个user-service实例
1.3 服务发现
将order-service的逻辑修改:向eureka-server拉取user-service的信息,实现服务发现。
1.pom引依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>2.yml加配置
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:10086/eureka
@Bean
@LoadBalanced
public RestTemplate restTemplate() { return new RestTemplate(); }
// 2.1.url路径
//String url = "http://localhost:8081/user/" + order.getUserId();
String url = "http://userservice/user/" + order.getUserId();
// 2.2.发送http请求,实现远程调用
User user = restTemplate.getForObject(url, User.class);
上面我们说到了@LoadBlanced 负载均衡。
SpringCloud底层利用了一个Ribbon组件来实现。
1.4Ribbon
为什么我们可以通过 String url = "http://userservice/user/" + order.getUserId();
就能获得userservice的ip和端口呢?
源码中可以发现是 LoadBlanceInterceptor ,会对RestTemplate的请求进行拦截,然后从Eureka获取服务列表,然后利用负载均衡算法获取ip和端口。
1.4.1LoadBalancerIntercepor
request.getURI()
:获取请求uri,本例中就是 http://user-service/user/8
originalUri.getHost()
:获取uri路径的主机名,其实就是服务id,user-service
this.loadBalancer.execute()
:处理服务id,和用户请求。
这里的this.loadBalancer
是LoadBalancerClient
类型,我们继续跟入。
1.4.2LoadBalancerClient
getLoadBalancer(serviceId):根据服务id获取ILoadBalancer,而ILoadBalancer会拿着服务id去eureka中获取服务列表并保存起来。
getServer(loadBalancer):利用内置的负载均衡算法,从服务列表中选择一个。本例中,可以看到获取了8082端口的服务
1.4.3负载均衡策略IRule
RibbonLoadBalancerClient public <T> T execute(String serviceId, LoadBalancerRequest<T> request, Object hint) throws IOException { ILoadBalancer loadBalancer = this.getLoadBalancer(serviceId); Server server = this.getServer(loadBalancer, hint); ......protected Server getServer(ILoadBalancer loadBalancer, Object hint) { return loadBalancer == null ? null : loadBalancer.chooseServer(hint != null ? hint : "default"); }BaseLoadBalancer protected IRule rule; private static final IRule DEFAULT_RULE = new RoundRobinRule(); public Server chooseServer(Object key) { ...... if (this.rule == null) { return null; } else { try { return this.rule.choose(key); } catch (Exception var3) { logger.warn("LoadBalancer [{}]: Error choosing server for key {}", new Object[]{this.name, key, var3}); return null; } } }
IRule实现类
内置负载均衡规则类 | 规则描述 |
---|---|
RoundRobinRule | 简单轮询服务列表来选择服务器。它是Ribbon默认的负载均衡规则。 |
AvailabilityFilteringRule | 对以下两种服务器进行忽略: (1)在默认情况下,这台服务器如果3次连接失败,这台服务器就会被设置为“短路”状态。短路状态将持续30秒,如果再次连接失败,短路的持续时间就会几何级地增加。 (2)并发数过高的服务器。如果一个服务器的并发连接数过高,配置了AvailabilityFilteringRule规则的客户端也会将其忽略。并发连接数的上限,可以由客户端的<clientName>.<clientConfigNameSpace>.ActiveConnectionsLimit属性进行配置。 |
WeightedResponseTimeRule | 为每一个服务器赋予一个权重值。服务器响应时间越长,这个服务器的权重就越小。这个规则会随机选择服务器,这个权重值会影响服务器的选择。 |
ZoneAvoidanceRule | 以区域可用的服务器为基础进行服务器的选择。使用Zone对服务器进行分类,这个Zone可以理解为一个机房、一个机架等。而后再对Zone内的多个服务做轮询。 |
BestAvailableRule | 忽略那些短路的服务器,并选择并发数较低的服务器。 |
RandomRule | 随机选择一个可用的服务器。 |
RetryRule | 重试机制的选择逻辑 |
默认是ZoneAvoidanceRule,一种轮询机制。
1.4.4自定义负载均衡策略
1.yml
userservice: # 给某个微服务配置负载均衡规则,这里是userservice服务
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule # 负载均衡规则2.代码
@Bean
public IRule randomRule(){
return new RandomRule();
}
2.Nacos
Nacos是SpringCloudAlibaba的组件。和Eureka没啥太大区别,Nacos能支持一些比较复杂的集群部署。
2.1 服务注册到nacos
父pom(cloud-demo )
<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>子pom(user-service和order-service )
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>yml 配nacos地址
spring:
cloud:
nacos:
server-addr: localhost:8848
2.2 nacos集群
一个服务可以有多个实例