当前位置:首页>热门 > >正文

微服务之道:8个原则,打造高效的微服务体系 世界快资讯

  • 2023-06-01 19:34:35来源:博客园

hi,我是熵减,见字如面。

现在,在大型的软件工程系统中,微服务化的系统设计,成为了大部分时候的必然之选。


(资料图)

而如何将微服务做有效的设计,则是需要每一个团队和工程师都需要考虑的一个问题。在保持系统的一致性、可理解性、可维护性和可扩展性上,需要有一些基本的指导原则。

下面分享微服务设计和实践中的8个基础原则,具体如下:

基本原则概览

在微服务中,设计API时可以遵循以下原则:

单一职责原则(Single Responsibility Principle):每个微服务应该只关注一个特定的业务领域或功能,因此其API应该具有明确的职责,只提供与该领域或功能相关的接口。

显式接口原则(Explicit Interface Principle):API应该明确和清晰地定义其接口,包括输入参数、输出结果和可能的错误码。这样可以提高接口的可理解性和可维护性,减少误用和不必要的沟通。

界限上下文(Bounded Context):根据微服务的边界和业务需求,划分出不同的界限上下文。API的设计应该与界限上下文相匹配,以确保接口的一致性和内聚性。

服务契约(Service Contract):API应该建立明确的服务契约,包括接口的语义、协议和版本管理。这有助于不同团队之间的协作,确保服务之间的兼容性和互操作性。

信息隐藏(Information Hiding):API应该隐藏内部实现细节,只暴露必要的接口。这样可以减少对内部实现的依赖性,提高服务的独立性和可替代性。

无状态性(Statelessness):尽量设计无状态的API,即不保存客户端的状态信息,每个请求都应该是独立的。这样可以提高服务的可伸缩性和容错性。

适应性与演进性(Adaptability and Evolution):API应该具有适应性和演进性,能够容易地适应不同的需求和变化。通过版本控制和向后兼容性,可以使API在不破坏现有客户端的情况下进行演进和升级。

安全性和身份验证(Security and Authentication):API应该提供适当的安全机制和身份验证,以保护服务和数据的安全性。这可能包括使用加密传输、身份验证令牌和访问控制等措施。

接下来,我们将通过日常的一些具体demo,来逐个展开这8个原则。

原则具体实例单一职责原则

以下是一个违反单一职责原则的反例,使用Java代码进行演示:

