微服務網關
Spring Cloud
技術棧採用Zuul
作爲微服務網關,在整個架構中,Zuul
是所有其他微服務的統一入口,對所有請求進行路由。
管理後臺微服務網關
後臺網關微服務創建Module(省略)
引入依賴
<?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>tensquare_parent</artifactId>
<groupId>com.tensquare</groupId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>tensquare_manager</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
</dependencies>
</project>
application.yml
server:
port: 9011
spring:
application:
name: tensquare‐manager #指定服務名
eureka:
instance:
prefer‐ip‐address: true
client:
service-url:
defaultZone: http://127.0.0.1:6868/eureka/
zuul:
routes:
tensquare‐gathering: #活動
path: /gathering/**
serviceId: tensquare‐gathering
tensquare‐article: #文章
path: /article/**
serviceId: tensquare‐article
tensquare‐base: #基礎
path: /base/**
serviceId: tensquare‐base
tensquare‐friend: #交友
path: /friend/**
serviceId: tensquare‐friend
tensquare‐qa: #問答
path: /qa/**
serviceId: tensquare‐qa
tensquare‐recruit: #招聘
path: /recruit/**
serviceId: tensquare‐recruit
tensquare‐spit: #吐槽
path: /spit/**
serviceId: tensquare‐spit
tensquare‐user: #用戶
path: /user/**
serviceId: tensquare‐user
啓動類
package com.tensquare.manager;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
@SpringBootApplication
@EnableZuulProxy
public class ManagerApplication {
public static void main(String[] args) {
SpringApplication.run(ManagerApplication.class, args);
}
}
前臺微服務網關
前臺網關微服務創建Module(省略)
引入依賴
<?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>tensquare_parent</artifactId>
<groupId>com.tensquare</groupId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>tensquare_web</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
</dependencies>
</project>
application.yml
server:
port: 9012
spring:
application:
name: tensquare‐web #指定服務名
eureka:
instance:
prefer‐ip‐address: true
client:
service-url:
defaultZone: http://127.0.0.1:6868/eureka/
zuul:
routes:
tensquare‐gathering: #活動
path: /gathering/**
serviceId: tensquare‐gathering
tensquare‐article: #文章
path: /article/**
serviceId: tensquare‐article
tensquare‐base: #基礎
path: /base/**
serviceId: tensquare‐base
tensquare‐friend: #交友
path: /friend/**
serviceId: tensquare‐friend
tensquare‐qa: #問答
path: /qa/**
serviceId: tensquare‐qa
tensquare‐recruit: #招聘
path: /recruit/**
serviceId: tensquare‐recruit
tensquare‐spit: #吐槽
path: /spit/**
serviceId: tensquare‐spit
tensquare‐user: #用戶
path: /user/**
serviceId: tensquare‐user
tensquare‐search: #用戶
path: /user/**
serviceId: tensquare‐search
啓動類
package com.tensquare.web;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
@EnableZuulProxy
@SpringBootApplication
public class WebApplication {
public static void main(String[] args) {
SpringApplication.run(WebApplication.class, args);
}
}
前臺網關轉發Token
編寫Zuul
過濾器實現Token
轉發
package com.tensquare.web.filter;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
@Component
public class WebFilter extends ZuulFilter {
@Override
public String filterType() {
return "pre";
}
@Override
public int filterOrder() {
return 0;
}
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() throws ZuulException {
System.out.println("zuul過濾器...");
//向header中添加鑑權令牌
RequestContext requestContext = RequestContext.getCurrentContext();
//獲取header
HttpServletRequest request = requestContext.getRequest();
String authorization = request.getHeader("Authorization");
if (authorization != null) {
requestContext.addZuulRequestHeader("Authorization", authorization);
}
return null;
}
}
我的另一篇文章有詳細介紹Zuul
,文章鏈接:Zuul網關詳解
後臺網關轉發Token
引入依賴
<dependency>
<groupId>com.tensquare</groupId>
<artifactId>tensquare_common</artifactId>
<version>${tensquare.version}</version>
</dependency>
配置Jwt相關常量
配置在application.yml
即可
jwt:
config:
key: imxushuai
配置Bean
配置在ManagerApplication
即可
@Bean
public JwtUtil jwtUtil(){
return new JwtUtil();
}
配置Zuul過濾器
package com.tensquare.manager.filter;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import util.JwtUtil;
import javax.servlet.http.HttpServletRequest;
@Slf4j
@Component
public class ManagerFilter extends ZuulFilter {
@Autowired
private JwtUtil jwtUtil;
@Override
public String filterType() {
return "pre";
}
@Override
public int filterOrder() {
return 0;
}
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() throws ZuulException {
RequestContext requestContext = RequestContext.getCurrentContext();
HttpServletRequest request = requestContext.getRequest();
if (request.getMethod().equals("OPTIONS")) {// 跳過預請求
return null;
}
String url = request.getRequestURL().toString();
if (url.indexOf("/admin/login") > 0) {// 放行登錄
log.info("登陸頁面: [{}]", url);
return null;
}
String authHeader = request.getHeader("Authorization");//獲取頭信息
if (authHeader != null && authHeader.startsWith("Bearer ")) {
String token = authHeader.substring(7);
Claims claims = jwtUtil.parseJWT(token);
if (claims != null) {
if ("admin".equals(claims.get("roles"))) {
requestContext.addZuulRequestHeader("Authorization", authHeader);
log.info("Token驗證通過,頭信息 [{}]", authHeader);
return null;
}
}
}
requestContext.setSendZuulResponse(false);//終止運行
requestContext.setResponseStatusCode(401);//http狀態碼
requestContext.setResponseBody("無權訪問");
requestContext.getResponse().setContentType("text/html;charset=UTF‐8");
return null;
}
}
配置中心
Spring Cloud Config
在分佈式系統中,由於服務數量巨多,爲了方便服務配置文件統一管理,實時更新,所 以需要分佈式配置中心組件。在Spring Cloud
中,有分佈式配置中心組件spring cloud config
,它支持配置服務放在配置服務的內存中(即本地),也支持放在遠程Git倉庫 中。在spring cloud config
組件中,分兩個角色,一是config server
,二是config client
。
Config Server
是一個可橫向擴展、集中式的配置服務器,它用於集中管理應用程序各個環境下的配置,默認使用Git存儲配置文件內容,也可以使用SVN存儲,或者是本地文件存儲。- Config Client是Config Server的客戶端,用於操作存儲在Config Server中的配置內容。微服務在啓動時會請求Config Server獲取配置文件的內容,請求到後再啓動容器。
創建Git Repository(省略)
在Git
服務器上創建用於存放配置文件的倉庫。創建好後,將所有的配置文件上傳至Git
服務器。
配置中心微服務
創建配置中心微服務Module(省略)
引入依賴
<?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>tensquare_parent</artifactId>
<groupId>com.tensquare</groupId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>tensquare_config</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
</dependencies>
</project>
application.yml
spring:
application:
name: tensquare‐config
cloud:
config:
server:
git:
uri: https://github.com/imxushuai/tensquare_config.git
server:
port: 12000
啓動類
package com.tensquare.config;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.config.server.EnableConfigServer;
@EnableConfigServer
@SpringBootApplication
public class ConfigApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigApplication.class, args);
}
}
運行測試
成功拉取到配置文件!
Config Client配置
在需要從配置中心拉取配置的微服務中重複一下操作:
引入依賴
引入Spring Cloud Config
依賴
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
新增配置文件
在resources
目錄中新增配置文件:bootstrap.yml
spring:
cloud:
config:
# 應用名
name: base
# 環境
profile: dev
# 分支
label: master
# 配置中心地址
uri: http://127.0.0.1:12000
配置完畢後,即可刪除配置文件
application.yml
,測試是否能正常啓動。
Spring Cloud Bus更新配置文件
使用Spring Cloud Bus
實現實時更新配置文件,當Git
庫配置文件發送變動時,熱更新相應微服務的配置文件。
原理參考:?點擊我?
修改Config Server端
引入依賴
在tensquare_config
中引入依賴
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-bus</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream-binder-rabbit</artifactId>
</dependency>
application.yml新增配置
新增後的application.yml
配置文件內容如下:
spring:
application:
name: tensquare‐config
cloud:
config:
server:
git:
uri: https://github.com/imxushuai/tensquare_config.git
rabbitmq:
host: 192.168.136.104
server:
port: 12000
management:
endpoints:
web:
exposure:
include: bus-refresh
修改Config Client端
在需要從配置中心拉取配置的微服務中重複一下操作:
引入依賴
引入Spring Cloud Bus
依賴
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-bus</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream-binder-rabbit</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
application.yml新增配置
注意:這裏新增的配置需要在Git
服務器中的每個配置文件中加入下面這段配置。
spring:
rabbitmq:
host: 192.168.136.104
熱更新配置文件說明
這樣配置文件熱更新的基本上算是完成了,以後在每一次配置文件有更新的時候,我們只需要調用一個接口,就可以完成配置文件的熱更新了。
接口:http://127.0.0.1:12000/actuator/bus-refresh
更新私有配置項
Spring Cloud Bus
更新只會更新框架已有的配置項,而不會更新類似Jwt
等用戶自定義的配置項。
需要更新自定義的配置項,需要在要更新配置項的Bean
上使用@RefreshScope
註解,這樣就可以完成配置的更新。