Eureka Server入門項目搭建
(剛開始學習微服務架構,來記錄下.)
一:單體應用與微服務
? ? 1.單體應用缺點
? ? ? ? ? ? 1.1 開發(fā)速度慢
????????????1. 2 啟動時間長
????????????1. 3 依賴龐大
????????????????......等等
? ? ? ? 2.什么是微服務
? ? ? ? ? ? ? ? ?2.1. 微服務架構設計代表了一種架構設計思想,再配合上容器技術(如Docker),可以在程序開發(fā)上的流程、 部署、服務維護等各方面的效率得到很大提升。
? ? ? ? ? ? ? ? ?2.2. 微服務就是將一個單體架構的應用按業(yè)務劃分為一個個的獨立運行的程序即服務,它們之間通過 HTTP協議進行通信(也可以采用消息隊列來通信,如 RoocketMQ,Kafaka等),可以采用不同的編程語言,使用不同的存儲技術,自動化部署(如Jenkins)減少人為控制,降低出錯概率。服務數量越多,管理起來越復雜,因此采用集中化管理。例如 Eureka,Zookeeper等都是比較常見的服務集中化管理框架
? ? ? ? ? ? ? ? ?2.3. .........
? ? ? ? 3.微服務的好處
? ? ? ? ? ? ? ? 3.1. 可以將一個龐大的單體架構的應用按業(yè)務切分為多個具有不同服務的程序應用,各自獨立運行,每個服務都有一個定義清楚的邊界,通過 RPC- 或者消息驅動API與外接溝通,單個微服務相比單體應用更容易開發(fā)和維護.
? ? ? ? ? ? ? ? ?3.2. 微服務架構使得每個微服務獨立部署。加快部署速度,這樣一來,每個服務都屬于一個單獨的個體,對服務的維護,升級,擴展等帶來極大的便利
? ? ? ? ? ? ? ? ? ? ?3.3. .....
? ? ? ? 4.微服務架構的不足之處
? ? ? ? ? ? ? ? ?4.1. 微服務應用是一個分布式系統(tǒng),由此會帶來分布式系統(tǒng)固有的復雜性.
? ? ? ? ? ? ? ? ?4.2. 多個服務之間的依賴問題,相關應用的升級以及修改等有可能會波及多個服務模塊的修改.在以往單體應用中,只需要修改相關的模塊便可,整合后一并部署。而微服務架構模式,修改服務模塊時就需要考慮服務間的依賴關系
? ? ? ? ? ? ? ? ?4.3. 分布式系統(tǒng)--->分布式事務問題
? ? ? ? ? ? ? ? ?4.4. 需要管理多個服務-->服務治理
另:微服務核心知識 :網關、服務發(fā)現注冊、配置中心、鏈路追蹤、負載均衡器、熔斷...等
1. 網關:路由轉發(fā) + 過濾器
????????????????????/api/v1/pruduct/? ? ? 商品服務
? ? ? ? ? ? ? ? ? ? ?/api/v1/order/? ? ? ? 訂單服務
????????????????????/api/v1/user/? ? 用戶服務
2. 服務注冊發(fā)現:調用和被調用方的信息維護
3. 配置中心:管理配置,動態(tài)更新 application.properties
4. 鏈路追蹤:分析調用鏈路耗時
例子:下單-》查詢商品服務獲取商品價格-》查詢用戶信息-》保存數據庫
5. 負載均衡器:分發(fā)負載
6. 熔斷:保護自己和被調用方
常見的微服務框架:
1. consumer: 調用方
2. provider: 被調用方
一個接口一般都會充當兩個角色(不是同時充當)
1、dubbo: zookeeper + dubbo + springmvc/springboot
官方地址:http://dubbo.apache.org/#!/?lang=zh-cn
配套
通信方式:rpc
注冊中心:zookeper/redis
配置中心:diamond
2、springcloud: 全家桶+輕松嵌入第三方組件(Netflix 奈飛)
官網:http://projects.spring.io/spring-cloud/
配套
通信方式:http restful
注冊中心:eruka/consul
配置中心:config
斷路器:hystrix
網關:zuul
分布式追蹤系統(tǒng):sleuth+zipkin
二:搭建步驟
(剛開始學習,我這里使用的是Eureka)
**項目結構:**
? (我這里按照習慣,建的是"父子工程",當然也可以新建兩個獨立工程,編輯器:IDEA)

