TE
TechEcho
Home24h TopNewestBestAskShowJobs
GitHubTwitter
Home

TechEcho

A tech news platform built with Next.js, providing global tech news and discussions.

GitHubTwitter

Home

HomeNewestBestAskShowJobs

Resources

HackerNews APIOriginal HackerNewsNext.js

© 2025 TechEcho. All rights reserved.

Give me back my monolith (2019)

331 pointsby winslettabout 3 years ago

42 comments

PaulKeebleabout 3 years ago
Microservices was always a solution to the organisational problem of getting more developers working on a system at once. A lot of people working on one code base over the top of each other often causes problems and issues with ownership. The solution was services independently developed with the trade off cost being increased complexity on a range of things.<p>There is an essay in the mythical man month about Conways law and microservices are very much about a way to use Conways law to achieve scale of development. You likely don&#x27;t need microservice until you hit a scale where the monolith is a real pain point. You can probably cope with a monolith especially with some reasonable design effort up to the 100 developers maybe more with a lot of separation but at some point in the &gt;25 developers range it becomes cheaper and easier to switch to multiple deployed units of software and deal with the increased system complexity and interface designs and the inherent versioning issues it causes.<p>It is easier to start with a monolith, find the right design and then split on the boundaries than it is to make the correct microservices to begin with.
评论 #31329124 未加载
评论 #31329043 未加载
评论 #31329300 未加载
评论 #31329891 未加载
评论 #31329600 未加载
评论 #31332691 未加载
评论 #31335550 未加载
评论 #31328646 未加载
评论 #31329018 未加载
评论 #31329821 未加载
评论 #31331022 未加载
评论 #31328966 未加载
评论 #31332133 未加载
评论 #31329178 未加载
评论 #31328972 未加载
评论 #31331011 未加载
评论 #31331582 未加载
评论 #31332885 未加载
评论 #31330798 未加载
评论 #31329425 未加载
评论 #31329168 未加载
评论 #31335536 未加载
评论 #31328937 未加载
linkddabout 3 years ago
Come to Erlang&#x2F;Elixir (and OTP), you get the best of both worlds:<p><pre><code> - a mono repository - a single codebase for a single system - your micro services are supervisors and gen servers (and a few other processes) in a supervision tree - you decide which erlang node run which apps - your monolith can scale easily thanks to libcluster and horde - ... </code></pre> Also, there is the midpoint between monolith and micro service, and this is called Service Oriented Architecture (SOA), you could have:<p><pre><code> - a DAL (Data Abstraction Layer) service - a Business Logic service (talking to the DAL) - an API (talking to the Business Logic service) - a Frontend (talking to the API) </code></pre> Your API (or gateway, or whatever you want to call it) can serve as glue for third-party services (like Stripe, or anything unrelated to your business).<p>Microservices are a solution for an organizational problem, not a tech one. You need multiple teams to work on the same system without blocking each others. This is a solution for huge corporations, not your 2 pizzas team startup.
评论 #31328574 未加载
评论 #31328735 未加载
评论 #31336977 未加载
评论 #31329212 未加载
评论 #31328593 未加载
phendrenad2about 3 years ago
The monolith vs microservice debate always seemed so misguided to me. It seems exactly like vim vs emacs. Or ruby vs python. The arguments are always the same.<p>* &quot;In vim I can do this in 3 keystrokes, in emacs it takes 5!&quot; (where &quot;this&quot; is some vim-idiomatic thing you&#x27;d never do in emacs).<p>* &quot;Ruby leads to bad programs, I have inherited a legacy ruby codebase and you wouldn&#x27;t believe what they did...&quot; &#x2F; &quot;Python leads to bad programs, I have inherited a legacy python codebase and you wouldn&#x27;t believe what they did...&quot;<p>* My team took a python&#x2F;ruby app and rewrote it ruby&#x2F;python, and now it&#x27;s 99% faster and our productivity is way higher!<p>What I&#x27;m hinting at is this: You can write a bad or good microservice or monolith. The rules are different. You&#x27;ll have different frustrations and tradeoffs. You&#x27;ll have to play to the architecture&#x27;s strengths and avoid it&#x27;s weaknesses. You&#x27;ll NEED institutional standards to keep people from doing the wrong thing for the architecture model and making a mess.
评论 #31335335 未加载
评论 #31336083 未加载
roflyearabout 3 years ago
I think the biggest pain point for me is the almost constantly-changing definition of &quot;microservices&quot; - at work, whenever someone says &quot;microservices&quot; they really mean a services architecture. I can largely get behind that. Because when you say services architecture, to me anyway, that doesn&#x27;t mean everything has to be a &quot;service&quot;. Some stuff can be on the same machine if you do not have a firm point of separation between the services. Maybe they will share some code eventually... ok... put them together, who cares?<p>Last time I asked our ops guy to define microservices for me, he couldn&#x27;t - instead he told me to read a 400 page book by some popular microservices preacher (who of course makes a lot of money by consulting for companies looking to use or currently using microservices ;))<p>If you cannot explain the general concepts to me, maybe you do not know what it is, and I think that is a big part of the problem.
评论 #31328750 未加载
评论 #31329092 未加载
评论 #31328484 未加载
评论 #31329199 未加载
fennecfoxenabout 3 years ago
Okay, Craig, you can have your monolith back when you can get your engineers to care <i>in the slightest</i> about keeping the codebase organized instead of turning it into a big ball of mud. I&#x27;m talking encapsulation. I&#x27;m talking well-defined interfaces that aren&#x27;t glued to specific implementations. I&#x27;m talking some sort of dependency inversion, dependency injection, service locator patterns, any of that. I&#x27;m talking real use of the single-responsibility principle, all that software-engineery stuff that everyone <i>ignores</i>. Because I understand what you&#x27;re getting at 110%, but by and large, all this stuff doesn&#x27;t happen otherwise.<p>Until then you&#x27;re going to have these things forced on you by your local Architect, forced on you by running a bunch of separate processes on separate containers with DNS as the cluster&#x27;s service-lookup framework.
评论 #31332086 未加载
评论 #31332899 未加载
asimabout 3 years ago
It&#x27;s just about need. Most people don&#x27;t need microservices. Let me repeat that. Most people don&#x27;t need microservices. It&#x27;s only relevant at scale. The scale I&#x27;m talking about is organizational scale and then potentially technical scale but it&#x27;s mostly about solving people problems by enabling independent development of products and features.<p>Developers are their own worst enemy. They love shiny buzzwords and using unnecessary tools and concepts just to say they did. Conceptually you can&#x27;t blame architecture patterns, that makes no sense. Blame those who choose to adopt patterns for the wrong reasons.
评论 #31334535 未加载
rr808about 3 years ago
Single RDMS database + stateless middle tier is still best solution for 99% of applications out there.
评论 #31328734 未加载
评论 #31329599 未加载
评论 #31334519 未加载
brightballabout 3 years ago
This is one of the big reasons I got into Elixir.<p>The way that you&#x27;re encouraged to architect your code makes it really easy to separate a specific piece(s) if you need to. The functional, no-side-effects approach combined with Elixir&#x27;s ability to easily communicate between nodes means that if I need to separate a particular set of functionality to certain servers...it&#x27;s just moving things around.<p>If I take a function call_me(arg1, arg2) and it returns a result without side effects, it&#x27;s no different for me to say call_me(node, arg1, arg2) because it&#x27;s still going to give me the same result just from a different server.<p>This flexibility means that I can comfortably built a monolith and not have to worry about having to untangle it later if I need to. I love it. It gives me long term peace of mind with short term productivity.
ascendantlogicabout 3 years ago
I wonder if anyone who wants to bring back the monolith has ever worked on a true large monolithic codebase? Not something that&#x27;s like 5-10k lines of code excluding frameworks, but monsters that are 100k+. Where test suites take an hour to run end-to-end and you&#x27;ve got 50+ devs all issuing pull requests in the same codebase? I feel like webapps usually have a sweet spot in terms of size and logical reach. This whiplash hype cycle of &quot;X&quot; and &quot;anti-X&quot; just exposes the ever lingering problem of letting blog posts on HN determine your architecture decisions.
评论 #31331071 未加载
评论 #31331701 未加载
评论 #31330840 未加载
评论 #31329063 未加载
评论 #31329496 未加载
评论 #31330658 未加载
评论 #31329196 未加载
评论 #31328969 未加载
评论 #31329237 未加载
评论 #31329590 未加载
WerBnabout 3 years ago
I relate so much with this article I&#x27;ve had a previous experience with a backend monolith repo, and these days I have to deal with a backend that has 20+ repos. It is hell. Duplicated code, duplicated logic, duplicated tests, duplicated settings, an hell to introduce newbies to the architecture, async calls to external basic APIs that could&#x27;ve been just simple method calls.<p>I think that the one major disadvantage of having a big monorepo, is that with those multiple entry points, you might end up with a bunch of unused dependencies. But even that is manageable I think: you can have different package dependencies definitions whilst using the same codebase.<p>I&#x27;ve always worked with small teams (max up to 5 or 6 developers) and that&#x27;s another point in favor of monorepos. I understand that big companies might want to have different teams working on different repos, for organisation reasons.
评论 #31329654 未加载
dfeeabout 3 years ago
On the NodeJS &#x2F; React ecosystem - no one really wants you to do monoliths.<p>NextJS, for example, doesn’t let you manage service lifecycle methods (unless you write a custom server - which they explicitly warn you against). NextJS wants to be special, that’s dumb and it sucks (well, in the context of using it to drive your SaaS platform, it’s pretty smart).<p>Remix, for example, wants to control your client&#x2F;server API calls, so you’re hard pressed to use other tools like GraphQL, and incur the risk for growing into microservices if you need it. Same story as NextJS about being special and probably driving SaaS platform sales.<p>Amazon just makes you manage an alphabet soup worth of products, which are all pretty expensive - unless you want to just lambda it… meaning custom runtimes and … back to microservices.<p>Point: microservices aren’t just driven by your org anymore, they’re pushed by vendors.
评论 #31330326 未加载
评论 #31329536 未加载
评论 #31329561 未加载
评论 #31330071 未加载
fulafelabout 3 years ago
This is dated 2019-03-13 and it says &quot;It feels like we’re starting to pass the peak of the hype cycle of microservices&quot; but wasn&#x27;t the peak already earlier? Looking at HN posts - <a href="https:&#x2F;&#x2F;hn.algolia.com&#x2F;?q=microservices" rel="nofollow">https:&#x2F;&#x2F;hn.algolia.com&#x2F;?q=microservices</a> - it looks like a lot of the high voted posts against microservices were 4-7 years ago.<p>Highest scoring one (2018): <a href="https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=17499137" rel="nofollow">https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=17499137</a>
评论 #31329062 未加载
Ensorceledabout 3 years ago
I remember a talk a few years ago where the CTO of a local startup was gushing about microservices and how productive they made his team. Sounded like an tech evangelist who had drank their own koolaid.<p>Then one of the &quot;questions&quot; in the Q&amp;A was a pretty aggressive attack based on how unproductive the skeptics company had been to date and how they were on the verge of failing.<p>The speaker asked how many development teams they had and what was the size of their DevOps&#x2F;Tooling team(s). When the skeptic admitted they only had a few developers, the speaker recommended they IMMEDIATELY pivot to Django&#x2F;Rails&#x2F;Node.js&#x2F;.Net; &quot;whatever you are most comfortable with&quot;. And then said &quot;Why are you still standing there? You need to pivot tomorrow morning.&quot;<p>I think of those two questions every time I read or consider microservices. &quot;How many teams. How big is your DevOps&#x2F;Tooling team.&quot;
atx42about 3 years ago
Why do we organize by shape, and not by function in our monoliths? We put all our controllers in a package, all our DB accessors in another package, all our &quot;data objects&quot; in another package. Even in OO languages like Java where we have package accessors that never get used because we layout our code such that package scope can never be used. We instead layout the code according to &quot;shape&quot;.<p>When figuring out what to spin-off as a microservice, we do this by functionality. Why not just make it easier in the monolith and organize by functionality instead? Let&#x27;s act like 4yr olds, not 3yr olds: <a href="https:&#x2F;&#x2F;pubmed.ncbi.nlm.nih.gov&#x2F;12090481&#x2F;" rel="nofollow">https:&#x2F;&#x2F;pubmed.ncbi.nlm.nih.gov&#x2F;12090481&#x2F;</a>
评论 #31330825 未加载
kabdibabout 3 years ago
One wrinkle I liked was to build a monolith, distributing the same bits everywhere, and to configure the actual services to start on an instance-by-instance basis. This simplifies distribution (e.g., &quot;unpack this single zip file, it&#x27;s got everything&quot;) and you can rapidly change what is running and where with a command-and-control system of your choice.<p>I can&#x27;t imagine having different build products and deployment stories for every service type, nor can I imagine institutionalized version skew of more than a couple of weeks.<p>This probably doesn&#x27;t scale to large teams, but it let a small team work pretty effectively with thousands of microservices.
评论 #31331489 未加载
staticassertionabout 3 years ago
&gt; Setup went from intro chem to quantum mechanics<p>Doesn&#x27;t really seem fair. On the one hand you might need to do a bit of work so that you can say `docker-compose up` or `nomad up` or whatever, but at the same time there are plenty of issues with running binaries&#x2F;databases directly on a laptop - version skew, for instance.<p>&gt; So long for understanding our systems<p>This is fundamental to all asynchronous systems. You don&#x27;t have backtraces anymore. If your service has concurrency primitives you probably already have to solve this problem with tracing, microservices just give you another asynchronous primitive.<p>&gt; If we can’t debug them, maybe we can test them<p>Bringing up your entire application is what you&#x27;d have to do in a monolith as well, I don&#x27;t understand this criticism. Also, &quot;teaching&quot; your CI to do this is 0 additional work - it&#x27;s gonna be another &quot;docker-compose up&quot; or whatever, generally speaking.<p>Our microservice codebase runs on laptops just as it runs in the cloud. It&#x27;s pretty nice.<p>With regards to &quot;That is probably a bit too much effort so we’re just going to test each piece in isolation&quot; - again, this is the same thing with your monolith. You&#x27;ll just do this at the module level.<p>This is really a &quot;right tool for the job&quot; situation. And that&#x27;s hard for people to understand, since oftentimes you don&#x27;t know what you&#x27;re building upfront.
Wherecombinatorabout 3 years ago
As a junior engineer (only working 6 months), the K8s side of things has been my biggest barrier for learning. On top of having to learn about software engineering practices, I’ve had to learn helm files, deployments, services etc. It was&#x2F;is very overwhelming. I know I’m new and naive but it seems needlessly complicated and it’ll be another few rounds of abstraction beyond K8s before people are happy with it.
评论 #31347011 未加载
评论 #31328823 未加载
unnouinceputabout 3 years ago
Both styles have their places. I&#x27;ve done migrations of monolith to microservices and I&#x27;ve done microservices to monolith. In the end is about what&#x27;s best for the project&#x2F;client, not the purism of &quot;I only do xxx or only yyy&quot;. If you&#x27;re one of those developers then don&#x27;t call yourself &quot;senior&quot;, you&#x27;re still in the mindset of a junior.
评论 #31328491 未加载
lxeabout 3 years ago
Hey, the longer it takes to understand, iterate, and work on a particular architecture, the more money you&#x27;re making per task completed as an engineer... so the more ridiculous the architecture with which you&#x27;re working, the slower your work is, the longer it takes to get done, the longer you stay employed!
jeffwaskabout 3 years ago
In my experience, the project to break apart a monolith often happens without a clear definition of what problems we trying to solve by breaking apart the monolith. Which ends up creating a raft of new problems plus the old problems and a bunch of sticky left overs that are perpetually &quot;going away soon&quot;.<p>And since you have no clear definition of why and what outcomes you expect, you also get massive scope creep in the middle of all this. Then you run into all the things no one planned for because there was no plan like how do we serve business functions like BI from our 30 new micro-service databases.
estabout 3 years ago
My theory: if you can easily swap local-procedure-calls with remote-procedure-calls, then it&#x27;s a well-designed system, monolith or not.
评论 #31329314 未加载
评论 #31328770 未加载
shroompastaabout 3 years ago
If you&#x27;re dealing with any complex architecture, there will be portions of your service that will be hit more than others.<p>I&#x27;m currently building a backend in which will need real time capabilities and also standard restful http services.<p>Separating the real time service which will need a significant amount of performance more than the restful services will help me better scale.<p>Furthermore, the entire backend is written in python, because that is what I&#x27;m currently capable of at the moment, but in the future, migrating the real time service to Go will be heavily favorable - by separating it into its own service allows for that rewrite to happen at ease.<p>Now, there are many cases where building microservices are an overkill, but this isn&#x27;t a one size fits all approach as the author would suggest, and I think we should all be tired of hearing a this or that type of article.
mrlobaabout 3 years ago
I&#x27;ve had great success with having a monolithic code base with multiple entry points. Each entry point is sort of a micro service (or just service), but it can access the same db as the other services (if it makes sense), use the same types, and crucially, it can easily be integration tested with the other entry points. With full debug support.<p>Such a &quot;monolith&quot; need not be the only one in the company. One per high level module or team works well.<p>I guess my point is, it doesn&#x27;t have to be either giant monolith or tiny micro services in separate repos. There&#x27;s everything in between as well.
alaricusabout 3 years ago
Microservices are a great idea, if you don&#x27;t religiously try to make everything a microservice.<p>I feel more inefficiencies were caused by forcing a microservice solution to every problem; than by big monoliths.
nixpulvisabout 3 years ago
Conway&#x27;s Law does not demand Microservices, it describes abstraction barriers. Forcing conflicts to be resolved in VCS as opposed to at runtime is a feature of monoliths, not a bug.
gmmeyerabout 3 years ago
IMO you should never create a new service unless it serves an engineer reason instead of an organizational one. There&#x27;s a lot of tools to help out monoliths, and a lot of ways to make it easier to shard the monolith as well.<p>Some services need it, like a backend intake platform of some sort that needs to have radically different performance characteristics than a user facing frontend. But for most services it just does not make a lot of sense to do this.
kgeistabout 3 years ago
It also depends on what kind of monolith we&#x27;re talking about.<p>We&#x27;ve found that &quot;moduliths&quot; (modular monoliths split into clearly defined bounded contexts with public APIs) work as well as microservices for scaling development: each team is responsible for their own module, there are very few conflicts, there&#x27;s no spaghetti because we have architectural reviews whenever a module wishes to cross the &quot;module barrier&quot; and call into another module etc. (i.e. introducing a new dependency). You can spin up as many modulith instances as you wish as well.<p>The problem is that our modulith is written in PHP using a very popular enterprisey framework. PHP is based on the paradigm of spinning up a new process per request (php-fpm can recycle them but still), so every request ends up reinitializing the whole framework every time: its entire dependency injection tree. Every new module increases response times linearly, it doesn&#x27;t scale. Another issue is that the single DB (common for monoliths) becomes the bottleneck, as all modules&#x2F;contexts go through it.<p>Our PHP modulith is very costly in terms of runtime. A similar request into a microservice is usually 20-50 times faster because it&#x27;s written in Go and manages its own DB. I think if our monolith was written in Go or Java from the very beginning we would have less impressive results after switching to microservices. Stuff rewritten from scratch is also usually faster than tons of old accumulated cruft.<p>Deployment&#x2F;compilation is much faster now, the old monolith also used to have a lot of JS&#x2F;CSS processing, PHP linters during build etc. so a tiny change to a module would trigger full recompilation of all modules running for 30-40 minutes. Each microservice is a separate deployment however, so a change to it only takes 1-2 minutes to deploy&#x2F;release.<p>My point is that when people are talking about monoliths vs microservices they are often comparing dinosaurs written 10-15 years ago (PHP, old frameworks with bad design decisions, tons of accumulated spaghetti) to modern, more lightweight languages&#x2F;tooling (for example, Go, k8s etc)<p>I think a &quot;modern modulith&quot; has its right to exist and is a viable competitor to microservices, provided they use more lightweight frameworks&#x2F;tools, use paradigms such as modules and CQRS, and if somehow they allow smart, incremental deployments.
duxupabout 3 years ago
I want to know how many people who are using &quot;microservices&quot; are actually using &quot;microservices&quot; with separate databases for each service, separate teams and so on...?<p>If you asked my boss, we&#x27;re using microservices. But really we&#x27;re just taking common tasks and breaking them out to their own service. Now that&#x27;s kinda like microservices, and it is very handy ... but it is not the full definition that I know of.
评论 #31328730 未加载
itsmemattchungabout 3 years ago
These days, I try to not to prematurely optimize by setting up micro services from day 1. I find starting with a monolith, with an eye towards micro services, works well for most projects and as patterns and abstractions emerge, slowly design and provision micro services.
benreesmanabout 3 years ago
The pros have an RPC when a program that needs to timing on one SKU needs something from a program that needs a different SKU. Otherwise, you don’t do the RPC.<p>Micro service or monolith? Hmm, I’d like F1 car or tank. If it fucking matters, you know which one you need.
dangabout 3 years ago
Discussed at the time:<p><i>Give Me Back My Monolith</i> - <a href="https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=19382765" rel="nofollow">https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=19382765</a> - March 2019 (411 comments)
tonymetabout 3 years ago
The lack of a stacktrace alone should be a hard blocker to microservice migration.<p>After that, the amount of cpu (i.e. dollars) and wall time wasted on encode-decode.<p>Anyone who does a microservice migration is not accounting for the above two costs.
评论 #31328755 未加载
Havocabout 3 years ago
Right tool for the job should have been the message all along.
tonymetabout 3 years ago
engineers don&#x27;t want to admit it, but microservices are a form of busywork. What used to be a few lines of native API code now require : RPC API boilerplate CRUD code, a build, a deployment, CI , dependency management etc.<p>Not to mention the additional complexity – now every &quot;service&quot; needs an LB.<p>You&#x27;ve converted a simple 1 person job into multiple days for many people.<p>microservices are a scam.
fmakunboundabout 3 years ago
At a company I work at currently, they have microservices, but they moved the monolith into the side-car. Best of both worlds.
nomoreusernamesabout 3 years ago
this is about scale. dont make things in a certain way because someone tells you to do it. collect metrics and use science to figure out what is best for you and your team today. engineers are building and using the things have to be reasonably happy with their tools or you get teenage behaviour.
fictionfutureabout 3 years ago
To be fair, most micro service setups and tutorials have been overly complicated; however, let’s agree that distributed workloads and architecture are superior in a number of ways.<p>Generally, when people discuss going back to the “monolith” they just haven’t found the right distributed architecture.
评论 #31328478 未加载
ChicagoDaveabout 3 years ago
If you have a simple crud system, a monolith I’d likely preferable. If your business domain has a lot of complexity, which you can discover through Event Storming, then breaking up the monolith will provide clear development criteria and much simpler maintenance.
cosmiccatnapabout 3 years ago
No<p>As someone who has spent the last 3 years of their life maintaining and scaling one this is madness.
kristianpaulabout 3 years ago
Then boring technologies are no that bad after all, imho at the end it’s about facing changes quickly and if you have the tools and systems to do that then good !
revskillabout 3 years ago
This is bullshit article, sorry for bad words, but it&#x27;s hard for me to keep using monothlich for any reason. Monothlich is the way to hell. It kills developer&#x27;s productivity and team velocity by margin cost.
light_hue_1about 3 years ago
If you use the wrong tools, everything looks like a disaster.<p>Microservices on AWS with lambda+dynamo+auroa+api-gateway work very well. There&#x27;s built in transparency. There is logging. You can set everything up with terraform.<p>Terraform makes the setup trivial. Compared to monoliths that I&#x27;ve seen that involve a lot of brittle manual steps, it&#x27;s not even a competition. AWS Lambda with xray and other logging tools makes tracking down errors trivial. I have yet to see a monolith with anything comparable.<p>&quot;Oh but I get a stack trace in my monolith&quot; is false advertisement. How useful is that stack trace when the stack is corrupted? Or when memory is corrupted because one line in another part of the monolith has an error that slowly screwed up some datastructure in another part of the monolith? I&#x27;ll take Lambdas that are all short, totally isolated, and easy to understand, any day. Debugging and understanding is much harder with a monolith.<p>And yes. To test, you need to bring up the entire working application. Just like you need to bring up the monolith. Oh? You mean, most people who test monolith don&#x27;t bring them up, they just test some mocked version of some module in isolation? Well, they&#x27;re probably testing the testing framework itself more than the monolith. With localstack you can bring up the entire AWS setup locally, automatically, run component and end to end tests. It&#x27;s far more testable than a monolith. And far more obvious when an interaction is not tested.<p>Monoliths are dead. Stop writing them. And start learning modern tooling.
评论 #31332946 未加载
评论 #31329639 未加载