web框架flask(8)——关注者,联系人和好友

本文详细介绍了在社交应用中实现用户关注功能的方法,包括数据库设计、关注与取消关注的实现及查询优化等内容。

关注者,联系人和好友

回顾

我们小型的 microblog 应用程序已经慢慢变大,到现在为止我们已经接触了需要完成应用程序的大部分的话题。

今天我们将更加深入地学习数据库。我们应用程序的每一个用户都能够选择他或者她的关注者,因此我们的数据库必须能够记录谁关注了谁。所有的社交应用都会以某种形式实现这个功能。一些应用程序称它为联系人,其他连接,好友,伙伴或者关注者。其他的站点使用同样的主意去实现允许和忽略的用户列表。我们称它为关注者,尽管名字不同实现方式却是一样的。

‘关注者’ 特色的设计

在编码之前,我们需要考虑下我们要从这个功能上得到些什么,换句话说,我们要实现些什么。

让我们先从最明显一个开始。我们想要用户容易地维护关注者的列表。

从另外一方面来看,对于每一个用户,我们想要知道他的或者她的关注者列表。

我们也想要有一种方式去查询用户是否被关注或者关注过其他用户。

用户点击任何用户的信息页上一个 “关注” 的链接就开始关注这个用户。否则,他们点击 “取消关注” 链接将会停止关注这个用户。

最后一个需求就是对于一个给定的用户,我们能够容易地查询数据库获取用户的被关注者的所有 blog。

所以,如果你认为这将是一个快速和容易的章节,请再想想!

数据库关系

我们说过我们想要有所有用户都拥有 “关注者” 和 “被关注者” 的列表。不幸地是,一个关系型数据库是没有 list 类型,我们有的是含有记录的表以及记录与记录之间的关系。

我们已经在数据库中有一个表来表示用户,所以剩下的就是找出适当的关系类型,它能模拟关注者/被关注者的链接。这是重新回顾三种数据关系类型的好时候:

一对多

在前面的章节中,我们已经见过一对多的关系。下面是这种关系的图表:

_images/6.png

usersposts 是具有这种关系的两个表。我们说一个用户会有撰写多篇 blog,一篇 blog 会有一个撰写人。这种关系在数据库中的表示就是在 “多” 的这一边中使用了外键。在上面的例子中外键就是 posts 表中的 user_id。 这个字段把每一篇 blog 链接到用户表的作者的数据记录上。

user_id 字段提供了到给定 blog 作者的直接入口,然而相反的情况了?因为关系是很有作用的,我们应该能够得到一个给定的用户所撰写的 blog 列表。原来在 posts 表中 user_id 字段是足够能够回答这个问题,因为数据库有高效的查询索引允许我们查询类似 “获取用户 user_id 为 X 的所有的 blog” 的操作。

多对多

多对多的关系是有些复杂。例如,考虑一个数据库有 students 以及 teachers。我们可以说一个学生会有很多个老师,以及一个老师下也有多个学生。这就像两端(学生和老师)都是一对多的关系。

对于这种类型的关系,我们应该能够查询数据库获取在一个 teachers 类中教某一个学生的老师列表,以及一个老师下所有教的学生的列表。表示上述关系是相当棘手的,它不能简单地在已存在的表中添加外键。

这种多对多的关系的表示需要一个额外的称为关联表的辅助表。下面是数据库如何表示学生和教师的关系的例子:

_images/7.png

虽然它可能不会看起来很简单,两个外键的关联表能够有效地回答很多种类的查询,如:

  • 哪些老师教学生 S?
  • 哪些学生是老师 T 教的?
  • 老师 T 有多少个学生?
  • 学生 S 有多少个老师?
  • 老师 T 正在教学生 S 吗?
  • 学生 S 在老师 T 的类里吗?

一对一

一对一的关系是一对多关系的一种特殊情况。表示方式是类似的,但是限制是添加到数据库中为了禁止 “多” 的这一边有一个以上的链接。

虽然某些情况下,这种类型的关系是有用的,它对其他两种类型来说是不常用,因为任何时候一个表的一个记录映射到另外一个表中的一个记录,可以说把两个表合并成一个更有意义。

表示关注者和被关注者

从上面讲述到关系来说,我们很容易地决定最合适的模型是多对多的关系,因为一个用户可以关注多个其他的用户,同样一个用户可以被其他多个用户关注。但是这有一个问题。我们想要表示用户关注其他用户,因为我们只有用户。我们应该使用什么作为多对多关系的第二个表(实体)?