1.新建一個空白的父工程,src以及其他暫時用不著的東西可以先刪除
? (步驟略)
? 2.新建第一個Module,用來做"注冊中心"

入門項目,業(yè)務不多,依賴選擇一個即可,項目創(chuàng)建好后的依賴:
<properties>
? ? ? ? <java.version>1.8</java.version>
? ? ? ? <spring-cloud.version>Hoxton.RELEASE</spring-cloud.version>
? ? </properties>
? ? <dependencies>
? ? ? ? <dependency>
? ? ? ? ? ? <groupId>org.springframework.cloud</groupId>
? ? ? ? ? ? <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
? ? ? ? </dependency>
? ? ? ? <dependency>
? ? ? ? ? ? <groupId>org.springframework.boot</groupId>
? ? ? ? ? ? <artifactId>spring-boot-starter-test</artifactId>
? ? ? ? ? ? <scope>test</scope>
? ? ? ? ? ? <exclusions>
? ? ? ? ? ? ? ? <exclusion>
? ? ? ? ? ? ? ? ? ? <groupId>org.junit.vintage</groupId>
? ? ? ? ? ? ? ? ? ? <artifactId>junit-vintage-engine</artifactId>
? ? ? ? ? ? ? ? </exclusion>
? ? ? ? ? ? </exclusions>
? ? ? ? </dependency>
? ? </dependencies>
? ? <dependencyManagement>
? ? ? ? <dependencies>
? ? ? ? ? ? <dependency>
? ? ? ? ? ? ? ? <groupId>org.springframework.cloud</groupId>
? ? ? ? ? ? ? ? <artifactId>spring-cloud-dependencies</artifactId>
? ? ? ? ? ? ? ? <version>${spring-cloud.version}</version>
? ? ? ? ? ? ? ? <type>pom</type>
? ? ? ? ? ? ? ? <scope>import</scope>
? ? ? ? ? ? </dependency>
? ? ? ? </dependencies>
? ? </dependencyManagement>
3.在啟動類上添加注解:@EnableEurekaServer

4.添加配置(application.yml):
server:
? port: 8761
eureka:
? instance:
? ? hostname: localhost
? client:
? ? #聲明自己是服務端
? ? registerWithEureka: false
? ? fetchRegistry: false
? ? serviceUrl:
? ? ? defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
5.啟動服務:方式跟平常啟動sprinboot應用一樣
瀏覽器輸入:http://localhost:8761/
一個簡單的"注冊中心"創(chuàng)建完畢


6.創(chuàng)建第二個Module:商品服務
依賴選擇:

7.分別創(chuàng)建實體類,service,controller;

