微服務-網關服務

来源:https://www.cnblogs.com/xiangkejin/archive/2018/07/26/9374871.html
-Advertisement-
Play Games

網關服務的作用: 身份認證、路由服務、為前端服務的後端—數據聚合 身份認證 如果我們的微服務和終端通信,勢必要考慮身份認證,如果我們的微服務都與每個終端用戶打交道,那麼這些代碼就需要拷貝多份, 並且植入到每個微服務業務代碼中,這就造成業務代碼和身份認證代碼耦合,降低代碼的復用性。 路由服務 由運維人 ...


網關服務的作用:

身份認證、路由服務、為前端服務的後端—數據聚合

  • 身份認證
如果我們的微服務和終端通信,勢必要考慮身份認證,如果我們的微服務都與每個終端用戶打交道,那麼這些代碼就需要拷貝多份, 並且植入到每個微服務業務代碼中,這就造成業務代碼和身份認證代碼耦合,降低代碼的復用性。
  • 路由服務

由運維人員手動維護路由規則和服務實例列表是非常費工夫的且容易出錯。

  • 為前端服務的後端

  比如將多個服務的數據聚合在一起返回給前端

為瞭解決上面的架構問題,API網關的概念應運而生,它的定義類似於面向對象設計模式中的Facade模式,它的存在就像是整個微服務架構系統的門面一樣,所有的外部客戶端訪問都需要經過它來進行調度和過濾。

由它來實現請求路由、負載均衡、校驗過濾等功能,以及與服務治理框架的結合,請求轉發的熔斷機制、服務的聚合等。

SpringCloud Zuul組件能非常好的解決這些問題,在服務路由的時候,我們看它如何方便的解決了這個問題。

創建一個API服務網關工程

簡單使用:

1、添加依賴

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-zuul</artifactId>
</dependency>

2、配置文件