好的,这种关系的第二个表(实体)也是用户。如果一个表是指向自己的关系叫做 自我指向 关系,这就是我们现在需要的。

下面是多对多关系的图:

_images/8.png

followers 表示我们的关联表。外键都是来自于用户表中,因为我们是用户连接到用户。在这个表中的每一个记录都是表示关注的用户以及被关注的用户的连接。像学生和老师的例子,像这样的一个设置允许回答所有我们将需要的关注者以及被关注者的问题。

数据模型

我们数据库的改变不是很大。我们首先开始添加 followers 表(文件 app/models.py):

followers = db.Table('followers',
    db.Column('follower_id', db.Integer, db.ForeignKey('user.id')),
    db.Column('followed_id', db.Integer, db.ForeignKey('user.id'))
)

这是对上面图表上的关系表的直接翻译。注意我们并没有像对 usersposts 一样把它声明为一个模式。因为这是一个辅助表,我们使用 flask-sqlalchemy 中的低级的 APIs 来创建没有使用关联模式。

接着我们在 users 表中定义一个多对多的关系:

class User(db.Model):
    id = db.Column(db.Integer, primary_key = True)
    nickname = db.Column(db.String(64), unique = True)
    email = db.Column(db.String(120), index = True, unique = True)
    posts = db.relationship('Post', backref = 'author', lazy = 'dynamic')
    about_me = db.Column(db.String(140))
    last_seen = db.Column(db.DateTime)
    followed = db.relationship('User',
        secondary = followers,
        primaryjoin = (followers.c.follower_id == id),
        secondaryjoin = (followers.c.followed_id == id),
        backref = db.backref('followers', lazy = 'dynamic'),
        lazy = 'dynamic')

关系的设置不是很简单,需要一些解释。像我们在前面章节设置一对多关系一样,我们使用了 db.relationship 函数来定义关系。我们将连接 User 实例到其它 User 实例,换一种通俗的话来说,在这种关系下连接的一对用户,左边的用户是关注着右边的用户。因为我们定义左边的用户为 followed,当我们从左边用户查询这种关系的时候,我们将会得到被关注用户的列表。让我们一个一个来解释下 db.relationship() 中的所有参数:

  • ‘User’ 是这种关系中的右边的表(实体)(左边的表/实体是父类)。因为定义一个自我指向的关系,我们在两边使用同样的类。
  • secondary 指明了用于这种关系的辅助表。
  • primaryjoin 表示辅助表中连接左边实体(发起关注的用户)的条件。注意因为 followers 表不是一个模式,获得字段名的语法有些怪异。
  • secondaryjoin 表示辅助表中连接右边实体(被关注的用户)的条件。
  • backref 定义这种关系将如何从右边实体进行访问。当我们做出一个名为 followed 的查询的时候,将会返回所有跟左边实体联系的右边的用户。当我们做出一个名为 followers 的查询的时候,将会返回一个所有跟右边联系的左边的用户。lazy 指明了查询的模式。dynamic 模式表示直到有特定的请求才会运行查询,这是对性能有很好的考虑。
  • lazy 是与 backref 中的同样名称的参数作用是类似的,但是这个是应用于常规查询。

如果上面的解释很难理解的话,没有关系。我们会在后面使用这些查询,一切就会明了。

因为我们对数据库做出了修改,现在我们必须生成一个新的迁移脚本:

./db_migrate.py

添加和移除 ‘关注者’

为了使得代码具有可重用性,我们将会在 User 模型中实现 followunfollow 函数,而不是在视图函数中。这种方式不仅可以让这个功能应用于真实的应用也能在单元测试中测试。原则上,从视图函数中移除应用程序的逻辑到数据模型中是一种好的方式。你们必须要保证视图函数尽可能简单,因为它能难被自动化测试。

下面是添加了添加和移除 ‘关注者’ 功能的 User 模型(文件 app/models.py):

class User(db.Model):
    #...
    def follow(self, user):
        if not self.is_following(user):
            self.followed.append(user)
            return self

    def unfollow(self, user):
        if self.is_following(user):
            self.followed.remove(user)
            return self

    def is_following(self, user):
        return self.followed.filter(followers.c.followed_id == user.id).count() > 0

上面这些方法是很简单了,多亏了 sqlalchemy 在底层做了很多的工作。我们只是从 followed 关系中添加或者移除了表项,sqlalchemy 为我们管理辅助表。