public class UserAPI {        public void createUser(String username, String password) {        // 创建用户的逻辑    }        public void getUserInfo(String username) {        // 获取用户信息的逻辑    }        public void updateUser(String username, String newPassword) {        // 更新用户密码的逻辑    }        public void deleteUser(String username) {        // 删除用户的逻辑    }        public void sendEmail(String username, String subject, String content) {        // 发送邮件的逻辑    }    }

在上述代码中,UserAPI 类违反了单一职责原则。它既包含了用户管理的功能(创建、获取、更新、删除用户),又包含了邮件发送的功能。这使得这个类承担了多个不同的职责,导致了耦合度增加、代码复杂度提高和可维护性下降的问题。

根据单一职责原则,应该将不同的职责拆分为独立的类或模块。

对于上述例子,可以将用户管理和邮件发送拆分为两个单独的类,分别负责各自的功能。这样可以提高代码的可读性、可维护性和扩展性。

public class UserManagementAPI {        public void createUser(String username, String password) {        // 创建用户的逻辑    }        public void getUserInfo(String username) {        // 获取用户信息的逻辑    }        public void updateUser(String username, String newPassword) {        // 更新用户密码的逻辑    }        public void deleteUser(String username) {        // 删除用户的逻辑    }    }public class EmailService {        public void sendEmail(String username, String subject, String content) {        // 发送邮件的逻辑    }    }

通过将功能进行拆分,每个类只关注一个特定的职责,代码变得更加清晰、可维护,并符合单一职责原则。

显式接口原则

以下是一个违反显式接口原则的反例,使用Java代码进行演示:

public class Calculator {        public int calculate(int a, int b, String operation) {        if (operation.equals("add")) {            return a + b;        } else if (operation.equals("subtract")) {            return a - b;        } else if (operation.equals("multiply")) {            return a * b;        } else if (operation.equals("divide")) {            return a / b;        }        return 0;    }    }

在上述代码中,Calculator 类违反了显式接口原则。它使用了一个字符串参数 operation 来决定进行何种计算操作。这种设计方式不明确和不清晰,没有明确定义接口和输入输出的结构,使用方在调用时无法准确理解和使用该接口。

根据显式接口原则,应该明确和清晰地定义接口,包括输入参数、输出结果和可能的错误码。以下是一个改进的示例:

public interface Calculator {        int add(int a, int b);        int subtract(int a, int b);        int multiply(int a, int b);        int divide(int a, int b);    }

通过定义明确的接口,使用方可以清晰地知道接口的输入和输出,而不需要传递一个字符串参数来确定操作类型。这样可以提高接口的可理解性和可维护性,遵循了显式接口原则。

public class SimpleCalculator implements Calculator {        @Override    public int add(int a, int b) {        return a + b;    }        @Override    public int subtract(int a, int b) {        return a - b;    }        @Override    public int multiply(int a, int b) {        return a * b;    }        @Override    public int divide(int a, int b) {        return a / b;    }    }

通过实现明确的接口,使用方可以根据接口定义来调用相应的方法,而无需传递一个字符串参数来指定操作。这样可以提高代码的可读性、可维护性和扩展性,并符合显式接口原则。

界限上下文

界限上下文原则(Bounded Context)的主要目标是将大型系统拆分为不同的上下文,每个上下文专注于一个特定的业务领域,并且在该上下文内保持一致性。以下是一个违反界限上下文原则的反例:

假设有一个电子商务系统,其中包含订单管理和库存管理两个领域。下面是一个违反界限上下文原则的实现示例:

public class OrderService {        public void createOrder(Order order) {        // 创建订单的逻辑    }        public void updateOrderStatus(Order order, String status) {        // 更新订单状态的逻辑    }        public void reserveStock(Order order) {        // 预留库存的逻辑    }        public void releaseStock(Order order) {        // 释放库存的逻辑    }        public void updateStock(Order order) {        // 更新库存的逻辑    }    }

在上述代码中,OrderService 类同时包含了订单管理和库存管理的逻辑,违反了界限上下文原则。应该将这两个业务领域拆分为独立的上下文,分别负责各自的功能。

public class OrderService {        public void createOrder(Order order) {        // 创建订单的逻辑    }        public void updateOrderStatus(Order order, String status) {        // 更新订单状态的逻辑    }    }public class InventoryService {        public void reserveStock(Order order) {        // 预留库存的逻辑    }        public void releaseStock(Order order) {        // 释放库存的逻辑    }        public void updateStock(Order order) {        // 更新库存的逻辑    }    }

通过将订单管理和库存管理拆分为独立的服务,每个服务只关注自己领域的逻辑,代码变得更加清晰、可维护,并符合界限上下文原则。这样可以减少不同领域之间的耦合度,提高代码的模块化和可扩展性。

服务契约

服务契约(Service Contracts)旨在定义服务之间的明确契约,包括输入参数、输出结果和可能的错误码。

假设我们有一个用户管理服务,其中有一个方法用于更新用户信息。下面是一个违反服务契约原则的示例:

public class UserService {        public void updateUser(String userId, String newEmail) {        // 更新用户信息的逻辑    }    }

在上述代码中,updateUser 方法只接受用户ID和新的电子邮件地址作为参数,但是它没有返回任何结果或处理任何错误情况。这违反了服务契约原则,因为它没有明确定义输入参数、输出结果和错误处理。

改进的做法是明确定义服务的契约,包括输入参数、输出结果和错误处理。以下是一个改进的示例:

public class UserService {        public UpdateUserResponse updateUser(UpdateUserRequest request) {        // 更新用户信息的逻辑        // ...        UpdateUserResponse response = new UpdateUserResponse();        // 设置更新结果        return response;    }    }public class UpdateUserRequest {    private String userId;    private String newEmail;    // 其他相关属性和方法        // Getters and setters}public class UpdateUserResponse {    private boolean success;    private String errorMessage;    // 其他相关属性和方法        // Getters and setters}

通过引入UpdateUserRequest和UpdateUserResponse对象来明确定义输入参数和输出结果的结构,我们可以更好地遵循服务契约原则。使用方可以清楚地了解服务的输入参数类型、输出结果类型以及如何处理错误情况。这样可以提高代码的可读性、可维护性和扩展性,并确保服务之间的契约明确。

信息隐藏

信息隐藏原则(Information Hiding Principle)是面向对象设计中的一个原则,它强调将类的内部细节隐藏起来,只暴露必要的接口给外部使用。

以下是一个违反信息隐藏原则的反例:

public class BankAccount {        public String accountNumber;    public String accountHolder;    public double balance;        public void deposit(double amount) {        balance += amount;    }        public void withdraw(double amount) {        balance -= amount;    }        public void displayAccountInfo() {        System.out.println("Account Number: " + accountNumber);        System.out.println("Account Holder: " + accountHolder);        System.out.println("Balance: " + balance);    }}

在上述代码中,BankAccount 类违反了信息隐藏原则。它将账户号码、账户持有人和余额都声明为公共的属性,可以被外部直接访问和修改。同时,displayAccountInfo 方法也直接打印账户信息到控制台。

改进的做法是将类的内部状态和实现细节封装起来,只提供必要的接口供外部访问和操作。以下是一个改进的示例:

public class BankAccount {        private String accountNumber;    private String accountHolder;    private double balance;        public BankAccount(String accountNumber, String accountHolder) {        this.accountNumber = accountNumber;        this.accountHolder = accountHolder;        this.balance = 0;    }        public void deposit(double amount) {        balance += amount;    }        public void withdraw(double amount) {        balance -= amount;    }        public void displayAccountInfo() {        System.out.println("Account Number: " + accountNumber);        System.out.println("Account Holder: " + accountHolder);        System.out.println("Balance: " + balance);    }}

在改进后的代码中,将账户的属性声明为私有,并提供了公共的方法来进行存款、取款和显示账户信息的操作。外部代码无法直接访问和修改账户的内部状态,只能通过提供的接口来与账户对象进行交互,保护了类的内部实现细节并提高了封装性。

无状态性

无状态性原则(Statelessness Principle)强调在设计中避免保存客户端的状态信息,每个请求应该是独立且自包含的。

以下是一个违反无状态性原则的反例:

public class ShoppingCart {        private List items;    private double totalPrice;        public void addItem(Item item) {        items.add(item);        totalPrice += item.getPrice();    }        public void removeItem(Item item) {        items.remove(item);        totalPrice -= item.getPrice();    }        public double getTotalPrice() {        return totalPrice;    }        // 其他方法}

在上述代码中,ShoppingCart 类保存了客户端的状态信息,包括购物车中的商品列表和总价格。每次添加或移除商品时,都会更新购物车中的商品列表和总价格。这违反了无状态性原则,因为购物车的状态信息依赖于之前的操作,并且随着时间的推移会发生变化。

改进的做法是使购物车变得无状态,每个请求都是独立的。以下是一个改进的示例:

public class ShoppingCart {        public double calculateTotalPrice(List items) {        double totalPrice = 0;        for (Item item : items) {            totalPrice += item.getPrice();        }        return totalPrice;    }        // 其他方法}

在改进后的代码中,我们将购物车改为一个无状态的类,不保存任何状态信息。相反,我们提供了一个 calculateTotalPrice 方法,接收商品列表作为参数,并根据传入的列表计算总价格。每次调用该方法时,都是独立的,不依赖于之前的操作,保持了无状态性。

这样设计可以更好地遵循无状态性原则,使每个请求都是独立的,无需保存客户端的状态信息,提高了可伸缩性和可靠性。

适应性与演进性

适应性与演进性原则(Adaptability and Evolvability Principle)强调系统的设计应具备适应变化和演进的能力,能够灵活应对新需求和技术的引入。

以下是一个违反适应性与演进性原则的反例:

public class PaymentService {        public void processPayment(String paymentMethod, double amount) {        if (paymentMethod.equals("creditCard")) {            // 处理信用卡支付逻辑            System.out.println("Processing credit card payment...");        } else if (paymentMethod.equals("paypal")) {            // 处理PayPal支付逻辑            System.out.println("Processing PayPal payment...");        } else if (paymentMethod.equals("applePay")) {            // 处理Apple Pay支付逻辑            System.out.println("Processing Apple Pay payment...");        } else {            throw new IllegalArgumentException("Unsupported payment method");        }    }        // 其他方法}

在上述代码中,PaymentService 类中的 processPayment 方法根据传入的支付方式进行相应的支付处理。这种实现方式违反了适应性与演进性原则,因为当引入新的支付方式时,需要修改 processPayment 方法的代码来添加新的逻辑分支。

改进的做法是通过接口和策略模式来实现支付方式的适应性和演进性。以下是一个改进的示例:

public interface PaymentMethod {    void processPayment(double amount);}public class CreditCardPayment implements PaymentMethod {    @Override    public void processPayment(double amount) {        // 处理信用卡支付逻辑        System.out.println("Processing credit card payment...");    }}public class PayPalPayment implements PaymentMethod {    @Override    public void processPayment(double amount) {        // 处理PayPal支付逻辑        System.out.println("Processing PayPal payment...");    }}public class ApplePayPayment implements PaymentMethod {    @Override    public void processPayment(double amount) {        // 处理Apple Pay支付逻辑        System.out.println("Processing Apple Pay payment...");    }}public class PaymentService {        public void processPayment(PaymentMethod paymentMethod, double amount) {        paymentMethod.processPayment(amount);    }        // 其他方法}

在改进后的代码中,我们定义了一个 PaymentMethod 接口,并为每种支付方式实现了具体的实现类。

PaymentService 类的 processPayment 方法接收一个 PaymentMethod 对象作为参数,并调用相应的支付方式的 processPayment 方法进行支付处理。

通过接口和策略模式的使用,我们使得支付方式的添加和修改变得更加灵活和可扩展,符合适应性与演进性原则。

安全性和身份验证

安全性和身份验证原则(Security and Authentication Principle)强调在系统设计中应该考虑安全性需求,并采取适当的身份验证措施来保护系统和用户的安全。

以下是一个违反安全性和身份验证原则的反例:

public class UserController {        public UserDTO getUser(String userId) {        // 根据用户ID查询用户信息        return userRepository.findUserById(userId);    }        public void updateUser(String userId, UserDTO updatedUser) {        // 更新用户信息        userRepository.updateUser(userId, updatedUser);    }        // 其他方法}

在上述代码中,UserController 类提供了获取用户和更新用户信息的方法。然而,该实现没有进行任何身份验证或安全性检查,任何人只要知道用户ID就可以获取和更新用户信息。

改进的做法是引入身份验证和安全性措施来保护用户信息。以下是一个改进的示例:

public class UserController {        private AuthenticationService authenticationService;    private UserRepository userRepository;        public UserDTO getUser(String userId, String authToken) {        if (!authenticationService.isAuthenticated(authToken)) {            throw new SecurityException("Unauthorized access");        }        // 根据用户ID查询用户信息        return userRepository.findUserById(userId);    }        public void updateUser(String userId, UserDTO updatedUser, String authToken) {        if (!authenticationService.isAuthenticated(authToken)) {            throw new SecurityException("Unauthorized access");        }        // 更新用户信息        userRepository.updateUser(userId, updatedUser);    }        // 其他方法}

在改进后的代码中,我们引入了 AuthenticationService 来进行身份验证,并在获取用户和更新用户信息的方法中进行验证。

如果身份验证失败,将抛出一个安全异常,阻止未经授权的访问。

这样,用户信息的访问和修改将受到身份验证和安全性保护,符合安全性和身份验证原则。

最后

以上的8个基本原则,可以作为我们日常设计微服务API的指导,来帮助团队确保服务的一致性、可理解性、可维护性和可扩展性。

然而,具体的微服务的API设计,还应根据具体的项目的特定需求、团队的技术栈和业务场景做出适当的调整和决策。

标签:

延伸阅读

推荐阅读

微服务之道:8个原则,打造高效的微服务体系 世界快资讯

hi,我是熵减,见字如面。现在,在大型的软件工程系统中,微服务化的系统设计,成为了大部分时候的必然之选

拜托小姐插曲i love you下载_拜托小姐插曲

1、求你了,小姐-我爱你我爱你,哦我爱你,我会永远在你身边,我的心永远和你在一起,哦我爱你,每当我单独

AppleFitness流媒体播放到iOS14.5中的AirPlay2智能电视_今日热门

Peloton和DailyBurn等在线健身服务已变得非常流行,现在Apple希望参与其中。他们很快将为Apple用户

小冰首批网红明星克隆人提前上线 暂不开放技术接口

6月1日,记者从小冰公司获悉,日前,首批网红明星克隆人已提前上线,其中包括此前饱受争议的“半藏森林”。

中国“网红”城市“虚”“实”结合 促“流量”变“留量” 天天快播

题:中国“网红”城市“虚”“实”结合促“流量”变“留量”作者李娇阳5月31日,来自中国国内数字文化产业

浦发银行投资金条价格今天多少一克(2023年06月01日)

金投网提供浦发银行投资金条价格今天多少一克(2023年06月01日),浦发银行投资金条价格最新消息(2023年06

天天观焦点:光灵石怎么得

今天来聊聊关于光灵石怎么得的文章,现在就为大家来简单介绍下光灵石怎么得,希望对各位小伙伴们有所帮助。

艺术 | “北方演艺集团剧目孵化平台——扶风起飞计划”在天津启动

5月31日“北方演艺集团剧目孵化平台——扶风起飞计划”发布会在天津曹禺剧院拉开帷幕。北方演艺集团党委副

6月1日医疗服务板块涨幅达3% 环球视点

6月1日11点17分,医疗服务板块指数报1314 504点,涨幅达3%,成交82 97亿元,换手率0 89%。板块个股中,涨幅

彩金贵妃醉酒金币价格今天多少一克(2023年06月01日)|焦点消息

金投网提供彩金贵妃醉酒金币价格今天多少一克(2023年06月01日),彩金贵妃醉酒金币价格最新消息(2023年06

green浏览器打不开网址_green浏览器

1、在电脑上找到控制面板,查找方法最方便的方法为在电脑桌面的左下角找到并点击开始-----控制面板选项;2

国际油价,一个月大跌10%!什么情况→

国际油价,一个月大跌10%!什么情况→当地时间周三,投资者等待美国众议院对债务上限协议的投票结果,市场

全球资讯:中消协发布“六一”消费提示 给孩子报班一次性交钱不要超5000元

在“六一”儿童节来临之际,不少教育培训机构选择在“六一”期间大幅度促销。对此,中国消费者协会今天发布

福克斯3w公里保养,福克斯十万公里大保养明细表 前沿热点

福克斯3W公里保养和十万公里大保养明细表的重要性福克斯作为福特汽车旗下的一款车型,拥有着优秀的动力、空

win7如何显示隐藏文件 相关知识学习

文件夹或者文件的属性设置成隐藏,有时候会想不隐藏显示,那么win7如何显示隐藏文件?具体步骤如下:

培育家国情怀,长沙枫林绿洲小学庆“六一”逐梦未来_环球速读

三湘都市报5月31日讯(全媒体记者杨斯涵黄京通讯员刘彦希实习生龙思汝)今日,长沙市岳麓区枫林绿洲小学202

全球热点!周至|凌晨,有群众向竹峪派出所报警!

老人年纪大了,记忆力减退,行动不便,独自出行便会成为一件困难的事情,近日,周至县公安局竹峪派出所民警

穆帅10分钟从冷静到暴怒,20年第2个乌龙,罗马遇34年魔咒-焦点速递

穆帅10分钟从冷静到暴怒,20年第2个乌龙,罗马遇34年魔咒,罗马,穆帅,曼奇尼,欧联杯,塞维利亚队,何塞·穆里尼奥

:沃尔沃XC90怎么样及艾瑞泽5e 450 瑞虎3xe 480现在报价多少钱

去年国内车市掉头向下,豪华品牌却集体出现大幅上扬,宝马、奔驰、奥迪,乃至凯迪拉克、雷克萨斯等在国内大

5月PMI数据公布!哪些结构性机会可以关注?-环球快看

中长期来看,我们对股票市场的基本逻辑和判断并未改变,即当前宏观经济已经从衰退期转向复苏期,此时资本市

【新人物必备指南】费尔男爵 当前速递

64-65BaronFel费尔男爵发音Fěl种族人类性别男性头发颜色黑色眼睛颜色深棕色身高1 83米母星科雷利亚费尔男

新生儿皮下坏疽_关于新生儿皮下坏疽简介

1、新生儿皮下坏疽是新生儿期特有的急性皮下组织的化脓性感染。2、绝大多数由金黄色葡萄球菌引起,多发生在

天天观热点:弘扬正能量丨公安河西分局对4名见义勇为人员予以褒奖

弘扬正能量丨公安河西分局对4名见义勇为人员予以褒奖为大力弘扬见义勇为精神喝社会正能量,近日,公安河西

天天短讯!景海鹏、邓清明,第三次拥抱!

5月30日18时22分翘盼已久的“神十五”航天员乘组顺利打开“家门”欢迎远道而来的“神十六”航天员入驻“天

女捕快txt小说下载_一号女捕快txt网盘

一号女捕快txt全集小说附件已上传到百度网盘,点击免费下载:内容预览:本站提供的小说《一号女捕快》是一

抖音回应 10 亿元收购支付公司快钱:仅初步接洽

IT之家5月31日消息,相信大多数抖音用户都接触过“抖音支付”,这也是目前抖音App内最主要的支付选项之一。

当前视讯!水何澹澹_水何澹澹山岛竦峙画面

1、东临碣石,以观沧海。2、水何澹澹,山岛竦峙。3、树木丛生,百草丰茂。4、秋风萧瑟,洪波涌起。5、日月

当前滚动:福龙马:5月预中标2.13亿元环卫服务项目

福龙马:5月预中标2 13亿元环卫服务项目:福龙马公告,公司2023年5月预中标了山东省聊城市、安徽省宿州市、

环球新动态:宇通客车氢燃料商用车已安全运营超5800万公里

在5月29日举行的“2023河南(郑州)氢能与燃料电池汽车产业发展论坛暨2023第十一届郑州国际新能源汽车博览

英雄为国再出征——记神舟十六号航天员 今日讯

这一刻,世人目光又一次聚焦中国西北巴丹吉林沙漠深处——

猜您喜欢

Copyright ©  2015-2022 起点服装网版权所有  备案号:皖ICP备2022009963号-12   联系邮箱: 39 60 29 14 2@qq.com