實體類:
//Product.java
package com.xt.tools.eureka.product_server.domain;
import lombok.Data;
/*
* @description: 說明
* @author: 小譚
* @date: 2019/12/5 20:04
*/
@Data
public class Product {
? ? private int id;
? ? private String name;
? ? private int price;
? ? private int store;
? ? public Product(int id, String name, int price, int store) {
? ? ? ? this.id = id;
? ? ? ? this.name = name;
? ? ? ? this.price = price;
? ? ? ? this.store = store;
? ? }
? ? public Product() {}
}
service接口:
//ProductService.java
package com.xt.tools.eureka.product_server.service;
import com.xt.tools.eureka.product_server.domain.Product;
import java.util.List;
/*
* @description: 說明
* @author: 小譚
* @date: 2019/12/5 20:06
*/
public interface ProductService {
? ? List<Product> ListProduct();
? ? Product findById(int id);
}
service接口實現類:
package com.xt.tools.eureka.product_server.service;
import com.xt.tools.eureka.product_server.domain.Product;
import org.springframework.stereotype.Service;
import java.util.*;
/*
* @description: 說明
* @author: 小譚
* @date: 2019/12/5 20:09
*/
@Service
public class ProductServiceImpl implements ProductService {
? ? private static Map<Integer,Product> daoMap = new HashMap<>();
? ? static {
? ? ? ? Product p1 = new Product(1,"iphonex",9999, 10);
? ? ? ? Product p2 = new Product(2,"冰箱",5342, 19);
? ? ? ? Product p3 = new Product(3,"洗衣機",523, 90);
? ? ? ? Product p4 = new Product(4,"電話",64345, 150);
? ? ? ? Product p5 = new Product(5,"汽車",2345, 140);
? ? ? ? Product p6 = new Product(6,"椅子",253, 20);
? ? ? ? Product p7 = new Product(7,"java編程思想",2341, 10);
? ? ? ? daoMap.put(p1.getId(),p1);
? ? ? ? daoMap.put(p2.getId(),p2);
? ? ? ? daoMap.put(p3.getId(),p3);
? ? ? ? daoMap.put(p4.getId(),p4);
? ? ? ? daoMap.put(p5.getId(),p5);
? ? ? ? daoMap.put(p6.getId(),p6);
? ? ? ? daoMap.put(p7.getId(),p7);
? ? }
? ? @Override
? ? public List<Product> ListProduct() {
? ? ? ? Collection<Product> values = daoMap.values();
? ? ? ? List<Product> products = new ArrayList<>(values);
? ? ? ? return products;
? ? }
? ? @Override
? ? public Product findById(int id) {
? ? ? ? return daoMap.get(id);
? ? }
}
controller:
package com.xt.tools.eureka.product_server.controller;
import com.xt.tools.eureka.product_server.service.ProductService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/*
* @description: 說明
* @author: 小譚
* @date: 2019/12/5 20:03
*/
@RestController
@RequestMapping("/api/v1/product")
public class productController {
? ? @Autowired
? ? private ProductService productService;
? ? @RequestMapping("list")
? ? public Object List(){
? ? ? ? return productService.ListProduct();
? ? }
? ? @RequestMapping("find")
? ? public Object product(@RequestParam("id") int id){
? ? ? ? return productService.findById(id);
? ? }
}
最后,配置文件:
server:
? port: 8771
#指定spring應用名稱
spring:
? application:
? ? name: product-server
#指定注冊中心地址
eureka:
? client:
? ? serviceUrl:
? ? ? defaultZone: http://localhost:8761/eureka/
現在可以啟動服務了,至于這個Module的啟動類的注解:@EnableEurekaClient,可加可不加
(1):http://localhost:8771/api/v1/product/list

(2):http://localhost:8771/api/v1/product/find?id=2

有數據返回,功能一切正常,再來刷新一下注冊中心:

與開始相比,頁面多出了一些東西,目前,商品服務已成功注冊進去了,
問題一:eureka管理后臺出現一串紅色字體:是警告,說明有服務上線率低
EMERGENCY! EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ARE UP WHEN THEY'RE NOT. RENEWALS ARE LESSER THAN THRESHOLD AND HENCE THE INSTANCES ARE NOT BEING EXPIRED JUST TO BE SAFE.
關閉檢查方法:eureka服務端配置文件加入
server:
enable-self-preservation: false
注意:自我保護模式禁止關閉,默認是開啟狀態(tài)true
問題二:為什么只加一個注冊中心地址,就可以注冊
官方解釋:(https://cloud.spring.io/spring-cloud-netflix/reference/html/#service-discovery-eureka-clients):
By having spring-cloud-starter-netflix-eureka-client on the classpath, your application automatically registers with the Eureka Server. Configuration is required to locate the Eureka server, as shown in the following example:
google翻譯:
通過在類路徑上使用spring-cloud-starter-netflix-eureka-client,您的應用程序將自動向Eureka Server注冊。需要配置以找到Eureka服務器,如以下示例所示
github項目: https://github.com/XT962464oo/Eureka_demo