followunfollow 方法是定义成当它们成功的话返回一个对象或者失败的时候返回 None。当返回一个对象的时候,这个对象必须被添加到数据库并且提交。

is_following 方法在一行代码中做了很多。我们做了一个 followed 关系查询,这个查询返回所有当前用户作为关注者的 (follower, followed) 对。

测试

让我们编写单元测试框架来检验目前我们已经写好的代码(文件 tests.py):

class TestCase(unittest.TestCase):
    #...
    def test_follow(self):
        u1 = User(nickname = 'john', email = 'john@example.com')
        u2 = User(nickname = 'susan', email = 'susan@example.com')
        db.session.add(u1)
        db.session.add(u2)
        db.session.commit()
        assert u1.unfollow(u2) == None
        u = u1.follow(u2)
        db.session.add(u)
        db.session.commit()
        assert u1.follow(u2) == None
        assert u1.is_following(u2)
        assert u1.followed.count() == 1
        assert u1.followed.first().nickname == 'susan'
        assert u2.followers.count() == 1
        assert u2.followers.first().nickname == 'john'
        u = u1.unfollow(u2)
        assert u != None
        db.session.add(u)
        db.session.commit()
        assert u1.is_following(u2) == False
        assert u1.followed.count() == 0
        assert u2.followers.count() == 0

通过执行下面的命令来运行这个测试:

./tests.py

数据库查询

我们的数据库模型已经能够支持大部分我们列出来的需求。我们缺少的实际上是最难的。我们的首页将会显示登录用户所有关注者撰写的 blog,因为我们需要一个返回这些 blog 的查询。

最明了的解决方式就是查询给定的关注者用户的列表,这也是我们目前可以做到的。接着对每一个返回的用户去查询他的或者她的 blog。一旦我们完成所有的查询工作,我们把它们整合到一个列表中然后排序。听起来不错?实际上不是。

这种方法其实问题很大。当一个用户拥有上千个关注者的话会发生些什么?我们需要执行上千次甚至更多的数据库查询,并且在内存中我们需要维持一个数据量很大的 blog 的列表,接着还要排序。不知道这些做完,要花上多久的时间?

这种收集以及排序的工作需要在其它的地方完成,我们只要使用结果就行。这类的工作其实就是关系型数据库擅长。数据库有索引,因此允许以一种高效地方式去查询以及排序。

所以我们真正想要的是要拿出一个单一的数据库查询,表示我们想要得到什么样的信息,然后我们让数据库弄清楚什么是最有效的方式来为我们获取数据。

下面这种查询可以实现上述的要求,这个单行的代码又被我们添加到 User 模型(文件 app/models.py):

class User(db.Model):
    #...
    def followed_posts(self):
        return Post.query.join(followers, (followers.c.followed_id == Post.user_id)).filter(followers.c.follower_id == self.id).order_by(Post.timestamp.desc())

让我们来分解这个查询。它一共有三部分:连接,过滤以及排序。

连接

为了理解一个连接操作做了什么,让我们看看例子。假设我们有一个如下内容的 User 表:

_images/2.jpg

只为了简化例子,表里面还有一些额外的字段没有显示。

比如说,我们的 followers 辅助表中表示用户 “john” 关注着 用户 “susan” 以及 “david”,用户 “susan” 关注着 “mary” 以及 用户 “mary” 关注着 “david”。表示上述的数据是这样的:

_images/3.jpg

最后,我们的 Post 表中,每一个用户有一篇 blog:

_images/4.jpg

这里再次申明为了使得例子显得简单,我们忽略了一些字段。

下面是我们的查询的连接部分的,独立于其余的查询:

Post.query.join(followers,
    (followers.c.followed_id == Post.user_id))

Post 表中调用了 join 操作。这里有两个参数,第一个是其它的表,我们的 followers 表。第二参数就是连接的条件。

连接操作所做的就是创建一个数据来自于 Postfollowers 表的临时新的表,根据给定条件进行整合。

在这个例子中,我们要 followers 表中的字段 followed_idPost 表中的字段 user_id 相匹配。

为了演示整合的过程,我们从 Post 表中取出所有记录,从 followers 表中取出符合条件的记录插入在后边。如果没有匹配的话,Post 表中的记录就会被移除。

我们例子中这个临时表的连接的结果如下:

_images/5.jpg

注意 Post 表中的 user_id=1 记录被移除了,因为在 followers 表中没有 followed_id=1 的记录。

过滤

连接操作给我们被某人关注的用户的 blog 的列表,但是没有指出谁是关注者。我们仅仅对这个列表的子集感兴趣,我们只需要被某一特定用户关注的用户的 blog 列表。