zuul.routes.api-a-url.path=/hello/**
zuul.routes.api-a-url.url=http://localhost:9000/

所有符合/hello/**規則的訪問都將被路由轉發到http://localhost:9000/地址上,其中api-a-url是路由的名字,可以任意定義。

3、啟動類

@SpringBootApplication
@EnableZuulProxy
public class GatewayServiceZuulApplication {

    public static void main(String[] args) {
        SpringApplication.run(GatewayServiceZuulApplication.class, args);
    }
}

啟動類添加@EnableZuulProxy,支持網關路由。

 面向服務的路由

 實際上上面那種方式同樣需要運維人員花費大量的時間來維護各個路由path和url的關係。為瞭解決這個問題,Zuul實現了於Eureka的無縫結合,我們可以讓路喲的path不是映射具體的url,而是讓它映射到某個具體的服務,而

具體的url則交給Eureka的服務發現機制去自動維護。

1、添加依賴

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>

增加spring-cloud-starter-eureka包,添加對eureka的支持。

2、配置文件

配置修改為:

spring.application.name=gateway-service-zuul
server.port=8888

zuul.routes.api-a.path=/producer/**
zuul.routes.api-a.serviceId=spring-cloud-producer

eureka.client.serviceUrl.defaultZone=http://localhost:8000/eureka/

 

 

項目採取方案

由於項目採取的並不是前後端分離的架構,所有的請求到達API 服務網關,zuul進行路由,可是並不能將各服務返回頁面的進行聚合再返回給瀏覽器。

而是採用了一種次等的策略,將所有的靜態資源放在API網關中,API網關接收請求,調用各個服務介面,將返回數據的數據進行聚合,然後給API網關的頁面進行渲染。

這裡身份認證JWT可以單獨作為一個認證服務被調用。基於JWT的token身份認證方案

以一個登陸請求為例:

API網關的UserController中的方法:

  @RequestMapping(value="/accounts/signin",method={RequestMethod.POST,RequestMethod.GET})
  public String loginSubmit(HttpServletRequest req){
    String username = req.getParameter("username");
    String password = req.getParameter("password");
    if (username == null || password == null) {
      req.setAttribute("target", req.getParameter("target"));
      return "/user/accounts/signin";
    }
    User  user =  accountService.auth(username, password);
    if (user == null) {
      return "redirect:/accounts/signin?" + "username=" + username + "&" + ResultMsg.errorMsg("用戶名或密碼錯誤").asUrlParams();
    }else {
      UserContext.setUser(user);
      return  StringUtils.isNotBlank(req.getParameter("target")) ? "redirect:" + req.getParameter("target") : "redirect:/index";
    }
  }
  }

 API網關的UserService中的方法

 public User auth(String username, String password) {
    if (StringUtils.isBlank(username) || StringUtils.isBlank(password)) {
       return null;
    }
    User user = new User();
    user.setEmail(username);
    user.setPasswd(password);
    try {
      user = userDao.authUser(user);
    } catch (Exception e) {
      return null;
    }
    return user;
  }

 API網關的UserDao中的方法

  @HystrixCommand
  public User authUser(User user) {
    String url = "http://" + userServiceName + "/user/auth";
    ResponseEntity<RestResponse<User>> responseEntity =  rest.post(url, user, new ParameterizedTypeReference<RestResponse<User>>() {});
    RestResponse<User> response = responseEntity.getBody();
    if (response.getCode() == 0) {
      return response.getResult();
   }{
      throw new IllegalStateException("Can not add user");
   }
  }

 這裡的方法添加了@HystrixCommand用於進行服務的熔斷,這個後面會介紹它。

經過RestTemplate攔截請求,轉發到某個服務實例上。註意它返回的是ResponseEntity<T>泛型對象,其中T是由ParameterizedTypeReference<T>中的T指定。

 responseEntity.getBody()就能獲取到實際返回的對象。

User-Service服務UserController中的auth方法:

@RequestMapping("auth")
  public RestResponse<User> auth(@RequestBody User user){
        User finalUser = userService.auth(user.getEmail(),user.getPasswd());
        return RestResponse.success(finalUser);
}

 User-Service服務UserService中的auth方法:

  /**
   * 校驗用戶名密碼、生成token並返回用戶對象
   * @param email
   * @param passwd
   * @return
   */
  public User auth(String email, String passwd) {
    if (StringUtils.isBlank(email) || StringUtils.isBlank(passwd)) {
      throw new UserException(Type.USER_AUTH_FAIL,"User Auth Fail");
    }
    User user = new User();
    user.setEmail(email);
    user.setPasswd(HashUtils.encryPassword(passwd));
    //user.setEnable(1);
    List<User> list =  getUserByQuery(user);
    if (!list.isEmpty()) {
       User retUser = list.get(0);
       onLogin(retUser);
       return retUser;
    }
    throw new UserException(Type.USER_AUTH_FAIL,"User Auth Fail");
  }

  //生成token的操作
  private void onLogin(User user) {
      //最後一個是時間戳
    String token =  JwtHelper.genToken(ImmutableMap.of("email", user.getEmail(), "name", user.getName(),"ts",Instant.now().getEpochSecond()+""));
    renewToken(token,user.getEmail());
    user.setToken(token);
  }

  //重新設置緩存過期時間
  private String renewToken(String token, String email) {
    redisTemplate.opsForValue().set(email, token);
    redisTemplate.expire(email, 30, TimeUnit.MINUTES);
    return token; 
  }

 

 

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • #include #include //提供malloc()原型 /* 線性表需要的方法: 1、 List MakeEmpty():初始化一個空線性表 2、 EementType FindKey(int K, List L):根據位序K,返回相應元素 3、 int Find(ElementType ... ...
  • 前言 這次分析信號量Semaphore,為什麼稱之為信號量呢?是因為它可以控制同時訪問某個資源的操作數量或是同時執行某個指定操作的數量。就好比它像一個租賃汽車的公司,租賃公司的汽車的數量是固定的,用完需要歸還,用之前需要去租借(acquire 前提是還有可用的汽車),如果汽車都被租出去了,那隻能等到 ...
  • 首先感謝授課XXX老師。 1.什麼是線程安全問題 當多個線程共用同一個全局變數,做寫的操作時候,可能會受到其他線程的干擾,導致數據出現問題,這種現象就叫做線程安全問題。做讀的時候不會產生線程安全問題。 什麼安全:多個線程同時共用一個全局變數,做寫操作的時候會發生線程安全。 多個線程共用同一個局部變數 ...
  • 最近在做一個項目的時候,需要使用golang來調用操作系統中的命令行,來執行shell命令或者直接調用第三方程式,這其中自然就用到了golang自帶的exec.Command. 但是如果直接使用原生exec.Command會造成大量的重覆代碼,網上搜了一圈又沒有找到對exec.Command相應的封 ...
  • 本文為CUBA-Platform簡介 ,一個結合了可靠架構、企業級應用程式“必備”功能和應用程式快速開發工具的開源框架。 ...
  • <! done   簡單的‘Hello World!’   Python命令行 假設你已經安裝好了Python, 那麼在Linux命令行輸入: $python 將直接進入python。然後在命令行提示符>>>後面輸入: >>>print('He ...
  • 前言 CountDownLatch是一個閉鎖實現,它可以使一個或者多個線程等待一組事件發生。它包含一個計數器,用來表示需要等待的事件數量,coutDown方法用於表示一個事件發生,計數器隨之遞減,而await方法等待計數器為0之前一直阻塞。它是基於AQS的共用鎖來實現的,其中使用了較多的AQS的方法 ...
  • 1、作用域public,private,protected,以及不寫時的區別 答:區別如下: 作用域 當前類 同一package 子孫類 其他package public √ √ √ √ protected √ √ √ × friendly √ √ × × private √ × × × 不寫時預設 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...