一、概述
zuul和nginx都是一種代理服務器,它們主要的目的都是將客戶端請求轉發到後端的服務器上。但是,它們之間還是有一些區別的。
二、負載均衡
nginx早期就引入了負載均衡的概念,它可以通過一些算法將請求分發到多台服務器上,從而降低單機的壓力,提高反應速度。而zuul的負載均衡是在Netflix的Eureka上實現的,基於Ribbon和RestTemplate實現,在請求到達zuul後,zuul會向Eureka註冊中心查詢可用的服務,並選出一台最優的服務器,將請求轉發到這台服務器上。
此外,在使用zuul實現負載均衡時,我們還需要在服務提供者中配置對應的註解。
@RestController
@RequestMapping("/api")
public class ApiController {
@Autowired
private RestTemplate restTemplate;
@ApiOperation("測試zuul的負載均衡")
@GetMapping("/test")
public String test() {
return "This is from provider " + restTemplate.getForEntity("http://provider/test", String.class).getBody();
}
}
在上述代碼中,我們可以看到,@Autowired註解引入了RestTemplate,這是實現負載均衡的核心組件,而restTemplate.getForEntity()方法中的URL參數中只寫了服務的名稱,比如”provider”,而沒有寫具體的IP地址和端口號,這是因為要使用zuul的負載均衡功能。
三、動態路由
zuul相對於nginx的另一個優勢在於它支持動態路由。在微服務中,如果有新的服務需要加入,或者某個服務需要下線,這個時候我們就需要修改nginx的配置文件並重啟nginx,而這個過程可能比較繁瑣。但是,在zuul中,我們只需要在Eureka上註冊或者下線服務,zuul可以動態地檢測這個變化,並相應地調整路由規則,從而實現自動化的服務發現和動態路由。
以下是一個實現了動態路由功能的zuul網關。
@SpringBootApplication
@EnableZuulProxy
public class GatewayApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayApplication.class, args);
}
@Value("${spring.cloud.config.uri}")
private String url;
@Autowired
private DiscoveryClient discoveryClient;
@EventListener
public void onApplicationEvent(ApplicationReadyEvent event) {
refreshRoute();
}
@Scheduled(fixedRate = 60000)
public void refreshRoute() {
List instances = discoveryClient.getInstances("zuul");
if (!instances.isEmpty()) {
ServiceInstance serviceInstance = instances.get(0);
String path = "/actuator/bus-refresh";
String url = "http://" + serviceInstance.getHost() + ":" + serviceInstance.getPort() + path;
RestTemplate restTemplate = new RestTemplate();
restTemplate.postForEntity(url, null, null);
}
}
}
上述代碼實現了通過定時器定時向Eureka Server查詢可用服務並更新路由規則。我們可以注意到,使用@EnableZuulProxy註解開啟了zuul的代理功能,@Autowired引入了DiscoveryClient,它能查詢Eureka上註冊的服務。在事件監聽方法onApplicationEvent()中,我們在應用啟動時即刻啟動一次路由刷新,以防重啟zuul前Eureka上已有服務改變。在定時任務方法refreshRoute()中,我們通過RestTemplate發送POST請求以觸發路由刷新。
四、動態訪問日誌
nginx在訪問日誌這個方面表現異常優秀,可以實時記錄請求日誌,並支持不同格式的日誌輸出。但是,在zuul這個框架中,要實現動態日誌需要藉助第三方工具。最常見的做法是結合Logstash和Elasticsearch,這樣我們就可以把所有的請求日誌都存儲到Elasticsearch上,並通過Kibana進行可視化展示和分析。
以下是一個實現動態日誌功能的zuul網關。
#zuul配置文件
zuul:
routes:
user:
path: /user/**
url: http://localhost:8080
product:
path: /product/**
url: http://localhost:8081
request:
occlude-headers:
#Logback日誌配置文件
%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
./logs/api-apm.log
true
%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
UTF-8
./logs/%d{yyyy-MM-dd}/api-apm-%d{yyyy-MM-dd_HH}.log
7
#Spring Boot啟動類
@SpringBootApplication(scanBasePackages = "com.example")
@EnableZuulProxy
public class GatewayApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayApplication.class, args);
}
@Bean
public ConfigurableServletWebServerFactory configurableServletWebServerFactory() {
TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
factory.addConnectorCustomizers((connector -> {
AbstractHttp11Protocol protocol = (AbstractHttp11Protocol) connector.getProtocolHandler();
protocol.setCompression("on");
protocol.setCompressionMinSize(1024);
String[] mimeTypes = protocol.getCompressableMimeTypes();
List mimeList = new ArrayList(Arrays.asList(mimeTypes));
mimeList.add("application/json");
protocol.setCompressableMimeTypes(mimeList.toArray(new String[0]));
}));
return factory;
}
@Bean
public PatternLayoutEncoder encoder() {
PatternLayoutEncoder encoder = new PatternLayoutEncoder();
encoder.setPattern("%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n");
encoder.setCharset(Charset.forName("UTF-8"));
return encoder;
}
@Bean
public LoggerFilter loggerFilter() {
LoggerFilter loggerFilter = new LoggerFilter();
loggerFilter.setAppenders("api-apm");
loggerFilter.setAdditive(false);
return loggerFilter;
}
@Bean
public Logger logger() {
Logger logger = (Logger) LoggerFactory.getLogger("com.netflix.zuul.monitoring.MonitoringHelper");
logger.setLevel(Level.ERROR);
return logger;
}
}
在上述代碼中,我們使用Logback配置了日誌相關信息,通過@EnableZuulProxy註解啟用了zuul的服務代理功能。在@Bean註解的方法中,我們還配置了Tomcat的壓縮策略和編碼信息,以及zuul的日誌過濾器和日誌級別。
總之,zuul和nginx二者的優劣勢都很明顯,它們的選擇要根據實際使用場景來判斷。在微服務架構中,通常會使用zuul作為服務網關,以實現動態路由、負載均衡等功能。但是,在靜態網頁服務器、WEB路由、反向代理等方面,nginx的性能和穩定性都是值得稱讚的。
原創文章,作者:NKOAN,如若轉載,請註明出處:https://www.506064.com/zh-hk/n/371067.html