因此我们过滤这个表格,查询的过滤操作是:

filter(followers.c.follower_id == self.id)

注意查询是在我们目标用户的内容中执行,因为这是 User 类的一个方法,self.id 就是我们感兴趣的用户的 id。因此在我们的例子中,如果我们感兴趣的用户的 id 是 id=1,那么我们会得到另一个临时表:

_images/6.jpg

这就是我们要的 blog。请注意查询是关注在 Post 类,因此即使我们得到一个不符合我们任何一个数据库模型的临时表,结果还是包含在这个临时表中的 blog。

排序

最后一步就是根据我们的规则对结果进行排序。排序操作如下:

order_by(Post.timestamp.desc())

 

这里还有一个小问题需要我们改善我们的查询操作。当用户阅读他们关注者的 blog 的时候,他们可能也想看到自己的 blog。因此最好把用户自己的 blog 也包含进查询结果中。

其实这不需要做任何改变。我们只需要把自己添加为自己的关注者。

为了结束我们长时间的查询操作的讨论,让我们为我们查询写些单元测试(文件 tests.py):

#...
from datetime import datetime, timedelta
from app.models import User, Post
#...
class TestCase(unittest.TestCase):
    #...
    def test_follow_posts(self):
        # make four users
        u1 = User(nickname = 'john', email = 'john@example.com')
        u2 = User(nickname = 'susan', email = 'susan@example.com')
        u3 = User(nickname = 'mary', email = 'mary@example.com')
        u4 = User(nickname = 'david', email = 'david@example.com')
        db.session.add(u1)
        db.session.add(u2)
        db.session.add(u3)
        db.session.add(u4)
        # make four posts
        utcnow = datetime.utcnow()
        p1 = Post(body = "post from john", author = u1, timestamp = utcnow + timedelta(seconds = 1))
        p2 = Post(body = "post from susan", author = u2, timestamp = utcnow + timedelta(seconds = 2))
        p3 = Post(body = "post from mary", author = u3, timestamp = utcnow + timedelta(seconds = 3))
        p4 = Post(body = "post from david", author = u4, timestamp = utcnow + timedelta(seconds = 4))
        db.session.add(p1)
        db.session.add(p2)
        db.session.add(p3)
        db.session.add(p4)
        db.session.commit()
        # setup the followers
        u1.follow(u1) # john follows himself
        u1.follow(u2) # john follows susan
        u1.follow(u4) # john follows david
        u2.follow(u2) # susan follows herself
        u2.follow(u3) # susan follows mary
        u3.follow(u3) # mary follows herself
        u3.follow(u4) # mary follows david
        u4.follow(u4) # david follows himself
        db.session.add(u1)
        db.session.add(u2)
        db.session.add(u3)
        db.session.add(u4)
        db.session.commit()
        # check the followed posts of each user
        f1 = u1.followed_posts().all()
        f2 = u2.followed_posts().all()
        f3 = u3.followed_posts().all()
        f4 = u4.followed_posts().all()
        assert len(f1) == 3
        assert len(f2) == 2
        assert len(f3) == 2
        assert len(f4) == 1
        assert f1 == [p4, p2, p1]
        assert f2 == [p3, p2]
        assert f3 == [p4, p3]
        assert f4 == [p4]

 

 

可能的改进

我们现在已经实现 ‘follower’ 功能所需要的内容,但是还能改进我们的设计使得变得更加合理。

所有的社会网络,我们对这种连接其它用户的功能是又爱又恨,但他们有更多的选择来控制信息的共享。

例如,我们没有权利拒绝别人的关注。这将要花费很大的底层代码用于查询,因为我们不仅仅需要查询到我们所关注的用户的 blog,而且还要过滤掉拒绝关注的用户的 blog。怎么实现这种需求了?简单,新增一个多对多的自我指向关系用来记录谁拒绝谁的关注,接着一个新的连接+过滤的查询用来返回这些 blog。

社交网络中另一个流行的特色就是能够定制关注者的分组,仅仅共享某些分组的内容。这也是能够通过添加额外的关系以及复杂的查询来实现。

我们不打算把这些加入到我们的 microblog,但是如果大家都感兴趣的话,我将会就此话题新写一章节。

收尾

今天我们已经取得了巨大的进步。尽管我们已经解决了所有的问题,但是有关数据库的设置和查询,我们还没有在应用程序中启用的这些新功能。

