1.nacos的四种负载均衡写法
1.1 基本知识点
1.1.1.@LoadBalanced注解
当使用RestTemplate进行远程服务调用时,假如需要负载均衡,可以在RestTemplate对象构建时,使用@LoadBalanced,对构建RestTemplate的方法进行修饰。修饰的同时也是对于负载均衡中的一些方法进行了封装;封装的代码大致如下:
ServiceInstance choose =loadBalancerClient.choose(serverId);
String ip=choose.getHost();
int port =choose.getPort();
//String url= "http://"+ip+":"+port+"/provider/echo/"+msg;
String url =String.format("http://%s:%s/provider/echo/%s",ip,port,appName);
1.1.2.Ribbon负载均衡策略
基于Ribbon方式的负载均衡,Netflix默认提供了七种负载均衡策略,对于SpringCloud Alibaba解决方案中又提供了NacosRule策略,默认的负载均衡策略是轮训策略。
一般常用轮训,当系统提供的负载均衡策略不能满足我们需求时,我们还可以基于IRule接口自己定义策略.可用ctrl+F6快速获取.
1.1.3.Feign
Feign 是一种声明式Web服务客户端,底层封装了对Rest技术的应用,通过Feign可以简化服务消费方对远程服务提供方法的调用实现。如图所示:
Feign 最早是由 Netflix 公司进行维护的,后来 Netflix 不再对其进行维护,最终 Feign 由一些社区进行维护,更名为 OpenFeign。
1.2负载均衡四种写法间的关系
1.2.1.手写式和loadBalancerClient
Resttemplate优势:单个较为方便,
Resttemplate+loadBalancerClient优势:
1.2.2.注解@loadBalaced和loadBalancerClient
区别:注解式将其中一部分封装给了拦截器,相对低效一些
1.2.3.注解@loadBalaced和loadBalancerClient
区别:将网页服务进行封装,交给openFeign管理,可以远程调用
1.2.4 总结
服务方在调用提供方时,有四种方式可供选择,而架构的任务在于根据不同的业务场景选择合适的方式,以实现功能调用.
1.2.5 fegin接口与注解配置
注解:
@EnableFeignClients
@SpringBootApplication
public class ConsumerApplication {…}
接口:
@FeignClient(name="sca-provider")//sca-provider为服务提供者名称
interface RemoteProviderService{
@GetMapping("/provider/echo/{string}")//前提是远端需要有这个服务
public String echoMessage(@PathVariable("string") String string);
}
配置优化:多接口时--引入contextId,作为远程调用服务的唯一标识
@FeignClient(name="sca-provider",contextId="remoteProviderService")//sca-provider为服务提供者名称
interface RemoteProviderService{
@GetMapping("/provider/echo/{string}")//前提是远端需要有这个服务
public String echoMessage(@PathVariable("string") String string);
}
调用超时的容错方案——优化用户体验
@Component
public class ProviderFallbackFactory
implements FallbackFactory<RemoteProviderService> {
//当正常远程调用的服务不可用时,系统可以调用此方法进行请求处理
// @Override在jdk1.7之前的版本并不可用,在1.7接口重新定义后,才可以使用@Override
@Override
public RemoteProviderService create(Throwable throwable) {
return new RemoteProviderService() {
@Override
public String echoMsg(String msg) {
//...通知运维人员(发短信,发邮件,电话)...
return "服务维护中,稍等片刻再访问";
}
};
}
说明:写入工厂配置时,需要加入相应的配置机制
#接口中加入反射获取失败返回值
@FeignClient(name = "sca-provider", contextId = "remoteProviderService",
fallbackFactory = ProviderFallbackFactory.class)//sca-provider为nacos中的服务名
public interface RemoteProviderService {
@GetMapping("/provider/echo/{msg}")
public String echoMsg(@PathVariable String msg);
}
注意在启动feign方式调用时增加服务中断处理机制.
feign:
hystrix:
enabled: true #默认值为false
最后优化的效果如图:
2.运行过程中常见错误分析
2.1 Application Failed to Start
界面如下:
解决方案:找到类中中不能执行的原因,修改后重启启动类
2.2依赖注入失败(Bean Not Found)
界面如图:
解决方案:检查依赖以及注解,使之在依赖接口与之匹配
2.3请求映射路径重复定义
解决方案:检查@GetMapping请求的一些部分是否重复,重复则进行相应的修改
2.4Feign远程调用超时
解决方案:确定程序运行时间,检查是否超时
3.相关知识点总结
3.1手写tomcat
public class Tomcat {
public static void main(String[] args) throws IOException {
//java服务的创建
System.out.println("start server ...");
//java中网络编程中的服务对象类型为serversocket
//构建服务,并在9999端口访问
ServerSocket server=new ServerSocket(9999);
//监听端口,等待服务连接
while(true){
Socket socket=server.accept();//阻塞方法
System.out.println("hello client"+socket);
//获取向客户端输出数据的流对象
OutputStream out=socket.getOutputStream();
//向客户端写数据
out.write("hello".getBytes());//这种方式浏览器不响应
String content="HTTP/1.1 200\r\n"+//响应行
"Content-Type:text/html;char"//响应头
+"\r\n"+//空行
"<h1>client</h1>";//数据
out.write(content.getBytes());
socket.close();
}
}
}
3.2 延时任务的代码
public class TimerTests {
public static void main(String[] args) {
//通过timer对象可以启动一个定时任务
Timer timer=new Timer();
//基于timer对象启动并执行任务
timer.schedule(new TimerTask() {
@Override
public void run() {
System.out.println(System.currentTimeMillis());
}
},1000,1000);
}
}
4.面试相关知识点
4.1 Feign 调用过程分析(了解)
Feign应用过程分析(底层逻辑先了解):
1)通过 @EnableFeignCleints 注解告诉springcloud,启动 Feign Starter 组件。
2) Feign Starter 在项目启动过程中注册全局配置,扫描包下所由@FeignClient注解描述的接口,然后由系统底层创建接口实现类(JDK代理类),并构建类的对象,然后交给spring管理(注册 IOC 容器)。
3) 接口被调用时被动态代理类逻辑拦截,将 @FeignClient 请求信息通过编码器生成 Request对象,基于此对象进行远程过程调用。
4) 请求对象经Ribbon进行负载均衡,挑选出一个健康的 Server 实例(instance)。
5) 通过 Client 携带 Request 调用远端服务返回请求响应。
6) 通过解码器生成 Response 返回客户端,将信息流解析成为接口返回数据。
4.2 服务调用实例
4.3 Bug分析
404错误
说明:404访问的资源不存在,检查输入网址是否匹配
405错误
500错误
例如,打开后台,假如出现了如下问题,就是你远程调用的服务url应该是写错了
例如:假如你的Consumer服务调用Provider服务,但是Provider服务没有启动就会出现如下问题:
4.4 面试题总结
- 为什么使用feign?(基于Feign可以更加友好的实现服务调用,简化服务消费方对服务提供方方法的调用)。
- @FeignClient注解的作用是什么?(告诉Feign Starter,在项目启动时,为此注解描述的接口创建实现类-代理类)
- Feign方式的调用,底层负载均衡是如何实现的?(Ribbon)
- @EnableFeignCleints 注解的作用是什么?(描述配置类,例如启动类)