幸运地是,这些不存在什么挑战。我们只需要修改下视图函数和模版,因此让我们完成最后的部分来结束这一章节吧。

成为自己的关注者

我们已经决定用户可以关注所有的用户,因此我们可以关注自己。

我们决定在 after_login 中处理 OpenID 的时候就设置自己成为自己的关注者(文件 app/views.py):

@oid.after_login
def after_login(resp):
    if resp.email is None or resp.email == "":
        flash('Invalid login. Please try again.')
        redirect(url_for('login'))
    user = User.query.filter_by(email = resp.email).first()
    if user is None:
        nickname = resp.nickname
        if nickname is None or nickname == "":
            nickname = resp.email.split('@')[0]
        nickname = User.make_unique_nickname(nickname)
        user = User(nickname = nickname, email = resp.email)
        db.session.add(user)
        db.session.commit()
        # make the user follow him/herself
        db.session.add(user.follow(user))
        db.session.commit()
    remember_me = False
    if 'remember_me' in session:
        remember_me = session['remember_me']
        session.pop('remember_me', None)
    login_user(user, remember = remember_me)
    return redirect(request.args.get('next') or url_for('index'))

关注以及取消关注的链接

接着,我们将会定义关注以及取消关注用户的视图函数(文件 app/views.py):

@app.route('/follow/<nickname>')
@login_required
def follow(nickname):
    user = User.query.filter_by(nickname=nickname).first()
    if user is None:
        flash('User %s not found.' % nickname)
        return redirect(url_for('index'))
    if user == g.user:
        flash('You can\'t follow yourself!')
        return redirect(url_for('user', nickname=nickname))
    u = g.user.follow(user)
    if u is None:
        flash('Cannot follow ' + nickname + '.')
        return redirect(url_for('user', nickname=nickname))
    db.session.add(u)
    db.session.commit()
    flash('You are now following ' + nickname + '!')
    return redirect(url_for('user', nickname=nickname))

@app.route('/unfollow/<nickname>')
@login_required
def unfollow(nickname):
    user = User.query.filter_by(nickname=nickname).first()
    if user is None:
        flash('User %s not found.' % nickname)
        return redirect(url_for('index'))
    if user == g.user:
        flash('You can\'t unfollow yourself!')
        return redirect(url_for('user', nickname=nickname))
    u = g.user.unfollow(user)
    if u is None:
        flash('Cannot unfollow ' + nickname + '.')
        return redirect(url_for('user', nickname=nickname))
    db.session.add(u)
    db.session.commit()
    flash('You have stopped following ' + nickname + '.')
    return redirect(url_for('user', nickname=nickname))

这里应该不需要做过多的解释,但是需要注意的是检查周围的错误,为了防止期望之外的错误,试着给用户提供信息并且重定向到合适的位置当错误发生的时候。

最后需要修改下模版(文件 app/templates/user.html):

<!-- extend base layout -->
{% extends "base.html" %}

{% block content %}
<table>
    <tr valign="top">
        <td><img src="{{user.avatar(128)}}"></td>
        <td>
            <h1>User: {{user.nickname}}</h1>
            {% if user.about_me %}<p>{{user.about_me}}</p>{% endif %}
            {% if user.last_seen %}<p><i>Last seen on: {{user.last_seen}}</i></p>{% endif %}
            <p>{{user.followers.count()}} followers |
            {% if user.id == g.user.id %}
                <a href="{{url_for('edit')}}">Edit your profile</a>
            {% elif not g.user.is_following(user) %}
                <a href="{{url_for('follow', nickname = user.nickname)}}">Follow</a>
            {% else %}
                <a href="{{url_for('unfollow', nickname = user.nickname)}}">Unfollow</a>
            {% endif %}
            </p>
        </td>
    </tr>
</table>
<hr>
{% for post in posts %}
    {% include 'post.html' %}
{% endfor %}
{% endblock %}

在编辑一行上,我们会显示关注者的用户数目,后面可能会跟随三种可能的链接:

  • 如果用户属于登录状态,“编辑” 链接会显示。
  • 否则,如果用户不是关注者,“关注” 链接会显示。
  • 否则,一个 “取消关注” 将会显示。

这个时候你可以运行应用程序,创建一些用户,试试关注以及取消关注用户。

最后剩下的就是 index 页,但是现在还不是完成的时候,我们会在下一章完成它。

结束语

今天的话题涉及到数据库关系以及查询,所以可能有些复杂。不用着急,慢慢的消化。

转载于:https://my.oschina.net/u/3767248/blog/1621582

<think>嗯,用户想了解大型科技公司为什么开发自己的Web框架。这个问题挺专业的,可能是个开发者或者技术决策者在做架构选型。从用户引用的资料来看,ta已经对主流框架(如FlaskWeb技术生态(如WASM)有一定了解,但更关注企业级实践背后的逻辑。 用户提供的引用材料很有价值。引用1提到Flask作为微框架的定位,正好能反衬出大公司需要更全面的解决方案;引用3讨论WASM的普及,暗示了性能优化的重要性;引用5描述的WSGI调用流程则揭示了框架底层需要处理的复杂性。这些都能成为回答的支撑点。 需要从多个维度展开:首先是技术自由度,大公司往往有独特的业务场景,比如谷歌需要处理每秒百万级查询,现成框架难以满足;其次是性能优化,像Netflix的自研框架能针对流媒体做传输优化;还有长期维护成本问题,第三方框架的升级可能破坏核心业务逻辑。 安全性系统集成也很关键。引用4提到的"爆库"风险说明数据安全是生命线,自研框架能深度整合内部风控体系。而像阿里双11这种场景,需要框架与库存系统、支付网关无缝协作,通用框架的中间件可能成为瓶颈。 不过也要客观说明弊端,比如初期开发成本高、社区支持弱等问题。最后用实际案例收尾会更有说服力,比如亚马逊的案例就很有代表性——他们为AWS生态专门打造框架,既服务内部也成了云产品。 用户可能还想知道"什么时候该自研",这可以作为延伸问题。另外要注意避免技术堆砌,把淘宝的优化实践说得太深可能会偏离主题,用"动态服务编排"这种概括更合适。</think>大型科技公司选择开发使用自定义Web框架,主要基于以下关键原因: --- ### 一、满足特定业务与技术需求 1. **极致性能优化** 大型应用(如亿级用户平台)需处理高并发、低延迟场景。自研框架可深度优化: - 定制化缓存机制(如分布式缓存层级) - 精简中间件调用链(减少冗余计算) - 针对性协议优化(如Uber自研**TChannel**替代HTTP)[^1] *案例:Netflix开发**Zuul**网关框架实现每秒百万级请求路由与过滤* 2. **特殊业务场景适配** 通用框架难以满足独特需求: - 淘宝需处理海量秒杀请求 → 自研**Tengine**扩展Nginx能力 - 支付宝金融级事务 → 自研**SOFAStack**保证分布式事务一致性 - 美团即时配送系统 → 自研**OCTO**实现动态路由调度 --- ### 二、技术生态深度整合 1. **统一技术栈管控** - 标准化开发规范(如Google内部**Protocol Buffers**强制替代JSON) - 无缝对接内部基建(如AWS Lambda与Amazon内部**AppStream**框架集成) - 避免第三方依赖冲突(如Meta自研**HHVM**替代PHP解释器) 2. **安全与合规强化** - 内置企业级安全方案(如金融公司自研框架集成硬件加密模块) - 满足监管审计要求(如GDPR数据脱敏机制深度嵌入框架层) --- ### 三、长期战略价值 1. **避免技术绑定风险** 第三方框架变更可能导致: ```mermaid graph LR A[框架重大本升级] --> B[业务系统适配成本] B --> C[旧停止维护风险] C --> D[安全漏洞无法修复] ``` 2. **构建技术护城河** - 自研框架形成技术专利(如IBM**WebSphere**系列) - 框架能力产品化(如阿里**Dubbo**成为Apache顶级项目) --- ### 四、典型案例分析 | 公司 | 自研框架 | 解决痛点 | 性能提升 | |------------|----------------|---------------------------|--------------------| | Google | **gRPC** | 微服务通信效率 | 延迟降低70% | | LinkedIn | **Rest.li** | 超大规模API治理 | QPS提升5倍 | | 字节跳动 | **Kitex** | 微服务资源占用 | CPU消耗减少40% | --- ### 自研框架的代价 1. **高昂的初始成本** $$开发成本 = \sum_{i=1}^{n}(工程师工时 \times 技术复杂度)$$ 2. **社区生态缺失** 需自建文档/培训/支持体系(如百度内部**Eagle框架**培训机制) --- ### 何时应该自研? 决策模型需评估: ```python def should_build_custom_framework(): if (业务规模 > 行业Top 5% or 特殊需求无法用开源方案解决 or 技术战略需要控制权): return True else: return False # 优先选择成熟开源方案 ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值